`timescale 1ns / 1ns ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 17:42 11/14/2019 // Design Name: // Module Name: RecvTop // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module RecvTop ( input clk, input clk_2x, // clk_2x input clk_4x, input rst, input rst2, // TODO: delete the signal // phy wave input [11:0] dini, input [11:0] dinq, // mgc control output [ 3:0] ad9361_ctrl_in, output wire flag_mgc_done_pulse, // active high pulse signal output wire frame_sync_pulse, // in domain clk //vio input vio_tsync_inter16, //为1的时候启用内插,从16倍过采样中挑一路 input EQUenable_vio, //为1时启用均衡 input [ 7:0] Zerozone_vio, //零域估计,默认值为8'd29 input [ 6:0] vio_stopbit, //寻找停止位,默认值为7'd60 // stop signal output flag_stop, //给shx,拉高8个clk表示当前时帧有效数据接收完毕 output [16:0] addr_stop, //给shx,拉高8个clk,与flag_stop对齐,指示位置与最后1bit有效数据的位置对齐 // mac frame header output [63:0] recvNetData, output recvNetDataNd ); wire rst_TimeSync; wire rst_freq; wire DAGC_rdy; wire framesync; //帧同步峰 wire flag_cfo_done; //帧同步峰,与频率补偿输出对应 wire framesync_tsync; //帧同步标志,与TSync输出对应 wire IntpARdy; //TSync输出nd wire nd_SC_FDE_dout; //SC_FDE输出nd wire framerdy; //一帧译码结果存储完毕标志 reg flag_bercount = 1'd0; reg flag_badframe = 1'd0; reg flag_ber = 1'd0; wire [11:0] dc_removal_dout_i; //MGC_adaptation、去直流输出 wire [11:0] dc_removal_dout_q; wire [ 9:0] matchfilterout_i; //MF输出 wire [ 9:0] matchfilterout_q; wire [ 9:0] DAGC_out_i; //DAGC输出 wire [ 9:0] DAGC_out_q; wire [ 9:0] freqdataout_i; //频率补偿输出 wire [ 9:0] freqdataout_q; wire [ 9:0] IntpOuti; //TSync输出 wire [ 9:0] IntpOutq; wire [ 9:0] SC_FDE_douti; //SC_FDE输出 wire [ 9:0] SC_FDE_doutq; wire [24:0] mean_temp; wire [12:0] acc_mean; wire [ 4:0] state_mgc; wire mgc1_rdy; wire flag_state_mgc; wire [ 2:0] state_rst; wire flag_overflow; wire flag_small; wire [11:0] dc_value_i; wire [11:0] dc_value_q; wire flag_dc; wire flag_agch; wire flag_agcl; wire flag_agc_power; wire [12:0] agc_ref; wire [12:0] agc_check; wire flag_powerabsh; wire flag_powerabsl; wire flag_abs_power; wire [10:0] abs_ref; wire [10:0] abs_check; wire [ 3:0] flag_clk_4bit; //位同步选取通道结果 wire flagoverflow_fftpilot_26to14; //第1个fft结果截位,即导频fft结果的截位,26截到14 wire flagoverflow_ChnZF_26to18; //第2个fft结果截位,即ZF信道估计结果的截位,26截到18 wire flagoverflow_comdiv_34to20i; //第1个除法器结果截位,即复数除法结果的截位,得到没有去噪的ZF估计,34截到18 wire flagoverflow_comdiv_34to20q; //第1个除法器结果截位,即复数除法结果的截位,得到没有去噪的ZF估计,34截到18 wire flagoverflow_ifftzero_29to17i; //第1个ifft结果截位,即ZF零域估计处,结果先除掉低8位,29-8=21截到17 wire flagoverflow_ifftzero_29to17q; //第1个ifft结果截位,即ZF零域估计处,结果先除掉低8位,29-8=21截到17 wire flagoverflow_MMSEdiv_divisor_31to28; //第2个除法器,即MMSE除法的分母截位,31截到28 wire flagoverflow_divmmse_34to11; //第2个除法器结果截位,即MMSE信道估计结果的截位,34截到11 wire flagoverflow_ifftindata_28to20i; //均衡完毕后(频域结果)的截位,即乘法器输出结果的截位,28截到20 wire flagoverflow_ifftindata_28to20q; //均衡完毕后(频域结果)的截位,即乘法器输出结果的截位,28截到20 wire flagoverflow_fftdata_26to16i; //数据段ow的fft输出截位,26截到16 wire flagoverflow_fftdata_26to16q; //数据段ow的fft输出截位,26截到16 wire flagoverflow_FDE_dataout_29to10i; //ifft结果截位,即均衡结果处,结果先除掉低8位,29-7=22截到10 wire flagoverflow_FDE_dataout_29to10q; //ifft结果截位,即均衡结果处,结果先除掉低8位,29-7=22截到10 reg flagoverflow = 1'd0; //总溢出标志 wire Pilot_rdy_hide1_d1; reg [ 7:0] cnt_mgc_delay; wire mgc_start; wire flag_mgc_done; // level flag wire flag_mgc_done_4x; // level flag // startup delay always @(posedge clk) begin if (rst) begin cnt_mgc_delay <= 0; end else if (cnt_mgc_delay < 8'hff) begin cnt_mgc_delay <= cnt_mgc_delay + 1; end else begin cnt_mgc_delay <= cnt_mgc_delay; end end assign mgc_start = (cnt_mgc_delay == 8'hFE); // * MGC module ad9361_mgc_pin_ctrl u_ad9361_mgc_pin_ctrl ( .clk (clk), .rst (rst), .start (mgc_start), .rx_data_i (dini), .rx_data_q (dinq), .ad9361_ctrl_in (ad9361_ctrl_in), .flag_mgc_done_pulse(flag_mgc_done_pulse), .flag_mgc_done (flag_mgc_done) ); reg MF_rdy; // flag_mgc_done_d1 wire MF_rst; // flag_mgc_done_pulse_d2 always @(posedge clk) begin if (rst) begin MF_rdy <= 0; end else begin MF_rdy <= flag_mgc_done; end end wire fifo_out_valid; reg [ 2:0] cnt_fifo_out_valid; reg [ 2:0] cnt_fifo_out_valid_sel = 1; // 根据speed mode对应的计数器边界值 wire [31:0] fifo_out; reg dmf_s_valid; wire dmf_tvalid_interp4_i; wire dmf_tvalid_interp4_q; wire [31:0] mf_data_interp4_i; wire [31:0] mf_data_interp4_q; wire [23:0] dmf_tdata_interp4_i; wire [23:0] dmf_tdata_interp4_q; // valid signal for dmf always @(posedge clk_4x) begin if (rst) begin dmf_s_valid <= 1'd0; end else if (flag_mgc_done_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 // refer to Receiver.v 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 wire mf_fir_s_tready_i; wire mf_fir_s_tready_q; // Match filter fir_match_interp4 u_fir_match_filter_interp4_i ( .aclk (clk), // input wire aclk .s_axis_data_tvalid(flag_mgc_done), // input wire s_axis_data_tvalid .s_axis_data_tready(mf_fir_s_tready_i), // output wire s_axis_data_tready .s_axis_data_tdata ({4'd0, dini}), // 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(flag_mgc_done), // input wire s_axis_data_tvalid .s_axis_data_tready(mf_fir_s_tready_q), // output wire s_axis_data_tready .s_axis_data_tdata ({4'd0, dinq}), // 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 ); // CDC into clk_4x fifo_shift u_fifo_shift ( // input .s_aclk (clk), // input wire s_aclk .s_aresetn (flag_mgc_done), // input wire s_aresetn .s_axis_tvalid(flag_mgc_done), // input wire s_axis_tvalid .s_axis_tready(), // output wire s_axis_tready .s_axis_tdata ({8'd0, mf_data_interp4_q[29-:12], mf_data_interp4_i[29-:12]}), // 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 () ); 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) ); wire [7:0] cnt_chu_seq_sync_max_vio; localparam CNT_CHU_SEQ_SYNC_MAX = 40; //! should not less than 3 due to the minimum rst of aresetn wire [21:0] mag; wire mag_valid; wire frame_sync_4x; // wire frame_sync_pulse; reg flag_frame_sync; // active high level wire rst_frame_sync; // derive from frame sync pulse reg [ 7:0] cnt_chu_seq_sync; // frame sync delay to chu seq sample start pos assign rst_frame_sync = ((cnt_chu_seq_sync >= 1) && (cnt_chu_seq_sync < cnt_chu_seq_sync_max_vio)); //* calc the magnitude MagnitudeEstimator #( .VEC_WIDTH(21) ) u_MagnitudeEstimator ( .clk (clk_4x), .rst (rst), .vec_valid(dmf_tvalid_interp4_i), .I (dmf_tdata_interp4_i[20:0]), .Q (dmf_tdata_interp4_q[20:0]), .mag (mag), .mag_valid(mag_valid) ); //* frame sync threashold judgement 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() // under clk_4x ); always @(posedge clk) begin if (frame_sync_pulse) begin cnt_chu_seq_sync <= 1; end // avoid the tailing of the convolution (here we use CNT_CHU_SEQ_SYNC_MAX clocks) else if (cnt_chu_seq_sync >= 1 && cnt_chu_seq_sync < cnt_chu_seq_sync_max_vio) begin cnt_chu_seq_sync <= cnt_chu_seq_sync + 1; end else begin cnt_chu_seq_sync <= 0; end end always @(posedge clk) begin if (rst) begin flag_frame_sync <= 0; end else if (cnt_chu_seq_sync == cnt_chu_seq_sync_max_vio) begin flag_frame_sync <= 1; end else begin flag_frame_sync <= flag_frame_sync; end end wire [ 9:0] FrameSync_douti; wire [ 9:0] FrameSync_doutq; wire dagc_rdy; wire mgc_rdy; wire rst_dagc; // * lost the connection with other nodes reg [20:0] cnt_lost; reg framelost; always @(posedge clk) begin if (rst_frame_sync) begin cnt_lost <= 21'd0; framelost <= 1'b0; end else begin if (cnt_lost >= 21'd750000) begin cnt_lost <= 21'd0; framelost <= 1'b1; end else begin cnt_lost <= 21'd1 + cnt_lost; framelost <= 1'b0; end end end DAGC_v2 DAGC_v2 ( .clk (clk), .rst (~flag_mgc_done), .mgc1_rdy (MF_rdy), .framesync_d0 (flag_frame_sync), .vio_powertest_h (2'b00), .vio_powertest_l (2'b00), .matchfilterout_i(mf_data_interp4_i[29-:10]), // input, .matchfilterout_q(mf_data_interp4_q[29-:10]), // input .DAGC_out_i (DAGC_out_i), // output .DAGC_out_q (DAGC_out_q), // output // debug .flag_agch (flag_agch), .flag_agcl (flag_agcl), .flag_agc_power (flag_agc_power), .agc_ref (agc_ref), .agc_check (agc_check), .dagc_rdy (dagc_rdy), .mgc_rdy (mgc_rdy), .rst_dagc (rst_dagc) ); // CFO estimation freqestm freqestm ( .clk (clk), .rst (mgc_start), .mgc_rdy (mgc_rdy), .framesync (dagc_rdy), .datain_i (DAGC_out_i), .datain_q (DAGC_out_q), .dataout_i (freqdataout_i), .dataout_q (freqdataout_q), .framesync_delay(flag_cfo_done), .data_save (data_save), .rst_freq (rst_freq) ); //位同步 wire [1:0] cnt_tsync; TimeSync_top TimeSync_top ( .clk (clk), .rst (rst_frame_sync), .dini (freqdataout_i), .dinq (freqdataout_q), .rdy (IntpARdy), .douti (IntpOuti), .doutq (IntpOutq), .vio_tsync_inter16(vio_tsync_inter16), .framesync (flag_cfo_done), //帧同步标志 .framesync_tsync (framesync_tsync), //帧同步标志 //debug .cnt_tsync (cnt_tsync), .flag_clk_4bit (flag_clk_4bit) ); // SC-FDE SC_FDE_TOP SC_FDE_TOP_djy ( .clk (clk), .rst (rst_frame_sync), // param .EQUenable_vio (EQUenable_vio), //为1时启用均衡 .Zerozone_vio (Zerozone_vio), //零域估计,默认值为8'd29 .flag_ow_left (framesync_tsync), //在一帧内,与第一个数据段的pilot的ow第一个nd对齐 .nd (IntpARdy), .dini (IntpOuti), .dinq (IntpOutq), .nd_SC_FDE_dout (nd_SC_FDE_dout), .SC_FDE_douti (SC_FDE_douti), .SC_FDE_doutq (SC_FDE_doutq), // debug,溢出标志 .flagoverflow_fftpilot_26to14 (), .flagoverflow_ChnZF_26to18 (), .flagoverflow_comdiv_34to20i (), .flagoverflow_comdiv_34to20q (), .flagoverflow_ifftzero_29to17i (), .flagoverflow_ifftzero_29to17q (), .flagoverflow_MMSEdiv_divisor_31to28(), .flagoverflow_divmmse_34to11 (), .flagoverflow_ifftindata_28to20i (), .flagoverflow_ifftindata_28to20q (), .flagoverflow_fftdata_26to16i (), .flagoverflow_fftdata_26to16q (), .flagoverflow_FDE_dataout_29to10i (), .flagoverflow_FDE_dataout_29to10q () ); wire phase_adjust_rdy; wire [9:0] phase_adjust_douti; wire [9:0] phase_adjust_doutq; phase_adjust phase_adjust ( .clk (clk), .rst (rst_frame_sync), .din_i (SC_FDE_douti), .din_q (SC_FDE_doutq), .nd (nd_SC_FDE_dout), .framesync(framesync_tsync), .rdy (phase_adjust_rdy), .dout_i (phase_adjust_douti), .dout_q (phase_adjust_doutq) ); wire IQmergerdy; wire ldpcsyncin; wire [7:0] IQmergedout; IQmerge IQmerge ( .clk (clk), .clk2 (clk_2x), .rst (rst2 || rst_frame_sync), .nd (phase_adjust_rdy), .framesync (framesync_tsync), .dini (phase_adjust_douti), .dinq (phase_adjust_doutq), .rdy (IQmergerdy), .ldpcsyncin(ldpcsyncin), .dout (IQmergedout) ); wire LDPC_SyncOut; wire LDPC_Rdy; wire LDPC_Dout; wire [8:0] good_frames; wire [8:0] bad_frames; wire [8:0] total_frames; CCSDS_LDPC_DEC_K1024_R12_TOPP LDPC_decode ( .clk (clk_2x), .Rst (rst2 || rst_frame_sync), .FrameSync (ldpcsyncin), .Nd (IQmergerdy), .Din (IQmergedout), .LDPC_SyncOut(LDPC_SyncOut), .Rdy (LDPC_Rdy), .LDPC_Dout (LDPC_Dout), .good_frames (good_frames), .bad_frames (bad_frames), .total_frames(total_frames) ); // ***** cdc ***** 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(flag_mgc_done_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 (flag_mgc_done) // 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 (1), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values .REG_OUTPUT (1), // 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 ***** vio_recv_top u_vio_recv_top ( .clk (clk), .probe_out0(cnt_chu_seq_sync_max_vio) ); ila_recv_top u_ila_recv_top ( .clk (clk), .probe0 (dini), // width: 12 .probe1 (dinq), // width: 12 .probe2 (mf_data_interp4_i[29-:12]), // width: 12 .probe3 (mf_data_interp4_q[29-:12]), // width: 12 .probe4 (flag_mgc_done), // width: 1 .probe5 (flag_frame_sync), // width: 1 .probe6 (flag_cfo_done), // width: 1 .probe7 (freqdataout_i), // width: 10 .probe8 (freqdataout_q), // width: 10 .probe9 (IntpARdy), // width: 1 .probe10(IntpOuti), // width: 10 .probe11(IntpOutq), // width: 10 .probe12(nd_SC_FDE_dout), // width: 1 .probe13(SC_FDE_douti), // width: 10 .probe14(SC_FDE_doutq), // width: 10 .probe15(phase_adjust_rdy), // width: 1 .probe16(phase_adjust_douti), // width: 10 .probe17(phase_adjust_doutq), // width: 10 .probe18(LDPC_Rdy), // width: 1 .probe19(LDPC_Dout), // width: 1 .probe20(good_frames), // width: 9 .probe21(bad_frames) // width: 9 ); endmodule