`timescale 1ns / 1ns module Receiver ( input clk, input clk_2x, input clk_4x, input rst, input [ 2:0] speed_mode, input [11:0] ad9361_rx_data_i, input [11:0] ad9361_rx_data_q, output frame_sync_pulse // in domain clk ); // ******** Wire & Reg ******** // reg [23:0] mf_data_d1; // clk_4x // reg [23:0] mf_data_d2; // clk_4x // wire rst_4x; // NOTE: HIGH FANOUT to be fixed reg [11:0] mf_data_i; reg [11:0] mf_data_q; reg [20:0] dmf_data_i; reg [20:0] dmf_data_q; wire [23:0] dmf_tdata_interp4_i; wire [23:0] dmf_tdata_interp4_q; wire [23:0] dmf_tdata_interp16_i; wire [23:0] dmf_tdata_interp16_q; reg dmf_tvalid; wire dmf_tvalid_interp4_i; wire dmf_tvalid_interp4_q; wire dmf_tvalid_interp16_i; wire dmf_tvalid_interp16_q; wire dmf_ready; wire [31:0] mf_data_interp16_i; wire [31:0] mf_data_interp16_q; wire [31:0] mf_data_interp4_i; wire [31:0] mf_data_interp4_q; wire [21:0] mag; wire mag_valid; wire frame_sync; wire fifo_out_valid; reg [ 2:0] cnt_fifo_out_valid; reg [ 2:0] cnt_fifo_out_valid_sel; // 根据speed mode对应的计数器边界值 wire [31:0] fifo_out; reg dmf_s_valid; reg [ 8:0] cnt_startup; wire startup; wire startup_4x; wire frame_sync_4x; // ******** Assingment ******** assign startup = (cnt_startup == 9'd511); // ******** Logic Block ******** always @(posedge clk) begin if (rst) begin cnt_startup <= 9'd0; end else if (cnt_startup < 9'd511) begin cnt_startup <= cnt_startup + 8'd1; end end // valid signal for dmf always @(posedge clk_4x) begin if (rst) begin dmf_s_valid <= 1'd0; end else if (startup_4x && fifo_out_valid && cnt_fifo_out_valid == cnt_fifo_out_valid_sel) begin // fifo_out_valid may be not trustable at the rst state dmf_s_valid <= 1'd1; end else begin dmf_s_valid <= 1'd0; end end always @(posedge clk_4x) begin if (rst) begin cnt_fifo_out_valid <= 3'd0; end else if (fifo_out_valid) begin if (cnt_fifo_out_valid == cnt_fifo_out_valid_sel) begin cnt_fifo_out_valid <= 3'd0; end else begin cnt_fifo_out_valid <= cnt_fifo_out_valid + 3'd1; end end else begin cnt_fifo_out_valid <= cnt_fifo_out_valid; end end // speed mode select always @(*) begin case (speed_mode) 3'd0: begin // 16 mf_data_i = mf_data_interp16_i[31-:12]; mf_data_q = mf_data_interp16_q[31-:12]; dmf_data_i = dmf_tdata_interp16_i[20:0]; dmf_data_q = dmf_tdata_interp16_q[20:0]; dmf_tvalid = dmf_tvalid_interp16_i; cnt_fifo_out_valid_sel = 3'd7; end // 3'd1: begin // 8 // end 3'd2: begin // 4 mf_data_i = mf_data_interp4_i[29-:12]; mf_data_q = mf_data_interp4_q[29-:12]; dmf_data_i = dmf_tdata_interp4_i[20:0]; dmf_data_q = dmf_tdata_interp4_q[20:0]; dmf_tvalid = dmf_tvalid_interp4_i; cnt_fifo_out_valid_sel = 3'd1; end // 3'd3: begin // 2 // end default: begin mf_data_i = mf_data_interp16_i[31-:12]; mf_data_q = mf_data_interp16_q[31-:12]; dmf_data_i = dmf_tdata_interp16_i[20:0]; dmf_data_q = dmf_tdata_interp16_q[20:0]; dmf_tvalid = dmf_tvalid_interp16_i; cnt_fifo_out_valid_sel = 3'd7; end endcase end // ******** Inst ******** xpm_cdc_sync_rst #( .DEST_SYNC_FF (4), // DECIMAL; range: 2-10 .INIT (1), // DECIMAL; 0=initialize synchronization registers to 0, 1=initialize synchronization // registers to 1 .INIT_SYNC_FF (1), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values .SIM_ASSERT_CHK(1) // DECIMAL; 0=disable simulation messages, 1=enable simulation messages ) xpm_cdc_sync_rst_inst ( .dest_rst(rst_4x), // 1-bit output: src_rst synchronized to the destination clock domain. This output // is registered. .dest_clk(clk_4x), // 1-bit input: Destination clock. .src_rst (rst) // 1-bit input: Source reset signal. ); // match filter // fir_match_interp16 u_fir_match_filter_interp16_i ( // .aclk (clk), // input wire aclk // .s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid // .s_axis_data_tready(), // output wire s_axis_data_tready // .s_axis_data_tdata ({4'd0, ad9361_rx_data_i}), // input wire [15 : 0] s_axis_data_tdata // .m_axis_data_tvalid(), // output wire m_axis_data_tvalid // .m_axis_data_tdata (mf_data_interp16_i) // output wire [31 : 0] m_axis_data_tdata // ); // fir_match_interp16 u_fir_match_filter_interp16_q ( // .aclk (clk), // input wire aclk // .s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid // .s_axis_data_tready(), // output wire s_axis_data_tready // .s_axis_data_tdata ({4'd0, ad9361_rx_data_q}), // input wire [15 : 0] s_axis_data_tdata // .m_axis_data_tvalid(), // output wire m_axis_data_tvalid // .m_axis_data_tdata (mf_data_interp16_q) // output wire [31 : 0] m_axis_data_tdata // ); fir_match_interp4 u_fir_match_filter_interp4_i ( .aclk (clk), // input wire aclk .s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid .s_axis_data_tready(), // output wire s_axis_data_tready .s_axis_data_tdata ({4'd0, ad9361_rx_data_i}), // input wire [15 : 0] s_axis_data_tdata .m_axis_data_tvalid(), // output wire m_axis_data_tvalid .m_axis_data_tdata (mf_data_interp4_i) // output wire [31 : 0] m_axis_data_tdata ); fir_match_interp4 u_fir_match_filter_interp4_q ( .aclk (clk), // input wire aclk .s_axis_data_tvalid(startup), // input wire s_axis_data_tvalid .s_axis_data_tready(), // output wire s_axis_data_tready .s_axis_data_tdata ({4'd0, ad9361_rx_data_q}), // input wire [15 : 0] s_axis_data_tdata .m_axis_data_tvalid(), // output wire m_axis_data_tvalid .m_axis_data_tdata (mf_data_interp4_q) // output wire [31 : 0] m_axis_data_tdata ); // TODO: 削峰 fifo_shift u_fifo_shift ( // input .s_aclk (clk), // input wire s_aclk .s_aresetn (startup), // input wire s_aresetn .s_axis_tvalid(startup), // input wire s_axis_tvalid .s_axis_tready(), // output wire s_axis_tready .s_axis_tdata ({8'd0, mf_data_q, mf_data_i}), // input wire [31 : 0] s_axis_tdata // output .m_aclk (clk_4x), // input wire m_aclk .m_axis_tvalid(fifo_out_valid), // output wire m_axis_tvalid .m_axis_tready(1'b1), // input wire m_axis_tready .m_axis_tdata (fifo_out), // output wire [31 : 0] m_axis_tdata .wr_rst_busy (), .rd_rst_busy () ); // TODO: dmf根据不同的速率挡位来选择不同的内插值的fir滤波器 // NOTE: 编写关于抽取的滤波器设计相关文档 // dmf filter // fir_dmf_interp16 u_fir_dmf_interp16_i ( // .aclk (clk_4x), // input wire aclk // .s_axis_data_tvalid(dmf_s_valid), // input wire s_axis_data_tvalid // .s_axis_data_tready(), // output wire s_axis_data_tready // .s_axis_data_tdata ({4'd0, fifo_out[11:0]}), // input wire [15 : 0] s_axis_data_tdata // .m_axis_data_tvalid(dmf_tvalid_interp16_i), // output wire m_axis_data_tvalid // .m_axis_data_tdata (dmf_tdata_interp16_i) // output wire [31 : 0] m_axis_data_tdata // ); // fir_dmf_interp16 u_fir_dmf_interp16_q ( // .aclk (clk_4x), // input wire aclk // .s_axis_data_tvalid(dmf_s_valid), // input wire s_axis_data_tvalid // .s_axis_data_tready(), // output wire s_axis_data_tready // .s_axis_data_tdata ({4'd0, fifo_out[23:12]}), // input wire [15 : 0] s_axis_data_tdata // .m_axis_data_tvalid(dmf_tvalid_interp16_q), // output wire m_axis_data_tvalid // .m_axis_data_tdata (dmf_tdata_interp16_q) // output wire [31 : 0] m_axis_data_tdata // ); fir_dmf_interp4 u_fir_dmf_interp4_i ( .aclk (clk_4x), .s_axis_data_tvalid(dmf_s_valid), .s_axis_data_tready(), .s_axis_data_tdata ({4'd0, fifo_out[11:0]}), .m_axis_data_tvalid(dmf_tvalid_interp4_i), .m_axis_data_tdata (dmf_tdata_interp4_i) ); fir_dmf_interp4 u_fir_dmf_interp4_q ( .aclk (clk_4x), .s_axis_data_tvalid(dmf_s_valid), .s_axis_data_tready(), .s_axis_data_tdata ({4'd0, fifo_out[23:12]}), .m_axis_data_tvalid(dmf_tvalid_interp4_q), .m_axis_data_tdata (dmf_tdata_interp4_q) ); MagnitudeEstimator #( .VEC_WIDTH(21) ) u_MagnitudeEstimator ( .clk (clk_4x), .rst (rst), .vec_valid(dmf_tvalid), .I (dmf_data_i), .Q (dmf_data_q), .mag (mag), .mag_valid(mag_valid) ); PAPR #( .MAG_WIDTH (22), .WINDOW_DEPTH(1023) ) u_PAPR ( .clk (clk_4x), .rst (rst), .vec_mag (mag), .mag_valid (mag_valid), .frame_sync (frame_sync_4x), .frame_sync_pulse() ); xpm_cdc_single #( .DEST_SYNC_FF (2), // DECIMAL; range: 2-10 .INIT_SYNC_FF (1), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values .SIM_ASSERT_CHK(1), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages .SRC_INPUT_REG (1) // DECIMAL; 0=do not register input, 1=register input ) xpm_cdc_startup_inst ( .dest_out(startup_4x), // 1-bit output: src_in synchronized to the destination clock domain. This output is // registered. .dest_clk(clk_4x), // 1-bit input: Clock signal for the destination clock domain. .src_clk (clk), // 1-bit input: optional; required when SRC_INPUT_REG = 1 .src_in (startup) // 1-bit input: Input signal to be synchronized to dest_clk domain. ); xpm_cdc_pulse #( .DEST_SYNC_FF (4), // DECIMAL; range: 2-10 .INIT_SYNC_FF (0), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values .REG_OUTPUT (0), // DECIMAL; 0=disable registered output, 1=enable registered output .RST_USED (0), // DECIMAL; 0=no reset, 1=implement reset .SIM_ASSERT_CHK(1) // DECIMAL; 0=disable simulation messages, 1=enable simulation messages ) xpm_cdc_frame_sync_pulse_inst ( .dest_pulse(frame_sync_pulse), // 1-bit output: Outputs a pulse the size of one dest_clk period when a pulse // transfer is correctly initiated on src_pulse input. This output is // combinatorial unless REG_OUTPUT is set to 1. .dest_clk (clk), // 1-bit input: Destination clock. .dest_rst (), // 1-bit input: optional; required when RST_USED = 1 .src_clk (clk_4x), // 1-bit input: Source clock. .src_pulse (frame_sync_4x), // 1-bit input: Rising edge of this signal initiates a pulse transfer to the // destination clock domain. The minimum gap between each pulse transfer must be // at the minimum 2*(larger(src_clk period, dest_clk period)). This is measured // between the falling edge of a src_pulse to the rising edge of the next // src_pulse. This minimum gap will guarantee that each rising edge of src_pulse // will generate a pulse the size of one dest_clk period in the destination // clock domain. When RST_USED = 1, pulse transfers will not be guaranteed while // src_rst and/or dest_rst are asserted. .src_rst () // 1-bit input: optional; required when RST_USED = 1 ); // ******** Debug ******** endmodule