Merge branch 'dev/design' into integration_new_controller
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
module tb_top;
|
module tb_top;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// ���������
|
// Параметры
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
parameter string ZERO_LEVEL_PARAM = "logic"; // "logic" VS "true"
|
parameter string ZERO_LEVEL_PARAM = "logic"; // "logic" VS "true"
|
||||||
parameter VERBOSE = 1;
|
parameter VERBOSE = 1;
|
||||||
@@ -22,14 +22,14 @@ module tb_top;
|
|||||||
localparam CLOCK_DEVIATION = 3; // Maximum clock deviation of pulse stats
|
localparam CLOCK_DEVIATION = 3; // Maximum clock deviation of pulse stats
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// �������� ������� � �����
|
// Тактовые сигналы и сброс
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic clk_dac;
|
logic clk_dac;
|
||||||
logic rst_dac;
|
logic rst_dac;
|
||||||
logic clk_adc;
|
logic clk_adc;
|
||||||
logic rst_adc;
|
logic rst_adc;
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// ���������� � ������
|
// Управление и конфиг
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic dac_start;
|
logic dac_start;
|
||||||
logic [31:0] pulse_width;
|
logic [31:0] pulse_width;
|
||||||
@@ -38,11 +38,11 @@ module tb_top;
|
|||||||
logic [15:0] pulse_num;
|
logic [15:0] pulse_num;
|
||||||
logic [31:0] smp_num;
|
logic [31:0] smp_num;
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// �����
|
// Входы
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
reg out_of_range;
|
reg out_of_range;
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// ������
|
// Выходы
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
||||||
wire m_axis_tvalid;
|
wire m_axis_tvalid;
|
||||||
@@ -72,7 +72,7 @@ module tb_top;
|
|||||||
.out_of_range(out_of_range)
|
.out_of_range(out_of_range)
|
||||||
);
|
);
|
||||||
|
|
||||||
// �������� �������
|
// Тактовые сигналы
|
||||||
initial begin
|
initial begin
|
||||||
clk_adc = 0;
|
clk_adc = 0;
|
||||||
forever #(CLK_ADC_PERIOD/2) clk_adc = ~clk_adc;
|
forever #(CLK_ADC_PERIOD/2) clk_adc = ~clk_adc;
|
||||||
@@ -82,17 +82,17 @@ module tb_top;
|
|||||||
forever #(CLK_DAC_PERIOD/2) clk_dac = ~clk_dac;
|
forever #(CLK_DAC_PERIOD/2) clk_dac = ~clk_dac;
|
||||||
end
|
end
|
||||||
|
|
||||||
// === ����� ��� ������������ ===
|
// === Таски для тестирования ===
|
||||||
// ������� ������
|
// Функция модуля
|
||||||
function automatic real fabs(real val);
|
function automatic real fabs(real val);
|
||||||
return (val < 0.0) ? -val : val;
|
return (val < 0.0) ? -val : val;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
`define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
`define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
|
||||||
// ����� ������ DAC DUT
|
// Таска сброса DAC DUT
|
||||||
task automatic reset_dut_dac(
|
task automatic reset_dut_dac(
|
||||||
input int rst_duration // ������� ������ ������� �����
|
input int rst_duration // сколько тактов держать сброс
|
||||||
);
|
);
|
||||||
@(negedge clk_dac);
|
@(negedge clk_dac);
|
||||||
rst_dac <= 1;
|
rst_dac <= 1;
|
||||||
@@ -100,9 +100,9 @@ module tb_top;
|
|||||||
rst_dac <= 0;
|
rst_dac <= 0;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
// ����� ������ ADC DUT
|
// Таска сброса ADC DUT
|
||||||
task automatic reset_dut_adc(
|
task automatic reset_dut_adc(
|
||||||
input int rst_duration // ������� ������ ������� �����
|
input int rst_duration // сколько тактов держать сброс
|
||||||
);
|
);
|
||||||
@(negedge clk_adc);
|
@(negedge clk_adc);
|
||||||
rst_adc <= 1;
|
rst_adc <= 1;
|
||||||
@@ -110,9 +110,9 @@ module tb_top;
|
|||||||
rst_adc <= 0;
|
rst_adc <= 0;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
// ����� ������� DUT
|
// Таска запуска DUT
|
||||||
task automatic start_dut(
|
task automatic start_dut(
|
||||||
input int start_duration // ������� ������ ������� �������
|
input int start_duration // сколько тактов держать импульс
|
||||||
);
|
);
|
||||||
@(negedge clk_dac); // to make signal stable
|
@(negedge clk_dac); // to make signal stable
|
||||||
dac_start <= 1;
|
dac_start <= 1;
|
||||||
@@ -120,15 +120,15 @@ module tb_top;
|
|||||||
dac_start <= 0;
|
dac_start <= 0;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
// ����� ������������ DUT
|
// Таска конфигурации DUT
|
||||||
task automatic set_config(
|
task automatic set_config(
|
||||||
input logic [31:0] w, // ������ ��������
|
input logic [31:0] w, // ширина импульса
|
||||||
input logic [31:0] p, // ������ ��������
|
input logic [31:0] p, // период импульса
|
||||||
input logic [15:0] n, // ���������� ���������
|
input logic [15:0] n, // количество импульсов
|
||||||
input logic [DAC_DATA_WIDTH-1:0] h, // ������ ��������
|
input logic [DAC_DATA_WIDTH-1:0] h, // высота импульса
|
||||||
input logic [31:0] sn // ����� �������
|
input logic [31:0] sn // число сэмплов
|
||||||
);
|
);
|
||||||
// ������ ���������������� ��������
|
// Задаем конфигурационные регистры
|
||||||
pulse_width <= w;
|
pulse_width <= w;
|
||||||
pulse_period <= p;
|
pulse_period <= p;
|
||||||
pulse_num <= n;
|
pulse_num <= n;
|
||||||
@@ -136,7 +136,7 @@ module tb_top;
|
|||||||
smp_num <= sn;
|
smp_num <= sn;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
// �������� ����� �������� DUT
|
// Основная таска проверки DUT
|
||||||
task automatic run_test_case(
|
task automatic run_test_case(
|
||||||
input int pulse_width,
|
input int pulse_width,
|
||||||
input int pulse_period,
|
input int pulse_period,
|
||||||
@@ -192,7 +192,7 @@ module tb_top;
|
|||||||
start_dut(start_hold_time);
|
start_dut(start_hold_time);
|
||||||
begin
|
begin
|
||||||
@(posedge clk_dac);
|
@(posedge clk_dac);
|
||||||
// ����� ������ �������������
|
// старт первой синхронизации
|
||||||
sync_start_time = $realtime;
|
sync_start_time = $realtime;
|
||||||
end
|
end
|
||||||
join_none
|
join_none
|
||||||
@@ -209,28 +209,27 @@ module tb_top;
|
|||||||
if (VERBOSE >= 3) begin
|
if (VERBOSE >= 3) begin
|
||||||
$display("[TB] -run_test_case- Found valid pulse response data positive front");
|
$display("[TB] -run_test_case- Found valid pulse response data positive front");
|
||||||
end
|
end
|
||||||
// ����� �����. ���������� �������������
|
// Старт цикла. Завершение синхронизации
|
||||||
sync_time_stats.push_back($realtime - sync_start_time);
|
sync_time_stats.push_back($realtime - sync_start_time);
|
||||||
pulse_start_time = $realtime;
|
pulse_start_time = $realtime;
|
||||||
|
|
||||||
fork
|
fork
|
||||||
// ����� ����� ������� ��� ��������� ��������� � �������������� ���������� ��� ������ ����������� ���������� ��������
|
// Поток будет запущен для ненулевых импульсов и гарантированно завершится как только зафиксирует статистику импульса
|
||||||
// ������ ��������
|
// Начало импульса
|
||||||
if (pulse_height != ZERO_LEVEL && pulse_width != 0) begin
|
if (pulse_height != ZERO_LEVEL && pulse_width != 0) begin
|
||||||
if (VERBOSE >= 4) begin
|
if (VERBOSE >= 4) begin
|
||||||
$display("[TB] -run_test_case- Wait until pulse become high");
|
$display("[TB] -run_test_case- Wait until pulse become high");
|
||||||
end
|
end
|
||||||
wait(m_axis_tdata != ZERO_LEVEL);
|
wait(m_axis_tdata != ZERO_LEVEL);
|
||||||
// ����������� ������ ��������. ����������� �������� ������
|
// Фактическое начало импульса. Поступление высокого уровня
|
||||||
pulse_update_val_time = $realtime;
|
pulse_update_val_time = $realtime;
|
||||||
pulse_delay_time_stats.push_back(pulse_update_val_time - pulse_start_time);
|
pulse_delay_time_stats.push_back(pulse_update_val_time - pulse_start_time);
|
||||||
|
|
||||||
// �������� ��� ������ �������� ������� � ��������. �.�. OTR != 0 ������ �� �������� ������ ��������, �� �� ����� ��������� ����� ������.
|
// Проверим что высота импульса совпала с заданной. Т.к. OTR != 0 влияет на выходные данные сэмплера, то не будем проверять такие случаи.
|
||||||
@(posedge clk_adc);
|
@(posedge clk_adc);
|
||||||
#1.5; // �������� ���������� ���������� ���������
|
#1.5; // Ожидание завершения переходных процессов
|
||||||
// todo fix
|
// Будем считать что из-за OTR данные изменились (по условию OTR + MSB), проверка пропускается, т.к. сложно понять точное значение OTR в момент обработки данных от tdata
|
||||||
// ����� ������� ��� ��-�� OTR ������ ���������� (�� ������� OTR + MSB), �������� ������������, �.�. ������ ������ ������ �������� OTR � ������ ��������� ������ �� tdata
|
if (m_axis_tdata != (pulse_height >> 2) && (randomize_out_of_range || out_of_range_val)) begin
|
||||||
if (m_axis_tdata != (pulse_height >> 2) && !(randomize_out_of_range || out_of_range_val)) begin
|
|
||||||
$display("[ERROR] -run_test_case- Wrong pulse height: %d. Must be: %d", m_axis_tdata, pulse_height >> 2);
|
$display("[ERROR] -run_test_case- Wrong pulse height: %d. Must be: %d", m_axis_tdata, pulse_height >> 2);
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
@@ -241,14 +240,14 @@ module tb_top;
|
|||||||
wait(m_axis_tdata == ZERO_LEVEL);
|
wait(m_axis_tdata == ZERO_LEVEL);
|
||||||
pulse_width_time_stats.push_back($realtime - pulse_update_val_time);
|
pulse_width_time_stats.push_back($realtime - pulse_update_val_time);
|
||||||
end
|
end
|
||||||
// ����� ��������
|
// Конец импульса
|
||||||
join_none
|
join_none
|
||||||
|
|
||||||
@(negedge m_axis_tvalid);
|
@(negedge m_axis_tvalid);
|
||||||
if (VERBOSE >= 3) begin
|
if (VERBOSE >= 3) begin
|
||||||
$display("[TB] -run_test_case- Found valid pulse response data negative front");
|
$display("[TB] -run_test_case- Found valid pulse response data negative front");
|
||||||
end
|
end
|
||||||
// ���������� �����. ����� �������������
|
// Завершение цикла. Старт синхронизации
|
||||||
pulse_period_time_stats.push_back($realtime - pulse_start_time);
|
pulse_period_time_stats.push_back($realtime - pulse_start_time);
|
||||||
sync_start_time = $realtime;
|
sync_start_time = $realtime;
|
||||||
end
|
end
|
||||||
@@ -257,7 +256,7 @@ module tb_top;
|
|||||||
$display("[TB] -run_test_case- Stop pulse generation");
|
$display("[TB] -run_test_case- Stop pulse generation");
|
||||||
end
|
end
|
||||||
|
|
||||||
fork // �������� � ��������� �� ������ �����
|
fork // Проверка с таймаутом на лишние циклы
|
||||||
@(posedge m_axis_tvalid);
|
@(posedge m_axis_tvalid);
|
||||||
repeat(30) @(posedge clk_adc);
|
repeat(30) @(posedge clk_adc);
|
||||||
join_any
|
join_any
|
||||||
@@ -278,8 +277,7 @@ module tb_top;
|
|||||||
end
|
end
|
||||||
out_of_range = 0;
|
out_of_range = 0;
|
||||||
|
|
||||||
// �������� �� ����������. ������� ������� ��������
|
// Проверка по статистике. Подсчет средних значений
|
||||||
// todo randomize_out_of_range || out_of_range_val
|
|
||||||
if (pulse_delay_time_stats.size() != pulse_num && pulse_height != ZERO_LEVEL && pulse_width != 0 && !(randomize_out_of_range || out_of_range_val)) begin // Detected with pulse level. Skip if pulse level undetectable
|
if (pulse_delay_time_stats.size() != pulse_num && pulse_height != ZERO_LEVEL && pulse_width != 0 && !(randomize_out_of_range || out_of_range_val)) begin // Detected with pulse level. Skip if pulse level undetectable
|
||||||
$display("[ERROR] -run_test_case- Size of pulse_delay_time_stats samples not equal to pulse_num: %d VS %d", pulse_delay_time_stats.size(), pulse_num);
|
$display("[ERROR] -run_test_case- Size of pulse_delay_time_stats samples not equal to pulse_num: %d VS %d", pulse_delay_time_stats.size(), pulse_num);
|
||||||
$finish;
|
$finish;
|
||||||
@@ -325,7 +323,7 @@ module tb_top;
|
|||||||
$display("[ERROR] -run_test_case- avearge_pulse_delay too big: %0.3f", avearge_pulse_delay);
|
$display("[ERROR] -run_test_case- avearge_pulse_delay too big: %0.3f", avearge_pulse_delay);
|
||||||
error_flag = 1;
|
error_flag = 1;
|
||||||
end
|
end
|
||||||
if (fabs(average_pulse_width - pulse_width * CLK_DAC_PERIOD * (pulse_height != ZERO_LEVEL)) > CLOCK_DEVIATION * CLK_ADC_PERIOD && sample_num * CLK_ADC_PERIOD >= pulse_width * CLK_DAC_PERIOD && !(randomize_out_of_range || out_of_range_val)) begin
|
if (fabs(average_pulse_width - pulse_width * CLK_DAC_PERIOD * (pulse_height != ZERO_LEVEL)) > CLOCK_DEVIATION * CLK_ADC_PERIOD && sample_num * CLK_ADC_PERIOD >= pulse_width * CLK_DAC_PERIOD) begin
|
||||||
$display("[ERROR] -run_test_case- average_pulse_width deviates from choosen pulse_width. Deviation: %0.3f > %0.3f ns", fabs(average_pulse_width - pulse_width * CLK_DAC_PERIOD), CLOCK_DEVIATION * CLK_ADC_PERIOD);
|
$display("[ERROR] -run_test_case- average_pulse_width deviates from choosen pulse_width. Deviation: %0.3f > %0.3f ns", fabs(average_pulse_width - pulse_width * CLK_DAC_PERIOD), CLOCK_DEVIATION * CLK_ADC_PERIOD);
|
||||||
error_flag = 1;
|
error_flag = 1;
|
||||||
end
|
end
|
||||||
@@ -345,13 +343,13 @@ module tb_top;
|
|||||||
$display("[TB] -run_test_case- Passed checks");
|
$display("[TB] -run_test_case- Passed checks");
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
// �����
|
// Таска
|
||||||
|
|
||||||
// --- �������� ������� ����??�����??� ---
|
// --- ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ ---
|
||||||
initial begin
|
initial begin
|
||||||
$display("[TB] Tests start");
|
$display("[TB] Tests start");
|
||||||
|
|
||||||
// ??������������
|
// Инициализация
|
||||||
dac_start = 0;
|
dac_start = 0;
|
||||||
pulse_width = 0;
|
pulse_width = 0;
|
||||||
pulse_period = 0;
|
pulse_period = 0;
|
||||||
@@ -477,12 +475,12 @@ module tb_top;
|
|||||||
.randomize_out_of_range(0)
|
.randomize_out_of_range(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
// �������� ��������� ������ ����������. �.�. ����� ������ ������������ �� tvalid ��������, � �� ����������� ������ ������. ����� �� ���������� start ��������� �����, ����
|
// Ожидание окончания работы генератора. Т.к. конец работы определяется по tvalid сэмплера, а он завершается сильно раньше. Чтобы не пропустить start следующей таски, ждем
|
||||||
wait(dut.generator_inst.enable == 0);
|
wait(dut.generator_inst.enable == 0);
|
||||||
#50;
|
#50;
|
||||||
|
|
||||||
$display("[TB] Test 2. Edge cases. Sample num == 0. (6/7)");
|
$display("[TB] Test 2. Edge cases. Sample num == 0. (6/7)");
|
||||||
// �������� � ������ �������, �.�. run_test_case ����������� ���� pulse num ������. �������� ����� ������������ �� ���������� �������. �� �� ������ ���� ��� sample num = 0
|
// Запустим в работу вручную, т.к. run_test_case обязательно ждет pulse num циклов. Детекция цикла производится по активности сэплера. Ее не должно быть при sample num = 0
|
||||||
set_config(
|
set_config(
|
||||||
.w(10),
|
.w(10),
|
||||||
.p(125),
|
.p(125),
|
||||||
@@ -504,9 +502,8 @@ module tb_top;
|
|||||||
disable wait_sampler_active_proc;
|
disable wait_sampler_active_proc;
|
||||||
repeat(30) @(posedge clk_adc);
|
repeat(30) @(posedge clk_adc);
|
||||||
|
|
||||||
// ������ ���� ������ ��������� � ����, ��� ������� ����� ������ ������� �������� ������ ��������� pulse height ��-�� OTR=1
|
// Данный тест должен приводить к тому, что сэмплер будет давать крайние значения вместо заданного pulse height из-за OTR=1
|
||||||
// TODO �������� ��� ��� ����� ���������� OTR = 1 ���������. ����� ����������� �������
|
// Дописать авто тест
|
||||||
// �������� ���� ����
|
|
||||||
$display("[TB] Test 2. Edge cases. OTR == 1. (7/7)");
|
$display("[TB] Test 2. Edge cases. OTR == 1. (7/7)");
|
||||||
run_test_case(
|
run_test_case(
|
||||||
.pulse_width(10),
|
.pulse_width(10),
|
||||||
@@ -538,15 +535,15 @@ module tb_top;
|
|||||||
int r_w, r_p, r_n, r_h, r_sn;
|
int r_w, r_p, r_n, r_h, r_sn;
|
||||||
bit r_skip, r_otr, r_otr_rand;
|
bit r_skip, r_otr, r_otr_rand;
|
||||||
|
|
||||||
// ���������� ���������
|
// Генерируем параметры
|
||||||
r_p = $urandom_range(50, 150); // ������ �� 5 �� 50
|
r_p = $urandom_range(50, 150); // Период от 5 до 50
|
||||||
r_w = $urandom_range(10, r_p); // ������ �� ������ �������
|
r_w = $urandom_range(10, r_p); // Ширина не больше периода
|
||||||
r_n = $urandom_range(1, 10); // ���������� ���������
|
r_n = $urandom_range(1, 10); // Количество импульсов
|
||||||
r_h = $urandom_range(0, 2**(`MIN(ADC_DATA_WIDTH, DAC_DATA_WIDTH))-1); // ������ ��������
|
r_h = $urandom_range(0, 2**(`MIN(ADC_DATA_WIDTH, DAC_DATA_WIDTH))-1); // Высота импульса
|
||||||
r_sn = $urandom_range(2, 40); // ����� �������
|
r_sn = $urandom_range(2, 40); // Число сэмплов
|
||||||
r_skip = $urandom_range(0, 1); // ��������� ����� (0 - �����, 1 - �������)
|
r_skip = $urandom_range(0, 1); // Случайный сброс (0 - сброс, 1 - пропуск)
|
||||||
r_otr = 0; // Out Of Range ��������� ��������
|
r_otr = 0; // Out Of Range стартовое значение
|
||||||
r_otr_rand = 0; // ������� OTR ���������
|
r_otr_rand = 0; // Сделать OTR случайным
|
||||||
|
|
||||||
if (VERBOSE >= 1)
|
if (VERBOSE >= 1)
|
||||||
$display("[TB] --- Test #%0d (Config: W=%0d, P=%0d, N=%0d, H=%0d, SN=%0d, SkipReset=%0b) ---",
|
$display("[TB] --- Test #%0d (Config: W=%0d, P=%0d, N=%0d, H=%0d, SN=%0d, SkipReset=%0b) ---",
|
||||||
@@ -564,7 +561,7 @@ module tb_top;
|
|||||||
.randomize_out_of_range(r_otr_rand)
|
.randomize_out_of_range(r_otr_rand)
|
||||||
);
|
);
|
||||||
|
|
||||||
wait(dut.generator_inst.enable == 0); // �������� �� ���������� ������
|
wait(dut.generator_inst.enable == 0); // Проверка на завершение работы
|
||||||
#50;
|
#50;
|
||||||
end
|
end
|
||||||
$display("[TB] Test 3 complete");
|
$display("[TB] Test 3 complete");
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ module reflectometer_tb;
|
|||||||
localparam LOGIC_ZERO_LEVEL = 0; // DAC -5V for logic zero
|
localparam LOGIC_ZERO_LEVEL = 0; // DAC -5V for logic zero
|
||||||
localparam VOLTAGE_ZERO_LEVEL = 2**(DAC_DATA_WIDTH-1); // DAC 0V for logic zero
|
localparam VOLTAGE_ZERO_LEVEL = 2**(DAC_DATA_WIDTH-1); // DAC 0V for logic zero
|
||||||
localparam PACK_FACTOR = 1; // not used in TB
|
localparam PACK_FACTOR = 1; // not used in TB
|
||||||
localparam PROCESS_MODE = 0; // 0 - uint, 1 - int
|
localparam PROCESS_MODE = 1; // 0 - uint, 1 - int
|
||||||
localparam ACCUM_WIDTH = 32; // accumulator number bit witdth
|
localparam ACCUM_WIDTH = 32; // accumulator number bit witdth
|
||||||
localparam N_MAX = 4096; // max value of windows to average by experiments
|
localparam N_MAX = 4096; // max value of windows to average by experiments
|
||||||
localparam WINDOW_SIZE = 65; // fixed subwindow size to average by time
|
localparam WINDOW_SIZE = 65; // fixed subwindow size to average by time
|
||||||
localparam PACKET_SIZE = 1024; // bytes per UDP packet
|
localparam PACKET_SIZE = 1024; // bytes per UDP packet
|
||||||
|
|
||||||
localparam ZERO_LEVEL = VOLTAGE_ZERO_LEVEL; // "logic" VS "true"
|
localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "voltage"
|
||||||
|
|
||||||
localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz
|
localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz
|
||||||
localparam CLK_REF_PERIOD = 5.000; // 200 MHz
|
localparam CLK_REF_PERIOD = 5.000; // 200 MHz
|
||||||
@@ -63,7 +63,7 @@ module reflectometer_tb;
|
|||||||
wire [ADC_DATA_WIDTH-1:0] adc_data;
|
wire [ADC_DATA_WIDTH-1:0] adc_data;
|
||||||
// Интерфейс хендшейка с MAC-PHY
|
// Интерфейс хендшейка с MAC-PHY
|
||||||
wire send_request;
|
wire send_request;
|
||||||
logic request_ready = 1'b0;
|
logic request_ready;
|
||||||
// Сигналы ЦАП и АЦП
|
// Сигналы ЦАП и АЦП
|
||||||
real signal_voltage;
|
real signal_voltage;
|
||||||
|
|
||||||
@@ -72,6 +72,7 @@ module reflectometer_tb;
|
|||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
virtual_dac_model #( // default voltage range is +/- 5V
|
virtual_dac_model #( // default voltage range is +/- 5V
|
||||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||||
|
// ,.VOLTAGE_GAIN(2)
|
||||||
) virtual_dac (
|
) virtual_dac (
|
||||||
.clk_i(clk_dac),
|
.clk_i(clk_dac),
|
||||||
.wrt_i(dac_wrt),
|
.wrt_i(dac_wrt),
|
||||||
@@ -149,6 +150,7 @@ module reflectometer_tb;
|
|||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Таски для тестирования
|
// Таски для тестирования
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
|
// Таски работы с AXI-Stream
|
||||||
task automatic dut_soft_reset(virtual axis_if#(8).tb vif);
|
task automatic dut_soft_reset(virtual axis_if#(8).tb vif);
|
||||||
logic [7:0] tx_packet[];
|
logic [7:0] tx_packet[];
|
||||||
tx_packet = '{8'h0f};
|
tx_packet = '{8'h0f};
|
||||||
@@ -160,6 +162,7 @@ module reflectometer_tb;
|
|||||||
tx_packet = '{8'hf0};
|
tx_packet = '{8'hf0};
|
||||||
vif.master_send(tx_packet);
|
vif.master_send(tx_packet);
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task automatic dut_send_system_config(
|
task automatic dut_send_system_config(
|
||||||
virtual axis_if#(8).tb vif,
|
virtual axis_if#(8).tb vif,
|
||||||
input logic [31:0] pulse_width,
|
input logic [31:0] pulse_width,
|
||||||
@@ -183,60 +186,99 @@ module reflectometer_tb;
|
|||||||
endtask
|
endtask
|
||||||
|
|
||||||
// Таски сбора и обработки статистики
|
// Таски сбора и обработки статистики
|
||||||
|
task automatic dut_read_output(
|
||||||
|
virtual axis_if#(8).tb vif,
|
||||||
|
input int sample_num,
|
||||||
|
input bit randomize_recv_delays,
|
||||||
|
output int output_data[]
|
||||||
|
);
|
||||||
|
logic [7:0] rx_packet[];
|
||||||
|
logic [ACCUM_WIDTH-1:0] data_packet[];
|
||||||
|
int packet_num = $ceil(real'(sample_num / WINDOW_SIZE) / real'(PACKET_SIZE));
|
||||||
|
int numbers_per_packet = PACKET_SIZE/(ACCUM_WIDTH/8);
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
if (sample_num % WINDOW_SIZE) begin
|
||||||
|
$display("[TB] -dut_read_output- Error, sample_num must be multiple of WINDOW_SIZE: %0d %% %0d = %0d", sample_num, WINDOW_SIZE, sample_num % WINDOW_SIZE);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
data_packet = new[numbers_per_packet];
|
||||||
|
output_data = new[numbers_per_packet * packet_num];
|
||||||
|
// count send_request posedge todo
|
||||||
|
// timeout todo
|
||||||
|
|
||||||
|
// recv loop
|
||||||
|
for (int i = 0; i < packet_num; i++) begin
|
||||||
|
// randomize_recv_delays todo
|
||||||
|
request_ready = 1;
|
||||||
|
vif.slave_recv(rx_packet);
|
||||||
|
request_ready = 0;
|
||||||
|
|
||||||
|
// unpack values
|
||||||
|
data_packet = {<< byte {rx_packet}};
|
||||||
|
data_packet = {<< ACCUM_WIDTH {data_packet}};
|
||||||
|
|
||||||
|
// copy and convert values
|
||||||
|
for (int j = 0; j < data_packet.size(); j++) begin
|
||||||
|
output_data[i * data_packet.size() + j] = int'(data_packet[j]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// wait for dut.finish posedge todo
|
||||||
|
// timeout todo
|
||||||
|
|
||||||
|
// error handling todo
|
||||||
|
endtask
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
|
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
initial begin
|
initial begin
|
||||||
logic [7:0] rx_packet[];
|
int output_data[];
|
||||||
|
|
||||||
automatic virtual axis_if.tb control_vif = axis_control_if.tb;
|
automatic virtual axis_if.tb control_vif = axis_control_if.tb;
|
||||||
automatic virtual axis_if.tb accumulator_vif = axis_accumulator_if.tb;
|
automatic virtual axis_if.tb accumulator_vif = axis_accumulator_if.tb;
|
||||||
|
|
||||||
$display("[TB] Tests start");
|
$display("[TB] DUT initializaton");
|
||||||
|
|
||||||
// Инициализация
|
// Инициализация
|
||||||
|
request_ready = 0;
|
||||||
rst_n = 0;
|
rst_n = 0;
|
||||||
#100;
|
#100;
|
||||||
rst_n = 1;
|
rst_n = 1;
|
||||||
wait(mmcm_locked === 1'b1);
|
wait(mmcm_locked === 1'b1);
|
||||||
#150;
|
#150;
|
||||||
$display("[TB] MMCM locked");
|
$display("[TB] MMCM locked");
|
||||||
|
|
||||||
dut_soft_reset(control_vif);
|
dut_soft_reset(control_vif);
|
||||||
#100;
|
#100;
|
||||||
|
|
||||||
|
// Тесты
|
||||||
|
$display("[TB] Tests start");
|
||||||
dut_send_system_config(
|
dut_send_system_config(
|
||||||
.vif(control_vif),
|
.vif(control_vif),
|
||||||
.pulse_width(32'd12345),
|
.pulse_width(32'd123),
|
||||||
.pulse_period(32'd50000),
|
.pulse_period(32'd5000),
|
||||||
.pulse_num(16'd10),
|
.pulse_num(16'd1),
|
||||||
.pulse_height(14'd16000), // 0V
|
.pulse_height(14'd15000), // 0V
|
||||||
.pulse_period_adc(32'd26000)
|
.pulse_period_adc(32'd2600)
|
||||||
);
|
);
|
||||||
#100;
|
#100;
|
||||||
dut_start(control_vif);
|
dut_start(control_vif);
|
||||||
|
|
||||||
#1000;
|
dut_read_output(
|
||||||
request_ready = 1'b1;
|
.vif(accumulator_vif),
|
||||||
accumulator_vif.slave_recv(rx_packet);
|
.sample_num(2600),
|
||||||
$display("receive %0d bytes", rx_packet.size());
|
.randomize_recv_delays(0),
|
||||||
for (int i = 0; i < rx_packet.size(); i+=4) begin
|
.output_data(output_data)
|
||||||
$write("%0d ", {rx_packet[i], rx_packet[i+1], rx_packet[i+2], rx_packet[i+3]});
|
);
|
||||||
|
|
||||||
|
$display("Received %0d numbers", output_data.size());
|
||||||
|
for (int i = 0; i < output_data.size(); i++) begin
|
||||||
|
$write("%0d ", output_data[i]);
|
||||||
end
|
end
|
||||||
$display("");
|
$display("");
|
||||||
#1000;
|
|
||||||
request_ready = 1'b1;
|
|
||||||
accumulator_vif.slave_recv(rx_packet);
|
|
||||||
$display("receive %0d bytes", rx_packet.size());
|
|
||||||
for (int i = 0; i < rx_packet.size(); i+=4) begin
|
|
||||||
$write("%0d ", {rx_packet[i], rx_packet[i+1], rx_packet[i+2], rx_packet[i+3]});
|
|
||||||
end
|
|
||||||
$display("");
|
|
||||||
// wait();
|
|
||||||
// #100000;
|
|
||||||
// #93000;
|
|
||||||
// rst_n = 0;
|
|
||||||
#10000
|
|
||||||
$display("[TB] ALL PASSED");
|
$display("[TB] ALL PASSED");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ module generator
|
|||||||
|
|
||||||
logic enable, synced;
|
logic enable, synced;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
cnt_pulse_period = '0;
|
||||||
|
cnt_pulse_num = '0;
|
||||||
|
enable = 0;
|
||||||
|
synced = 0;
|
||||||
|
dac_out = ZERO_LEVEL;
|
||||||
|
end
|
||||||
|
|
||||||
always @(posedge clk_dac) begin
|
always @(posedge clk_dac) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
pulse_height_reg <= ZERO_LEVEL;
|
pulse_height_reg <= ZERO_LEVEL;
|
||||||
|
|||||||
+22
-25
@@ -13,38 +13,38 @@ module sampler
|
|||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input request,
|
input request,
|
||||||
|
|
||||||
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||||
output logic m_axis_tvalid,
|
output logic m_axis_tvalid,
|
||||||
output logic done
|
output logic done
|
||||||
);
|
);
|
||||||
|
// WARNING: number of samples smp_num must be multiple of PACK_FACTOR
|
||||||
|
// Last (smp_num % PACK_FACTOR) will be lost and not transmitted
|
||||||
logic [DATA_WIDTH-1:0] data_converted;
|
logic [DATA_WIDTH-1:0] data_converted;
|
||||||
logic [31:0] smp_num_reg, cnt_smp_num;
|
logic [31:0] smp_num_reg, cnt_smp_num;
|
||||||
logic synced;
|
logic synced;
|
||||||
logic [$clog2(PACK_FACTOR):0] pack_cnt;
|
logic [$clog2(PACK_FACTOR):0] pack_cnt;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
data_converted = '0;
|
|
||||||
if (PROCESS_MODE) begin
|
if (PROCESS_MODE) begin
|
||||||
if (out_of_range) begin
|
if (out_of_range) begin
|
||||||
if (data_in[DATA_WIDTH-1]==1'b1) data_converted = {1'b1, {(DATA_WIDTH-2){1'b0}}};
|
data_converted = {~data_in[DATA_WIDTH-1], {(DATA_WIDTH-1){data_in[DATA_WIDTH-1]}}};
|
||||||
else if (data_in[DATA_WIDTH-1]==1'b0) data_converted = {1'b0, {(DATA_WIDTH-2){1'b1}}};
|
|
||||||
end else begin
|
end else begin
|
||||||
if (data_in == {1'b1, {(DATA_WIDTH-1){1'b0}}})
|
data_converted = {~data_in[DATA_WIDTH-1], data_in[DATA_WIDTH-2:0]};
|
||||||
data_converted = data_in;
|
|
||||||
else
|
|
||||||
data_converted = data_in[DATA_WIDTH-1] ?{1'b1, (~data_in[DATA_WIDTH-2:0] + 1'b1)}:data_in;
|
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (out_of_range) begin
|
if (out_of_range) begin
|
||||||
if (data_in[DATA_WIDTH-1]==1'b1) data_converted = '1;
|
data_converted = {DATA_WIDTH{data_in[DATA_WIDTH-1]}};
|
||||||
else if (data_in[DATA_WIDTH-1]==1'b0) data_converted = '0;
|
|
||||||
end else begin
|
end else begin
|
||||||
data_converted = data_in;
|
data_converted = data_in;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
synced = 0;
|
||||||
|
m_axis_tdata = '0;
|
||||||
|
m_axis_tvalid = 0;
|
||||||
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk_in) begin
|
always_ff @(posedge clk_in) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
@@ -56,10 +56,9 @@ module sampler
|
|||||||
synced <= 0;
|
synced <= 0;
|
||||||
done <= 0;
|
done <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
m_axis_tvalid <= 0;
|
|
||||||
if (!synced) begin
|
if (!synced) begin
|
||||||
if (done && request) begin
|
if (done && request) begin
|
||||||
synced <= 1;
|
synced <= 1;
|
||||||
done <= 0;
|
done <= 0;
|
||||||
cnt_smp_num <= 0;
|
cnt_smp_num <= 0;
|
||||||
smp_num_reg <= smp_num;
|
smp_num_reg <= smp_num;
|
||||||
@@ -68,23 +67,21 @@ module sampler
|
|||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (cnt_smp_num != smp_num_reg) begin
|
if (cnt_smp_num != smp_num_reg) begin
|
||||||
cnt_smp_num <= cnt_smp_num +1;
|
cnt_smp_num++;
|
||||||
m_axis_tdata[pack_cnt*DATA_WIDTH +: DATA_WIDTH] <= data_converted;
|
m_axis_tdata[pack_cnt*DATA_WIDTH +: DATA_WIDTH] <= data_converted;
|
||||||
if (pack_cnt == PACK_FACTOR-1) begin
|
if (pack_cnt == PACK_FACTOR-1) begin
|
||||||
pack_cnt <= 0;
|
pack_cnt <= 0;
|
||||||
m_axis_tvalid <= 1;
|
m_axis_tvalid <= 1;
|
||||||
end else begin
|
end else begin
|
||||||
pack_cnt <= pack_cnt + 1;
|
pack_cnt++;
|
||||||
|
m_axis_tvalid <= 0;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
cnt_smp_num <= '0;
|
pack_cnt <= '0;
|
||||||
pack_cnt <= '0;
|
|
||||||
synced <= 0;
|
synced <= 0;
|
||||||
done <= 1;
|
m_axis_tvalid <= 0;
|
||||||
m_axis_tdata <= '0;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
+162
-115
@@ -1,17 +1,24 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module sampler_tb;
|
module sampler_tb #(
|
||||||
|
// Параметры тестбенча
|
||||||
localparam DATA_WIDTH = 12;
|
parameter int DATA_WIDTH = 12, // bitwidth of sampled data. Equal to ADC bitwidth
|
||||||
localparam PACK_FACTOR = 1;
|
parameter int PACK_FACTOR = 1, // packing of several numbers in one axi-stream tdata transaction
|
||||||
localparam PROCESS_MODE = 0;
|
parameter bit PROCESS_MODE = 0, // signed (1) / unsigned (0)
|
||||||
localparam CLK_PERIOD = 15.3846;
|
parameter real CLK_PERIOD = 15.3846,
|
||||||
|
parameter int OTR_OFFSET = 0 // Out of Range offset number clipping
|
||||||
|
);
|
||||||
|
// Вычислимые константы
|
||||||
|
// Диапазон значений семплера
|
||||||
|
localparam int MIN_VALUE = PROCESS_MODE ? -2**(DATA_WIDTH-1) : 0;
|
||||||
|
localparam int MAX_VALUE = PROCESS_MODE ? 2**(DATA_WIDTH-1)-1 : (2**DATA_WIDTH)-1;
|
||||||
|
|
||||||
logic clk;
|
logic clk;
|
||||||
logic rst;
|
logic rst_dut;
|
||||||
|
logic rst_gen;
|
||||||
|
|
||||||
logic [DATA_WIDTH-1:0] data_in;
|
wire [DATA_WIDTH-1:0] data_in;
|
||||||
logic out_of_range;
|
wire out_of_range;
|
||||||
|
|
||||||
logic [31:0] smp_num;
|
logic [31:0] smp_num;
|
||||||
|
|
||||||
@@ -21,15 +28,13 @@ module sampler_tb;
|
|||||||
logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
||||||
logic m_axis_tvalid;
|
logic m_axis_tvalid;
|
||||||
|
|
||||||
int received_count;
|
|
||||||
|
|
||||||
sampler #(
|
sampler #(
|
||||||
.DATA_WIDTH (DATA_WIDTH),
|
.DATA_WIDTH (DATA_WIDTH),
|
||||||
.PACK_FACTOR (PACK_FACTOR),
|
.PACK_FACTOR (PACK_FACTOR),
|
||||||
.PROCESS_MODE(PROCESS_MODE)
|
.PROCESS_MODE(PROCESS_MODE)
|
||||||
) dut (
|
) dut (
|
||||||
.clk_in (clk),
|
.clk_in (clk),
|
||||||
.rst (rst),
|
.rst (rst_dut),
|
||||||
|
|
||||||
.data_in (data_in),
|
.data_in (data_in),
|
||||||
.out_of_range (out_of_range),
|
.out_of_range (out_of_range),
|
||||||
@@ -54,141 +59,183 @@ module sampler_tb;
|
|||||||
// =====================================================
|
// =====================================================
|
||||||
// RESET
|
// RESET
|
||||||
// =====================================================
|
// =====================================================
|
||||||
initial begin
|
task automatic reset_dut();
|
||||||
rst = 1;
|
@(posedge clk);
|
||||||
data_in = 0;
|
rst_dut = 1;
|
||||||
out_of_range = 0;
|
@(posedge clk);
|
||||||
done = 0;
|
rst_dut = 0;
|
||||||
smp_num = 0;
|
endtask
|
||||||
|
|
||||||
repeat(5) @(posedge clk);
|
|
||||||
rst = 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// OUTPUT COUNTER
|
|
||||||
// =====================================================
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (m_axis_tvalid)
|
|
||||||
received_count++;
|
|
||||||
end
|
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// FEED DATA
|
// FEED DATA
|
||||||
// =====================================================
|
// =====================================================
|
||||||
task automatic feed_data_stream(
|
triangle_wave_gen #(
|
||||||
input int num_words,
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
input bit random_data,
|
.OFFSET(OTR_OFFSET), // offset of bits from '0 and '1 for OTR
|
||||||
input bit random_out_of_range
|
.STEP(1) // LSB bit per clock
|
||||||
|
) signal_gen (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst_gen),
|
||||||
|
.signal(data_in),
|
||||||
|
.otr(out_of_range)
|
||||||
);
|
);
|
||||||
logic [DATA_WIDTH-1:0] value;
|
|
||||||
bit oor;
|
|
||||||
begin
|
|
||||||
value = 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < num_words; i++) begin
|
|
||||||
|
|
||||||
if (random_data)
|
|
||||||
value = $urandom_range(1, (1<<DATA_WIDTH)-1);
|
|
||||||
else
|
|
||||||
value = value + 1;
|
|
||||||
|
|
||||||
if (random_out_of_range)
|
|
||||||
oor = ($urandom_range(0,3) == 0);
|
|
||||||
else
|
|
||||||
oor = 0;
|
|
||||||
|
|
||||||
data_in = value;
|
|
||||||
out_of_range = oor;
|
|
||||||
|
|
||||||
@(posedge clk);
|
|
||||||
end
|
|
||||||
|
|
||||||
out_of_range = 0;
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// TEST CASE
|
// TEST TASKS
|
||||||
// =====================================================
|
// =====================================================
|
||||||
task automatic run_test_case(
|
task automatic run_test_case(
|
||||||
input int n,
|
input int sample_num
|
||||||
input bit random_data,
|
|
||||||
input bit random_out_of_range
|
|
||||||
);
|
);
|
||||||
begin
|
logic [DATA_WIDTH-1:0] input_values[$];
|
||||||
received_count = 0;
|
logic [DATA_WIDTH-1:0] output_values[$];
|
||||||
|
bit flag;
|
||||||
|
int tmp_input_val, tmp_output_val;
|
||||||
|
|
||||||
data_in = 0;
|
// Startup sequence
|
||||||
out_of_range = 0;
|
rst_gen <= 1;
|
||||||
done = 0;
|
smp_num <= sample_num;
|
||||||
|
request <= 1;
|
||||||
smp_num = n;
|
|
||||||
|
|
||||||
// handshake
|
|
||||||
@(posedge clk);
|
@(posedge clk);
|
||||||
done <= 1'b1;
|
|
||||||
wait(request == 1'b1);
|
// syncronize
|
||||||
@(posedge clk);
|
while (!done)
|
||||||
done <= 1'b0;
|
@(posedge clk);
|
||||||
|
request <= 0;
|
||||||
|
|
||||||
|
// Wait for sync and start signal generator
|
||||||
|
// while (!dut.synced)
|
||||||
|
// @(posedge clk);
|
||||||
|
wait(dut.synced === 1);
|
||||||
|
rst_gen <= 0;
|
||||||
|
|
||||||
// wait enable
|
// Wait for valid data
|
||||||
wait(dut.enable == 1'b1);
|
fork
|
||||||
|
begin : stat_mon_proc
|
||||||
|
forever begin
|
||||||
|
@(posedge clk);
|
||||||
|
input_values.push_back(data_in);
|
||||||
|
if (m_axis_tvalid) begin
|
||||||
|
for (int i = 0; i < PACK_FACTOR; i++)
|
||||||
|
output_values.push_back(m_axis_tdata[DATA_WIDTH*i +: DATA_WIDTH]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
join_none
|
||||||
|
|
||||||
// feed data
|
// Wait until end
|
||||||
feed_data_stream(n + 10, random_data, random_out_of_range);
|
// while (dut.synced)
|
||||||
|
// @(posedge clk);
|
||||||
|
wait(dut.synced === 0);
|
||||||
|
|
||||||
// wait completion
|
disable stat_mon_proc;
|
||||||
wait(dut.enable == 1'b0);
|
// Pop last input value. Signal is ahead of tdata for 1 cycle
|
||||||
|
input_values.pop_back();
|
||||||
|
|
||||||
$display("Expected smp_num=%0d Received=%0d", smp_num, received_count);
|
// check data length correct
|
||||||
|
if ((input_values.size() - (input_values.size() % PACK_FACTOR)) != output_values.size()) begin
|
||||||
|
$display("[ERROR] -run_test_case- Input queue size don't equal to output queue size: %0d vs %0d", input_values.size(), output_values.size());
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
flag = 0;
|
||||||
|
for (int i = 0; i < output_values.size(); i++) begin
|
||||||
|
// clip value for OTR
|
||||||
|
tmp_input_val = int'(input_values[i]) + MIN_VALUE;
|
||||||
|
tmp_output_val = PROCESS_MODE ?
|
||||||
|
int'($signed({output_values[i][DATA_WIDTH-1], output_values[i]})) :
|
||||||
|
int'(output_values[i]);
|
||||||
|
|
||||||
if (received_count == smp_num)
|
if ((tmp_input_val < MIN_VALUE + OTR_OFFSET) ||
|
||||||
$display("[OK]");
|
(tmp_input_val > MAX_VALUE - OTR_OFFSET)) begin
|
||||||
else
|
// need clipping
|
||||||
$display("[ERROR]");
|
tmp_input_val = ((tmp_input_val - MIN_VALUE) < 2**(DATA_WIDTH-1)) ?
|
||||||
|
MIN_VALUE : MAX_VALUE;
|
||||||
|
end
|
||||||
|
|
||||||
repeat(10) @(posedge clk);
|
if (tmp_input_val != tmp_output_val)
|
||||||
end
|
flag = 1;
|
||||||
endtask
|
end
|
||||||
|
// $display("Total: %0d", output_values.size());
|
||||||
// =====================================================
|
if (flag) begin
|
||||||
// RANDOM TESTS
|
$display("[ERROR] -run_test_case- Sampled data not correct and not equal to generated signal.");
|
||||||
// =====================================================
|
$finish;
|
||||||
task automatic random_stress_test;
|
|
||||||
int n;
|
|
||||||
begin
|
|
||||||
for (int i = 0; i < 20; i++) begin
|
|
||||||
n = $urandom_range(5,20);
|
|
||||||
|
|
||||||
$display("\n--- TEST %0d --- n=%0d", i, n);
|
|
||||||
|
|
||||||
run_test_case(
|
|
||||||
n,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// MAIN
|
// MAIN
|
||||||
// =====================================================
|
// =====================================================
|
||||||
initial begin
|
initial begin
|
||||||
|
int random_number;
|
||||||
|
|
||||||
$display("\n=== BASIC TEST ===");
|
$display("\n=== BASIC TEST ===");
|
||||||
run_test_case(10, 0, 0);
|
|
||||||
|
|
||||||
$display("\n=== OUT_OF_RANGE TEST ===");
|
rst_dut = 1;
|
||||||
run_test_case(20, 1, 1);
|
rst_gen = 1;
|
||||||
|
smp_num = 0;
|
||||||
|
repeat(2) @(posedge clk);
|
||||||
|
rst_dut = 0;
|
||||||
|
repeat(2) @(posedge clk);
|
||||||
|
|
||||||
|
$display("basic test #1");
|
||||||
|
run_test_case(10);
|
||||||
|
run_test_case(100);
|
||||||
|
run_test_case(10000);
|
||||||
|
$display("basic test #2");
|
||||||
|
run_test_case(0);
|
||||||
|
|
||||||
$display("\n=== RANDOM STRESS TEST ===");
|
$display("\n=== RANDOM STRESS TEST ===");
|
||||||
random_stress_test();
|
for (int i = 0; i < 10; i++) begin
|
||||||
|
$display("Random test #%0d", i);
|
||||||
|
random_number = $urandom_range(0, 3 * 2**(DATA_WIDTH)); // up to 1.5 triangle waves
|
||||||
|
run_test_case(random_number);
|
||||||
|
end
|
||||||
|
|
||||||
$display("\n=== TEST FINISHED ===");
|
$display("\n=== TEST FINISHED ===");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module triangle_wave_gen #(
|
||||||
|
parameter DATA_WIDTH = 12,
|
||||||
|
parameter OFFSET = 100, // offset of bits from '0 and '1 for OTR
|
||||||
|
parameter STEP = 1 // LSB bit per clock
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
output logic [DATA_WIDTH-1:0] signal,
|
||||||
|
output logic otr
|
||||||
|
);
|
||||||
|
logic [DATA_WIDTH:0] counter;
|
||||||
|
logic direction;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
counter = '0;
|
||||||
|
direction = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
assign signal = counter > (2**DATA_WIDTH-1) ? (2**DATA_WIDTH-1) : counter;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
if (signal < OFFSET || (2**DATA_WIDTH - signal) <= OFFSET)
|
||||||
|
otr <= 1;
|
||||||
|
else
|
||||||
|
otr <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (rst) begin
|
||||||
|
counter = 0;
|
||||||
|
direction = 1;
|
||||||
|
end else begin
|
||||||
|
if (direction)
|
||||||
|
counter += STEP;
|
||||||
|
else
|
||||||
|
counter -= STEP;
|
||||||
|
|
||||||
|
if (counter >= 2**DATA_WIDTH-1 || counter <= 0)
|
||||||
|
direction <= ~direction;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|||||||
Reference in New Issue
Block a user