Files
2024-10-09 20:13:52 +08:00

624 lines
24 KiB
Verilog
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
`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,
// rx data src
output wire [31:0] rx_data_src_fifo_tdata,
output wire rx_data_src_fifo_tlast,
input wire rx_data_src_fifo_tready,
output wire rx_data_src_fifo_tvalid,
// ber
output reg err_flag_pos
);
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
//* 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 && ~flag_frame_sync) 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
assign rst_frame_sync = ((cnt_chu_seq_sync >= 1) && (cnt_chu_seq_sync < cnt_chu_seq_sync_max_vio));
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
wire [9:0] dagc_data_in_i;
wire [9:0] dagc_data_in_q;
shift_register_64 u_shift_register_64_i (
.D (mf_data_interp4_i[29-:10]), // input wire [9 : 0] D
.CLK(clk), // input wire CLK
.Q (dagc_data_in_i) // output wire [9 : 0] Q
);
shift_register_64 u_shift_register_64_q (
.D (mf_data_interp4_q[29-:10]), // input wire [9 : 0] D
.CLK(clk), // input wire CLK
.Q (dagc_data_in_q) // output wire [9 : 0] Q
);
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(dagc_data_in_i), // input,
.matchfilterout_q(dagc_data_in_q), // 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)
);
extract_mac_frame u_extract_mac_frame (
.clk (clk_2x),
.rst (rst2 || rst_frame_sync),
.ldpc_dec_out_start (LDPC_SyncOut),
.ldpc_dec_out_valid (LDPC_Rdy),
.ldpc_dec_out_data (LDPC_Dout),
.m_axis_mac_frame_tvalid(rx_data_src_fifo_tvalid),
.m_axis_mac_frame_tdata (rx_data_src_fifo_tdata),
.m_axis_mac_frame_tready(rx_data_src_fifo_tready),
.m_axis_mac_frame_tlast (rx_data_src_fifo_tlast)
);
reg err_flag;
reg err_flag_d1;
// reg err_flag_pos;
always @(posedge clk) begin
if (rst2 || rst_frame_sync) begin
err_flag <= 0;
end
else if (total_frames == 105 && bad_frames > 0) begin
err_flag <= 1;
end
err_flag_d1 <= err_flag;
err_flag_pos <= err_flag & ~err_flag_d1;
end
// ***** 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 (dagc_data_in_i), // width: 12
.probe3 (dagc_data_in_q), // 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