`timescale 1ns / 1ps module sync_top #( parameter int unsigned DAC_DATA_WIDTH = 14, // DAC bit-width parameter int unsigned ADC_DATA_WIDTH = 12, // ADC bit-width parameter int unsigned PACK_FACTOR = 1, // number of ADC readings per transaction parameter int unsigned PROCESS_MODE = 0, // representation format of ADC readings (0 - direct code, 1 - 2's completment) parameter int unsigned ZERO_LEVEL = 0, parameter int unsigned USE_DELAY_LINE = 0 ) ( input clk_adc, input rst_adc, input clk_dac, input rst_dac, input start, input out_of_range, input [31:0] pulse_width, input [31:0] pulse_period, // DAC counter limit input [DAC_DATA_WIDTH-1:0] pulse_height, input [15:0] pulse_num, input [31:0] smp_num, // ADC counter limit output [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata, output m_axis_tvalid ); //------------------------------------------------------------ // Internal signals //------------------------------------------------------------ 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_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_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]; // (* mark_debug = "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 > 0) begin : g_delay_line localparam int DELAY_LENGTH = USE_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_signal; for (int i = 0; i < DELAY_LENGTH-1; i++) begin signal_delay_line[i+1] <= signal_delay_line[i]; end end // ИСПРАВЛЕНО: читаем из последнего элемента массива assign adc_signal = signal_delay_line[DELAY_LENGTH-1]; end else begin : g_no_delay assign adc_signal = internal_wire_signal; end endgenerate //------------------------------------------------------------ // DAC -> ADC CDC //------------------------------------------------------------ logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени logic [1:0] sync_DA; wire dac_done_stretched; always_ff @(posedge clk_dac or posedge rst_dac) begin if (rst_dac) stretch <= 0; else begin stretch[0] <= dac_done; stretch[1] <= stretch[0]; stretch[2] <= stretch[1]; end end assign dac_done_stretched = |stretch; always_ff @(posedge clk_adc or posedge rst_adc) begin if (rst_adc) sync_DA <= 0; else begin sync_DA[0] <= dac_done_stretched; sync_DA[1] <= sync_DA[0]; end end assign adc_request = sync_DA[1]; //------------------------------------------------------------ // ADC -> DAC CDC //------------------------------------------------------------ logic [1:0] sync_AD; always_ff @(posedge clk_dac or posedge rst_dac) begin if (rst_dac) sync_AD <= 0; else begin sync_AD[0] <= adc_done; sync_AD[1] <= sync_AD[0]; end end assign dac_request = sync_AD[1]; //------------------------------------------------------------ // Generator //------------------------------------------------------------ generator #( .DATA_WIDTH(DAC_DATA_WIDTH), .ZERO_LEVEL(ZERO_LEVEL) ) generator_inst ( .clk_dac(clk_dac), .rst(rst_dac), .start(start), .pulse_width(pulse_width), .pulse_period(pulse_period), .pulse_height(pulse_height), .pulse_num(pulse_num), .dac_out(dac_signal), .request(dac_request), .done(dac_done) ); //------------------------------------------------------------ // Sampler //------------------------------------------------------------ sampler #( .DATA_WIDTH(ADC_DATA_WIDTH), .PACK_FACTOR(PACK_FACTOR), .PROCESS_MODE(PROCESS_MODE) ) sampler_inst ( .clk_in(clk_adc), .rst(rst_adc), .data_in(adc_signal), .out_of_range(out_of_range), .smp_num(smp_num), .m_axis_tdata(m_axis_tdata), .m_axis_tvalid(m_axis_tvalid), .request(adc_request), .done(adc_done) ); endmodule