upd: TB done

This commit is contained in:
Zer0Nu11
2026-07-31 19:18:59 +03:00
parent 7c7cd451b8
commit e354cb2742
2 changed files with 163 additions and 47 deletions
+10 -8
View File
@@ -86,15 +86,15 @@
Система работает в нескольких тактовых доменах: Система работает в нескольких тактовых доменах:
- Ethernet RX (`gmii_rx_clk`) - Ethernet RX (`clk_axis_control`)
- Ethernet TX (`gmii_tx_clk`) - Ethernet TX (`clk_axis_accumulator`)
- DAC (`dac_clk`) - DAC (`clk_generator`)
- ADC (`adc_clk`) - ADC (`clk_sampler`)
Для корректной синхронизации между DAC и ADC используются специальные CDC-регистры для сигналов: Для корректной синхронизации между DAC и ADC используются специальные CDC-регистры для сигналов:
- `sample_req` - `done`
- `sample_done` - `request`
Это обеспечивает безопасную передачу handshake-сигналов между тактовыми доменами. Это обеспечивает безопасную передачу handshake-сигналов между тактовыми доменами.
@@ -110,8 +110,8 @@
Типовые значения: Типовые значения:
- `8192` — середина диапазона ЦАП - `8192` — середина диапазона ЦАП (0V)
- `0` — нулевой уровень - `0` — нулевой уровень (-5V)
### ADC_DATA_WIDTH ### ADC_DATA_WIDTH
Ширина входных данных, получаемых с АЦП. Ширина входных данных, получаемых с АЦП.
@@ -143,3 +143,5 @@
```make all``` - собрать все до битстрима ```make all``` - собрать все до битстрима
```make vivado``` - открыть проект в Vivado ```make vivado``` - открыть проект в Vivado
```make sim``` - симуляция и верификация проекта
+148 -34
View File
@@ -1,9 +1,8 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
`include "interfaces.svh" `include "interfaces.svh"
// start push
`define DEBUG // `define DEBUG
`define MEASURE_CLK(clk, period) \ `define MEASURE_CLK(clk, period) \
begin \ begin \
@@ -15,6 +14,13 @@ begin \
period = t2 - t1; \ period = t2 - t1; \
end end
`define ERR_CHECK \
total_tests++; \
if (result_flag) begin \
total_failed_tests++; \
$error("Test #%0d failed. Err code: %0d", total_tests, result_flag); \
end \
module reflectometer_tb; module reflectometer_tb;
//------------------------------------------------------------ //------------------------------------------------------------
// Параметры // Параметры
@@ -30,6 +36,10 @@ module reflectometer_tb;
localparam PACKET_SIZE = 1024; // bytes per UDP packet localparam PACKET_SIZE = 1024; // bytes per UDP packet
localparam int REQUEST_TIMEOUT = 3 * PACKET_SIZE; // timeout for packet receiving from accumulator localparam int REQUEST_TIMEOUT = 3 * PACKET_SIZE; // timeout for packet receiving from accumulator
localparam int TEST_NUM = 100; // number of random tests
localparam real PEARSON_THRESHOLD = 0.99;
localparam real NRMSE_THRESHOLD = 0.1;
localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "voltage" localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "voltage"
@@ -326,6 +336,8 @@ module reflectometer_tb;
$finish; $finish;
end end
wait(processing_done == 0);
endtask endtask
//------------------------------------------------------------ //------------------------------------------------------------
@@ -425,32 +437,22 @@ module reflectometer_tb;
return sum / a.size(); return sum / a.size();
endfunction endfunction
// NRMSE двух выборок (нормирование MSE) // NRMSE двух выборок (нормирование RMSE)
function automatic real calc_nrmse( function automatic real calc_nrmse(
input real a[], input real a[],
input real b[] input real b[]
); );
real mse; const real EPS = 1e-12;
real min_val; real mse, ms = 0;
real max_val;
mse = calc_mse(a, b); mse = calc_mse(a, b);
min_val = a[0];
max_val = a[0];
foreach (a[i]) begin foreach (a[i]) begin
if (a[i] < min_val) ms += a[i] * a[i];
min_val = a[i];
if (a[i] > max_val)
max_val = a[i];
end end
ms /= a.size();
if (max_val == min_val) return $sqrt(mse / (ms + EPS));
return 0.0;
return $sqrt(mse) / (max_val - min_val);
endfunction endfunction
// Функция модуля // Функция модуля
@@ -521,6 +523,14 @@ module reflectometer_tb;
$write("\n"); $write("\n");
endfunction endfunction
// Вспомогательная функция для вывода массива
function automatic void display_array(input int a[]);
$write("\t");
foreach(a[i])
$write("%0d ", a[i]);
$write("\n");
endfunction
// Основная таска типового теста // Основная таска типового теста
task automatic run_test_case( task automatic run_test_case(
virtual axis_if#(8).tb ctrl_vif, virtual axis_if#(8).tb ctrl_vif,
@@ -533,7 +543,7 @@ module reflectometer_tb;
input int window_size, input int window_size,
input bit rand_recv_delays, input bit rand_recv_delays,
input bit use_reset, input bit use_reset,
output bit result output int result
); );
int output_data[]; // raw accum values int output_data[]; // raw accum values
real output_signal_v[]; // accum values after voltage conversion real output_signal_v[]; // accum values after voltage conversion
@@ -568,6 +578,11 @@ module reflectometer_tb;
// actual size of payload is pulse_period_adc / window_size // actual size of payload is pulse_period_adc / window_size
output_signal_v = new[pulse_period_adc / window_size]; output_signal_v = new[pulse_period_adc / window_size];
`ifdef DEBUG
$display("[TB] Output data stream");
display_array(output_data);
`endif
// voltage conversion // voltage conversion
begin begin
// zero level for partial sum // zero level for partial sum
@@ -605,17 +620,21 @@ module reflectometer_tb;
`endif `endif
// check metrics // check metrics
result = 1;
if (pearson < 0.99)
result = 0;
if (nrmse > 0.1)
result = 0; result = 0;
// if (pearson < PEARSON_THRESHOLD)
// result += 1;
if (nrmse > NRMSE_THRESHOLD)
result += 2;
/* /*
Max error not used in evaluation because of fast pulse edge falling Max error not used in evaluation because of fast pulse edge falling
resulting in plain difference between active signal level and zero level resulting in plain difference between active signal level and zero level
For ex.: zero_level = 0x00 = -5V. pulse_height = 2^14-1 = 0x3fff = 5V For ex.: zero_level = 0x00 = -5V. pulse_height = 2^14-1 = 0x3fff = 5V
In some cases like jitter this may cause max error = 5 - (-5) = 10(V) In some cases like jitter this may cause max error = 5 - (-5) = 10(V)
This cases are hardly traceble, thus max error not used in eval. This cases are hardly traceble, thus max error not used in eval.
Pearson not used in evaluation because it only shows correlation of changing signals. Tests broke on static signals.
Pearson and max err remain in test for info.
*/ */
endtask endtask
@@ -623,7 +642,7 @@ module reflectometer_tb;
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ // ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
//------------------------------------------------------------ //------------------------------------------------------------
initial begin initial begin
bit result_flag; int result_flag;
int total_failed_tests = 0, total_tests = 0; int total_failed_tests = 0, total_tests = 0;
automatic virtual axis_if.tb control_vif = axis_control_if.tb; automatic virtual axis_if.tb control_vif = axis_control_if.tb;
@@ -646,35 +665,130 @@ module reflectometer_tb;
join join
$info("[TB] ADC & DAC clock periods measured: ADC_period = %0.3f, DAC_period = %0.3f", CLK_ADC_PERIOD, CLK_DAC_PERIOD); $info("[TB] ADC & DAC clock periods measured: ADC_period = %0.3f, DAC_period = %0.3f", CLK_ADC_PERIOD, CLK_DAC_PERIOD);
dut_soft_reset(control_vif);
#100;
// Тесты // Тесты
$info("[TB] Tests start"); $info("[TB] Tests start");
$info("[TB] Simple test run"); $info("[TB] Simple test run");
run_test_case(
.ctrl_vif(control_vif),
.accum_vif(accumulator_vif),
.pulse_width(4000),
.pulse_period(10000),
.pulse_num(5),
.pulse_height(12000),
.pulse_period_adc(6000),
.window_size(10),
.rand_recv_delays(1),
.use_reset(1),
.result(result_flag)
);
`ERR_CHECK
$info("[TB] Random test run");
for (int i = 0; i < TEST_NUM; i++) begin
int pulse_width, pulse_period, pulse_num, pulse_height, pulse_period_adc, window_size;
bit rand_recv_delays, use_reset;
// Генерируемые параметры
pulse_period = $urandom_range(500, 5000);
pulse_width = $urandom_range(50, pulse_period);
pulse_num = $urandom_range(1, 10);
pulse_height = $urandom_range(0, 2**DAC_DATA_WIDTH-1);
window_size = $urandom_range(1, 11);
pulse_period_adc = $urandom_range(50, N_MAX-1) * window_size;
rand_recv_delays = 1;
use_reset = 1; // ($urandom_range(0, 10) >= 9);
`ifdef DEBUG
$display("Test #%0d", total_tests);
$display("Parameters:\n\tpulse_width=%0d\n\tpulse_period=%0d\n\tpulse_num=%0d\n\tpulse_height=%0d\n\tpulse_period_adc=%0d\n\twindow_size=%0d\n\trand_recv_delays=%0d\n\tuse_reset=%0d",
pulse_width, pulse_period, pulse_num, pulse_height, pulse_period_adc, window_size, rand_recv_delays, use_reset);
`endif
run_test_case( run_test_case(
.ctrl_vif(control_vif), .ctrl_vif(control_vif),
.accum_vif(accumulator_vif), .accum_vif(accumulator_vif),
.pulse_width(400), .pulse_width(pulse_width),
.pulse_period(pulse_period),
.pulse_num(pulse_num),
.pulse_height(pulse_height),
.pulse_period_adc(pulse_period_adc),
.window_size(window_size),
.rand_recv_delays(rand_recv_delays),
.use_reset(use_reset),
.result(result_flag)
);
`ERR_CHECK
if (result_flag) begin
$display("Parameters:\n\tpulse_width=%0d\n\tpulse_period=%0d\n\tpulse_num=%0d\n\tpulse_height=%0d\n\tpulse_period_adc=%0d\n\twindow_size=%0d\n\trand_recv_delays=%0d\n\tuse_reset=%0d",
pulse_width, pulse_period, pulse_num, pulse_height, pulse_period_adc, window_size, rand_recv_delays, use_reset);
end
end
$info("[TB] Corner case test run");
run_test_case(
.ctrl_vif(control_vif),
.accum_vif(accumulator_vif),
.pulse_width(0),
.pulse_period(1000), .pulse_period(1000),
.pulse_num(5), .pulse_num(5),
.pulse_height(12000), .pulse_height(12000),
.pulse_period_adc(600), .pulse_period_adc(600),
.window_size(10), .window_size(10),
.rand_recv_delays(0), .rand_recv_delays(0),
.use_reset(0), .use_reset(1),
.result(result_flag) .result(result_flag)
); );
`ERR_CHECK
$info("[TB] Random test run"); run_test_case(
.ctrl_vif(control_vif),
.accum_vif(accumulator_vif),
.pulse_width(1000),
.pulse_period(1000),
.pulse_num(5),
.pulse_height(12000),
.pulse_period_adc(600),
.window_size(10),
.rand_recv_delays(0),
.use_reset(1),
.result(result_flag)
);
`ERR_CHECK
$info("[TB] Corner case test run"); run_test_case(
.ctrl_vif(control_vif),
.accum_vif(accumulator_vif),
.pulse_width(500),
.pulse_period(1000),
.pulse_num(5),
.pulse_height(2**(DAC_DATA_WIDTH-1)),
.pulse_period_adc(600),
.window_size(10),
.rand_recv_delays(0),
.use_reset(1),
.result(result_flag)
);
`ERR_CHECK
run_test_case(
.ctrl_vif(control_vif),
.accum_vif(accumulator_vif),
.pulse_width(500),
.pulse_period(1000),
.pulse_num(5),
.pulse_height(15000),
.pulse_period_adc(10),
.window_size(1),
.rand_recv_delays(0),
.use_reset(1),
.result(result_flag)
);
`ERR_CHECK
// if (!failed) $display("[TB] Tests done. [%0d/%0d] tests passed, %0d failed", total_tests - total_failed_tests, total_tests, total_failed_tests);
$info("[TB] ALL PASSED"); if (!total_failed_tests)
$display("[TB] ALL PASSED");
$finish; $finish;
end end
endmodule endmodule