From b38a6936763baf2dfda0f0a569ae760940f3a666 Mon Sep 17 00:00:00 2001 From: Zer0Nu11 Date: Sat, 20 Jun 2026 09:33:33 +0300 Subject: [PATCH] fix: timing. New DAC-ADC line code --- designs/adc_dac_synchoronizer/Makefile | 2 +- designs/adc_dac_synchoronizer/debug.xdc | 11 ++++- designs/adc_dac_synchoronizer/sync_top.sv | 46 ++++++++++++++------ designs/adc_dac_synchoronizer/tb_sync_top.sv | 30 +++++++++---- 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/designs/adc_dac_synchoronizer/Makefile b/designs/adc_dac_synchoronizer/Makefile index f331cc4..1f62d02 100644 --- a/designs/adc_dac_synchoronizer/Makefile +++ b/designs/adc_dac_synchoronizer/Makefile @@ -23,7 +23,7 @@ SYN_FILES += sync_top.sv XCI_FILES += $(sort $(shell find ip/ -type f -name '*.xci')) -XDC_FILES += ../../constraints/ax7102.xdc +# XDC_FILES += ../../constraints/ax7102.xdc # useless for pure RTL design XDC_FILES += debug.xdc SYN_FILES += tb_sync_top.sv diff --git a/designs/adc_dac_synchoronizer/debug.xdc b/designs/adc_dac_synchoronizer/debug.xdc index 2a50dfc..600e406 100644 --- a/designs/adc_dac_synchoronizer/debug.xdc +++ b/designs/adc_dac_synchoronizer/debug.xdc @@ -1,3 +1,12 @@ # Primary clocks create_clock -name geneartor_clk -period 8.000 [get_ports clk_dac] -create_clock -name sampler_clk -period 15.385 [get_ports clk_adc] \ No newline at end of file +create_clock -name sampler_clk -period 15.385 [get_ports clk_adc] +set_clock_groups -asynchronous -group [get_clocks geneartor_clk] -group [get_clocks sampler_clk] + +# set_false_path -through [get_nets -hierarchical {*dac_signal* *internal_wire_singnal* *adc_singnal*}] +# set_false_path -through [get_nets {dac_done dac_done_stretched dac_request adc_done adc_request}] + +# set_property DONT_TOUCH true [get_cells -hierarchical -filter {NAME =~ *generator_inst*pulse_height_reg*}] +# set_property DONT_TOUCH true [get_cells -hierarchical -filter {NAME =~ *generator_inst*dac_out_reg*}] +# Применяем к самому проводу сигнала CE, чтобы Vivado не дробила его +# set_property DONT_TOUCH true [get_nets -of_objects [get_pins -hierarchical -filter {PIN_NAME =~ *CE} -of_objects [get_cells *pulse_height_reg*]]] \ No newline at end of file diff --git a/designs/adc_dac_synchoronizer/sync_top.sv b/designs/adc_dac_synchoronizer/sync_top.sv index af3115f..6de29c5 100644 --- a/designs/adc_dac_synchoronizer/sync_top.sv +++ b/designs/adc_dac_synchoronizer/sync_top.sv @@ -30,28 +30,46 @@ module sync_top //------------------------------------------------------------ wire dac_done, dac_request, adc_done, adc_request; wire [DAC_DATA_WIDTH-1:0] dac_signal; - wire [ADC_DATA_WIDTH-1:0] internal_wire_singnal; - wire [ADC_DATA_WIDTH-1:0] adc_singnal; + wire [ADC_DATA_WIDTH-1:0] internal_wire_signal; + wire [ADC_DATA_WIDTH-1:0] adc_signal; + + // 1. Адаптация разрядности и «заземление» лишних бит generate if (ADC_DATA_WIDTH > DAC_DATA_WIDTH) begin : g_pad_zeros - assign internal_wire_singnal = { {(ADC_DATA_WIDTH - DAC_DATA_WIDTH){1'b0}}, dac_signal }; - end - else begin : g_truncate - assign internal_wire_singnal = dac_signal[ADC_DATA_WIDTH-1:0]; + // АЦП шире ЦАП: добиваем нулями старшие биты + assign internal_wire_signal = { {(ADC_DATA_WIDTH - DAC_DATA_WIDTH){1'b0}}, dac_signal }; + end + else if (ADC_DATA_WIDTH < DAC_DATA_WIDTH) begin : g_truncate + // ЦАП шире АЦП (например, 14 -> 12): забираем младшие биты + assign internal_wire_signal = dac_signal[DAC_DATA_WIDTH-1:DAC_DATA_WIDTH-ADC_DATA_WIDTH]; + (* dont_touch = "true" *) wire dummy; + assign dummy = ^dac_signal; + end + else begin : g_match + // Разрядности равны + assign internal_wire_signal = dac_signal; end endgenerate + generate - if (USE_DELAY_LINE) begin + if (USE_DELAY_LINE > 0) begin : g_delay_line localparam int DELAY_LENGTH = USE_DELAY_LINE; - logic [DELAY_LENGTH:0][ADC_DATA_WIDTH-1:0] signal_delay_line; + // Двумерный массив для линии задержки + logic [DELAY_LENGTH-1:0][ADC_DATA_WIDTH-1:0] signal_delay_line; + always_ff @(posedge clk_dac) begin - signal_delay_line[0] <= internal_wire_singnal; - for (int i = 0; i < DELAY_LENGTH; i++) + signal_delay_line[0] <= internal_wire_signal; + for (int i = 0; i < DELAY_LENGTH-1; i++) begin signal_delay_line[i+1] <= signal_delay_line[i]; + end end - assign adc_singnal = signal_delay_line[DELAY_LENGTH]; - end else - assign adc_singnal = internal_wire_singnal; + + // ИСПРАВЛЕНО: читаем из последнего элемента массива + assign adc_signal = signal_delay_line[DELAY_LENGTH-1]; + end + else begin : g_no_delay + assign adc_signal = internal_wire_signal; + end endgenerate //------------------------------------------------------------ @@ -127,7 +145,7 @@ module sync_top ) sampler_inst ( .clk_in(clk_adc), .rst(rst_adc), - .data_in(adc_singnal), + .data_in(adc_signal), .out_of_range(out_of_range), .smp_num(smp_num), .m_axis_tdata(m_axis_tdata), diff --git a/designs/adc_dac_synchoronizer/tb_sync_top.sv b/designs/adc_dac_synchoronizer/tb_sync_top.sv index 09cde9c..63999d5 100644 --- a/designs/adc_dac_synchoronizer/tb_sync_top.sv +++ b/designs/adc_dac_synchoronizer/tb_sync_top.sv @@ -19,7 +19,7 @@ module tb_top; localparam VOLTAGE_ZERO_LEVEL = 2**(DAC_DATA_WIDTH-1); // DAC 0V for logic zero localparam ZERO_LEVEL = (ZERO_LEVEL_PARAM == "logic") ? LOGIC_ZERO_LEVEL : VOLTAGE_ZERO_LEVEL; - localparam CLOCK_DEVIATION = 2; // Maximum clock deviation of pulse stats + localparam CLOCK_DEVIATION = 3; // Maximum clock deviation of pulse stats //------------------------------------------------------------ // Тактовые сигналы и сброс @@ -183,6 +183,7 @@ module tb_top; .sn(sample_num) ); @(posedge clk_dac); + @(posedge clk_dac); if (randomize_start_timing) start_hold_time = $urandom_range(1, 15); @@ -221,8 +222,8 @@ module tb_top; wait(m_axis_tdata != ZERO_LEVEL); // Проверим что высота импульса совпала с заданной. Т.к. OTR != 0 влияет на выходные данные сэмплера, то не будем проверять такие случаи. // Будем считать что из-за OTR данные изменились (по условию OTR + MSB), проверка пропускается, т.к. сложно понять точное значение OTR в момент обработки данных от tdata - if (m_axis_tdata != pulse_height && (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); + 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); $finish; end // Фактическое начало импульса. Поступление высокого уровня @@ -356,11 +357,11 @@ module tb_top; #100; // init - $display("[TB] Test 1. Simple test. (1/3)"); + $display("[TB] Test 1. Simple test. (1/4)"); run_test_case( .pulse_width(50), .pulse_period(125), - .pulse_height(2**(ADC_DATA_WIDTH-1)), + .pulse_height(2**DAC_DATA_WIDTH-1), .pulse_num(5), .sample_num(65), .skip_reset(0), @@ -368,7 +369,7 @@ module tb_top; .out_of_range_val(0), .randomize_out_of_range(0) ); - $display("[TB] Test 1. Simple test. (2/3)"); + $display("[TB] Test 1. Simple test. (2/4)"); run_test_case( .pulse_width(25), .pulse_period(125), @@ -380,7 +381,7 @@ module tb_top; .out_of_range_val(0), .randomize_out_of_range(0) ); - $display("[TB] Test 1. Simple test. (3/3)"); + $display("[TB] Test 1. Simple test. (3/4)"); run_test_case( .pulse_width(10), .pulse_period(50), @@ -392,6 +393,19 @@ module tb_top; .out_of_range_val(0), .randomize_out_of_range(0) ); + + $display("[TB] Test 1. Simple test. (4/4)"); + run_test_case( + .pulse_width(25), + .pulse_period(125), + .pulse_height(2**(DAC_DATA_WIDTH-1)), + .pulse_num(10), + .sample_num(65), + .skip_reset(1), + .randomize_start_timing(1), + .out_of_range_val(0), + .randomize_out_of_range(0) + ); $display("[TB] Test 1 complete"); $display("[TB] Test 2. Edge cases. Pulse width 0%%. (1/7)"); @@ -500,8 +514,6 @@ module tb_top; ); $display("[TB] Test 2 complete"); - // $finish; // TODO remove - $display("[TB] Test 3. Random tests"); for (int i = 0; i < 100; i++) begin int r_w, r_p, r_n, r_h, r_sn;