fix: timing. New DAC-ADC line code

This commit is contained in:
Zer0Nu11
2026-06-20 09:33:33 +03:00
parent 789255fa04
commit b38a693676
4 changed files with 64 additions and 25 deletions

View File

@ -23,7 +23,7 @@ SYN_FILES += sync_top.sv
XCI_FILES += $(sort $(shell find ip/ -type f -name '*.xci')) 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 XDC_FILES += debug.xdc
SYN_FILES += tb_sync_top.sv SYN_FILES += tb_sync_top.sv

View File

@ -1,3 +1,12 @@
# Primary clocks # Primary clocks
create_clock -name geneartor_clk -period 8.000 [get_ports clk_dac] create_clock -name geneartor_clk -period 8.000 [get_ports clk_dac]
create_clock -name sampler_clk -period 15.385 [get_ports clk_adc] 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*]]]

View File

@ -30,28 +30,46 @@ module sync_top
//------------------------------------------------------------ //------------------------------------------------------------
wire dac_done, dac_request, adc_done, adc_request; wire dac_done, dac_request, adc_done, adc_request;
wire [DAC_DATA_WIDTH-1:0] dac_signal; wire [DAC_DATA_WIDTH-1:0] dac_signal;
wire [ADC_DATA_WIDTH-1:0] internal_wire_singnal; wire [ADC_DATA_WIDTH-1:0] internal_wire_signal;
wire [ADC_DATA_WIDTH-1:0] adc_singnal; wire [ADC_DATA_WIDTH-1:0] adc_signal;
// 1. Адаптация разрядности и «заземление» лишних бит
generate generate
if (ADC_DATA_WIDTH > DAC_DATA_WIDTH) begin : g_pad_zeros 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 }; // АЦП шире ЦАП: добиваем нулями старшие биты
assign internal_wire_signal = { {(ADC_DATA_WIDTH - DAC_DATA_WIDTH){1'b0}}, dac_signal };
end end
else begin : g_truncate else if (ADC_DATA_WIDTH < DAC_DATA_WIDTH) begin : g_truncate
assign internal_wire_singnal = dac_signal[ADC_DATA_WIDTH-1:0]; // ЦАП шире АЦП (например, 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 end
endgenerate endgenerate
generate generate
if (USE_DELAY_LINE) begin if (USE_DELAY_LINE > 0) begin : g_delay_line
localparam int DELAY_LENGTH = USE_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 always_ff @(posedge clk_dac) begin
signal_delay_line[0] <= internal_wire_singnal; signal_delay_line[0] <= internal_wire_signal;
for (int i = 0; i < DELAY_LENGTH; i++) for (int i = 0; i < DELAY_LENGTH-1; i++) begin
signal_delay_line[i+1] <= signal_delay_line[i]; signal_delay_line[i+1] <= signal_delay_line[i];
end
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 endgenerate
//------------------------------------------------------------ //------------------------------------------------------------
@ -127,7 +145,7 @@ module sync_top
) sampler_inst ( ) sampler_inst (
.clk_in(clk_adc), .clk_in(clk_adc),
.rst(rst_adc), .rst(rst_adc),
.data_in(adc_singnal), .data_in(adc_signal),
.out_of_range(out_of_range), .out_of_range(out_of_range),
.smp_num(smp_num), .smp_num(smp_num),
.m_axis_tdata(m_axis_tdata), .m_axis_tdata(m_axis_tdata),

View File

@ -19,7 +19,7 @@ module tb_top;
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 ZERO_LEVEL = (ZERO_LEVEL_PARAM == "logic") ? LOGIC_ZERO_LEVEL : VOLTAGE_ZERO_LEVEL; 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) .sn(sample_num)
); );
@(posedge clk_dac); @(posedge clk_dac);
@(posedge clk_dac);
if (randomize_start_timing) if (randomize_start_timing)
start_hold_time = $urandom_range(1, 15); start_hold_time = $urandom_range(1, 15);
@ -221,8 +222,8 @@ module tb_top;
wait(m_axis_tdata != ZERO_LEVEL); wait(m_axis_tdata != ZERO_LEVEL);
// Проверим что высота импульса совпала с заданной. Т.к. OTR != 0 влияет на выходные данные сэмплера, то не будем проверять такие случаи. // Проверим что высота импульса совпала с заданной. Т.к. OTR != 0 влияет на выходные данные сэмплера, то не будем проверять такие случаи.
// Будем считать что из-за OTR данные изменились (по условию OTR + MSB), проверка пропускается, т.к. сложно понять точное значение OTR в момент обработки данных от tdata // Будем считать что из-за OTR данные изменились (по условию OTR + MSB), проверка пропускается, т.к. сложно понять точное значение OTR в момент обработки данных от tdata
if (m_axis_tdata != pulse_height && (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); $display("[ERROR] -run_test_case- Wrong pulse height: %d. Must be: %d", m_axis_tdata, pulse_height >> 2);
$finish; $finish;
end end
// Фактическое начало импульса. Поступление высокого уровня // Фактическое начало импульса. Поступление высокого уровня
@ -356,11 +357,11 @@ module tb_top;
#100; // init #100; // init
$display("[TB] Test 1. Simple test. (1/3)"); $display("[TB] Test 1. Simple test. (1/4)");
run_test_case( run_test_case(
.pulse_width(50), .pulse_width(50),
.pulse_period(125), .pulse_period(125),
.pulse_height(2**(ADC_DATA_WIDTH-1)), .pulse_height(2**DAC_DATA_WIDTH-1),
.pulse_num(5), .pulse_num(5),
.sample_num(65), .sample_num(65),
.skip_reset(0), .skip_reset(0),
@ -368,7 +369,7 @@ module tb_top;
.out_of_range_val(0), .out_of_range_val(0),
.randomize_out_of_range(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( run_test_case(
.pulse_width(25), .pulse_width(25),
.pulse_period(125), .pulse_period(125),
@ -380,7 +381,7 @@ module tb_top;
.out_of_range_val(0), .out_of_range_val(0),
.randomize_out_of_range(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( run_test_case(
.pulse_width(10), .pulse_width(10),
.pulse_period(50), .pulse_period(50),
@ -392,6 +393,19 @@ module tb_top;
.out_of_range_val(0), .out_of_range_val(0),
.randomize_out_of_range(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 1 complete");
$display("[TB] Test 2. Edge cases. Pulse width 0%%. (1/7)"); $display("[TB] Test 2. Edge cases. Pulse width 0%%. (1/7)");
@ -500,8 +514,6 @@ module tb_top;
); );
$display("[TB] Test 2 complete"); $display("[TB] Test 2 complete");
// $finish; // TODO remove
$display("[TB] Test 3. Random tests"); $display("[TB] Test 3. Random tests");
for (int i = 0; i < 100; i++) begin for (int i = 0; i < 100; i++) begin
int r_w, r_p, r_n, r_h, r_sn; int r_w, r_p, r_n, r_h, r_sn;