`timescale 1 ns / 1 ns `include "interfaces.svh" module reflectometer_top #( parameter int unsigned DAC_DATA_WIDTH = 14, parameter int unsigned ADC_DATA_WIDTH = 12, parameter int unsigned PACK_FACTOR = 1, parameter int unsigned PROCESS_MODE = 0, parameter int unsigned ZERO_LEVEL = 8192, parameter int unsigned ACCUM_WIDTH = 32, parameter int unsigned N_MAX = 4096, parameter int unsigned WINDOW_SIZE = 65, parameter int unsigned PACKET_SIZE = 1024 )( input wire clk_in, input wire rst_n, output wire locked, // Accumulator AXI-S bus input wire clk_axis_accumulator, // GMII PHY RX clock axis_if.master axis_accumulator, // Control AXI-S bus input wire clk_axis_control, // GMII PHY TX clock axis_if.slave axis_control, // RTL-MAC handshake input wire request_ready, output wire send_request, // DAC output wire dac_clk_o, output wire [DAC_DATA_WIDTH-1:0] dac_data, output wire dac_wrt, // ADC output wire adc_clk_o, input wire [ADC_DATA_WIDTH-1:0] adc_data, input wire adc_otr ); // ------------------------------------------------------------------------- // Generated clocks for controller // Need to create this IP in Vivado: // input resetn // input clk_200 : 200 MHz : Reference clock // output clk_adc_65 : 65 MHz : ADC RTL clock // output clk_adc_65_180 : 65 MHz, phase 180 deg. : ADC PHY clock // output clk_adc_125 : 125 MHz : DAC RTL clock // output clk_adc_125_180 : 125 MHz, phase 180 deg. : DAC PHY clock // output locked // ------------------------------------------------------------------------- wire clk_sampler, clk_generator, clk_locked; clk_wiz_ctrl_inst clk_wiz_inst ( // Clock in ports .clk_200(clk_in), // Clock out ports .clk_adc_65(clk_sampler), .clk_adc_65_180(adc_clk_o), .clk_dac_125(clk_generator), .clk_dac_125_180(dac_clk_o), // Status and control signals .resetn(rst_n), .locked(clk_locked) ); assign locked = clk_locked; // ------------------------------------------------------------------------- // Controller reset // Use both external reset and clk_wiz lock // ------------------------------------------------------------------------- wire ctrl_rst_n = rst_n & clk_locked; // ------------------------------------------------------------------------- // Controller // ------------------------------------------------------------------------- wire [31:0] dac_pulse_width; wire [31:0] dac_pulse_period; wire [DAC_DATA_WIDTH-1:0] dac_pulse_height; wire [15:0] dac_pulse_num; wire [31:0] adc_pulse_period; wire [15:0] adc_pulse_num; wire dac_start; wire adc_start; wire dac_rst; wire adc_rst; wire finish; control #( .DAC_DATA_WIDTH(DAC_DATA_WIDTH) ) udp_ctrl_inst ( .eth_clk_in (clk_axis_control), .dac_clk_in (clk_generator), .adc_clk_in (clk_sampler), .rst_n (ctrl_rst_n), .s_axis_tdata (axis_control.tdata), .s_axis_tvalid (axis_control.tvalid), .s_axis_tready (axis_control.tready), .s_axis_tlast (axis_control.tlast), .finish (finish), .dac_pulse_width (dac_pulse_width), .dac_pulse_period (dac_pulse_period), .dac_pulse_height (dac_pulse_height), .dac_pulse_num (dac_pulse_num), .adc_pulse_period (adc_pulse_period), .adc_pulse_num (adc_pulse_num), .dac_start (dac_start), .adc_start (adc_start), .dac_rst (dac_rst), .adc_rst (adc_rst) ); //------------------------------------------------------------ // DAC -> ADC CDC //------------------------------------------------------------ (* ASYNC_REG = "TRUE" *) logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени (* ASYNC_REG = "TRUE" *) logic [1:0] sync_DA; wire dac_done_stretched; wire generator_done, generator_request; wire sampler_done, sampler_request; always_ff @(posedge clk_generator or posedge dac_rst) begin if (dac_rst) stretch <= 0; else begin stretch[0] <= generator_done; stretch[1] <= stretch[0]; stretch[2] <= stretch[1]; end end assign dac_done_stretched = |stretch; always_ff @(posedge clk_sampler or posedge adc_rst) begin if (adc_rst) sync_DA <= 0; else begin sync_DA[0] <= dac_done_stretched; sync_DA[1] <= sync_DA[0]; end end assign sampler_request = sync_DA[1]; //------------------------------------------------------------ // ADC -> DAC CDC //------------------------------------------------------------ (* ASYNC_REG = "TRUE" *) logic [1:0] sync_AD; always_ff @(posedge clk_generator or posedge dac_rst) begin if (dac_rst) sync_AD <= 0; else begin sync_AD[0] <= sampler_done; sync_AD[1] <= sync_AD[0]; end end assign generator_request = sync_AD[1]; //------------------------------------------------------------ // Generator (DAC) //------------------------------------------------------------ generator #( .DATA_WIDTH(DAC_DATA_WIDTH), .ZERO_LEVEL(ZERO_LEVEL) ) generator_inst ( .clk_dac(clk_generator), .rst(dac_rst), .start(dac_start), .pulse_width(dac_pulse_width), .pulse_period(dac_pulse_period), .pulse_height(dac_pulse_height), .pulse_num(dac_pulse_num), .dac_out(dac_data), .done(generator_done), .request(generator_request) ); assign dac_wrt = dac_clk_o; // ------------------------------------------------------------------------- // Sampler (ADC) // ------------------------------------------------------------------------- wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] sampler_m_axis_tdata; wire sampler_m_axis_tvalid; sampler #( .DATA_WIDTH(ADC_DATA_WIDTH), .PACK_FACTOR(PACK_FACTOR), .PROCESS_MODE(PROCESS_MODE) ) sampler_dut ( .clk_in(clk_sampler), .rst(adc_rst), .data_in(adc_data), .out_of_range(adc_otr), .m_axis_tdata(sampler_m_axis_tdata), .m_axis_tvalid(sampler_m_axis_tvalid), .smp_num(adc_pulse_period), .done(sampler_done), .request(sampler_request) ); // ------------------------------------------------------------------------- // Accumulator // ------------------------------------------------------------------------- accumulator_top #( .DATA_WIDTH(ADC_DATA_WIDTH), .ACCUM_WIDTH(ACCUM_WIDTH), .N_MAX(N_MAX), .WINDOW_SIZE(WINDOW_SIZE), .PACKET_SIZE(PACKET_SIZE) ) accumulator_top_dut ( .clk_in(clk_sampler), .rst(adc_rst), .s_axis_tdata(sampler_m_axis_tdata), .s_axis_tvalid(sampler_m_axis_tvalid), .start(adc_start), .smp_num(adc_pulse_period), .seq_num(adc_pulse_num), .req_ready(request_ready), .send_req(send_request), .eth_clk_in(clk_axis_accumulator), .m_axis_tdata(axis_accumulator.tdata), .m_axis_tvalid(axis_accumulator.tvalid), .m_axis_tready(axis_accumulator.tready), .m_axis_tlast(axis_accumulator.tlast), .finish(finish) ); endmodule