`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2019/12/25 14:19:40 // Design Name: // Module Name: Chn_Estimate // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module Chn_Estimate( input clk, input rst, //零域估计,默认值为8'd29 input [7:0] Zerozone_vio, //增强导频序列 input nd_pilot2, input [9:0] pilot_datai, input [9:0] pilot_dataq, //噪声估计结果 input nd_EstNoise, input [27:0] EstNoise_i, input [27:0] EstNoise_q, //fft核 input [25:0] fft_out_i, input [25:0] fft_out_q, input fft_out_nd, input [7:0] fft_index, output reg [16:0] fft_in_i = 17'd0, output reg [16:0] fft_in_q = 17'd0, output reg fft_in_nd = 1'd0, //ifft核 input [28:0] ifft_out_i, input [28:0] ifft_out_q, input ifft_out_nd, input [7:0] ifft_index, output reg [19:0] ifft_in_i = 20'd0, output reg [19:0] ifft_in_q = 20'd0, output reg ifft_in_nd = 1'd0, //信道估计两次fft输入完毕后拉高1clk output reg flag_ChnEstFFT_done = 1'd0, //MMSE信道估计结果RAM output reg write_MMSE_wea = 1'd0, output reg [7:0] addrin_MMSE = 8'd0, output reg [21:0] din_MMSE = 22'd0, //debug,溢出标志 output reg flagoverflow_fftpilot_26to14 = 1'd0, //第1个fft结果截位,即导频fft结果的截位,26截到14 output reg flagoverflow_ChnZF_26to18 = 1'd0, //第2个fft结果截位,即ZF信道估计结果的截位,26截到18 output reg flagoverflow_comdiv_34to20i = 1'd0, //第1个除法器结果截位,即复数除法结果的截位,得到没有去噪的ZF估计,34截到20 output reg flagoverflow_comdiv_34to20q = 1'd0, //第1个除法器结果截位,即复数除法结果的截位,得到没有去噪的ZF估计,34截到20 output reg flagoverflow_ifftzero_29to17i = 1'd0, //第1个ifft结果截位,即ZF零域估计处,结果先除掉低8位,29-8=21截到17 output reg flagoverflow_ifftzero_29to17q = 1'd0, //第1个ifft结果截位,即ZF零域估计处,结果先除掉低8位,29-8=21截到17 output reg flagoverflow_MMSEdiv_divisor_31to28 = 1'd0, //第2个除法器,即MMSE除法的分母截位,31截到28 output reg flagoverflow_divmmse_34to11 = 1'd0 //第2个除法器结果截位,即MMSE信道估计结果的截位,34截到11 ); //------------------------------------------------导频fft信息ROM--------------------------------------------// reg [7:0] addr_fft_piloti = 8'd0; wire[7:0] dout_fft_piloti; fft_pilot_real fft_pilot_real ( .clka(clk), // input wire clka .addra(addr_fft_piloti), // input wire [7 : 0] addra .douta(dout_fft_piloti) // output wire [7 : 0] douta ); reg [7:0] addr_fft_pilotq = 8'd0; wire[7:0] dout_fft_pilotq; fft_pilot_imag fft_pilot_imag ( .clka(clk), // input wire clka .addra(addr_fft_pilotq), // input wire [7 : 0] addra .douta(dout_fft_pilotq) // output wire [7 : 0] douta ); reg [7:0] addr_abs_pilot2 = 8'd0; wire[14:0] dout_abs_pilot2; abs_pilot2 abs_pilot2 ( .clka(clk), // input wire clka .addra(addr_abs_pilot2), // input wire [7 : 0] addra .douta(dout_abs_pilot2) // output wire [14 : 0] douta ); //------------------------------------------------复数除法器,分子计算,乘法部分延时1clk--------------------------------------------// reg [13:0] comdiv_ac_a = 14'd0; reg [7:0] comdiv_ac_c = 8'd0; wire[21:0] comdiv_ac_out; MUL_FDE ChnEst_comdiv_ac ( .CLK(clk), // input wire CLK .A(comdiv_ac_a), // input wire [13 : 0] A .B(comdiv_ac_c), // input wire [7 : 0] B .P(comdiv_ac_out) // output wire [21 : 0] P ); reg [13:0] comdiv_bd_b = 14'd0; reg [7:0] comdiv_bd_d = 8'd0; wire[21:0] comdiv_bd_out; MUL_FDE ChnEst_comdiv_bd ( .CLK(clk), // input wire CLK .A(comdiv_bd_b), // input wire [13 : 0] A .B(comdiv_bd_d), // input wire [7 : 0] B .P(comdiv_bd_out) // output wire [21 : 0] P ); reg [13:0] comdiv_bc_b = 14'd0; reg [7:0] comdiv_bc_c = 8'd0; wire[21:0] comdiv_bc_out; MUL_FDE ChnEst_comdiv_bc ( .CLK(clk), // input wire CLK .A(comdiv_bc_b), // input wire [13 : 0] A .B(comdiv_bc_c), // input wire [7 : 0] B .P(comdiv_bc_out) // output wire [21 : 0] P ); reg [13:0] comdiv_ad_a = 14'd0; reg [7:0] comdiv_ad_d = 8'd0; wire[21:0] comdiv_ad_out; MUL_FDE ChnEst_comdiv_ad ( .CLK(clk), // input wire CLK .A(comdiv_ad_a), // input wire [13 : 0] A .B(comdiv_ad_d), // input wire [7 : 0] B .P(comdiv_ad_out) // output wire [21 : 0] P ); reg [0:0] nd_comdiv_mulin = 1'd0; reg [0:0] nd_comdiv_mulout = 1'd0; always @(posedge clk) begin if(rst) begin nd_comdiv_mulout <= 1'd0; end else begin nd_comdiv_mulout <= nd_comdiv_mulin; end end //---------------------------------------------复数除法器,分子计算,加法+量化*256*7,共延时2clk------------------------------------------// reg [0:0] nd_comdiv_mulout_d1 = 1'd0; reg [22:0] comdiv_temp_ac_bd = 23'd0; reg [22:0] comdiv_temp_bc_ad = 23'd0; always @(posedge clk) begin if(rst) begin nd_comdiv_mulout_d1 <= 1'd0; comdiv_temp_ac_bd <= 23'd0; comdiv_temp_bc_ad <= 23'd0; end else begin if(nd_comdiv_mulout) begin nd_comdiv_mulout_d1 <= 1'd1; comdiv_temp_ac_bd <= {comdiv_ac_out[21],comdiv_ac_out} + {comdiv_bd_out[21],comdiv_bd_out}; comdiv_temp_bc_ad <= {comdiv_bc_out[21],comdiv_bc_out} - {comdiv_ad_out[21],comdiv_ad_out}; end else begin nd_comdiv_mulout_d1 <= 1'd0; comdiv_temp_ac_bd <= 23'd0; comdiv_temp_bc_ad <= 23'd0; end end end reg [0:0] nd_comdiv_mulout_d2 = 1'd0; reg [25:0] comdiv_temp_ac_bd2 = 26'd0; reg [25:0] comdiv_temp_bc_ad2 = 26'd0; always @(posedge clk) begin if(rst) begin nd_comdiv_mulout_d2 <= 1'd0; comdiv_temp_ac_bd2 <= 26'd0; comdiv_temp_bc_ad2 <= 26'd0; end else begin if(nd_comdiv_mulout_d1) begin nd_comdiv_mulout_d2 <= 1'd1; comdiv_temp_ac_bd2 <= {comdiv_temp_ac_bd,3'd0} - {{3{comdiv_temp_ac_bd[22]}},comdiv_temp_ac_bd}; comdiv_temp_bc_ad2 <= {comdiv_temp_bc_ad,3'd0} - {{3{comdiv_temp_bc_ad[22]}},comdiv_temp_bc_ad}; end else begin nd_comdiv_mulout_d2 <= 1'd0; comdiv_temp_ac_bd2 <= 26'd0; comdiv_temp_bc_ad2 <= 26'd0; end end end //------------------------------------------------除法器两个,复用(延时38clk)--------------------------------------------// //------------------------------------------------①复数除法器,除法计算--------------------------------------------// //------------------------------------------------②MMSE信道估计除法--------------------------------------------// reg dividerin_valid = 1'd0; reg [27:0] dividerin_divisor = 28'd0; reg [33:0] dividerin_dividend_i = 34'd0; wire dividerout_valid_i; wire[71:0] div_axis_dout_tdata_i; wire[33:0] dividerout_data_i; assign dividerout_data_i = div_axis_dout_tdata_i[65:32]; divider_ChnEst divider_ChnEst_i ( .aclk (clk), // input wire aclk .s_axis_divisor_tvalid (dividerin_valid), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata ({4'd0,dividerin_divisor}), // input wire [31 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid (dividerin_valid), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata ({6'd0,dividerin_dividend_i}), // input wire [39 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid (dividerout_valid_i), // output wire m_axis_dout_tvalid .m_axis_dout_tdata (div_axis_dout_tdata_i) // output wire [71 : 0] m_axis_dout_tdata ); reg [33:0] dividerin_dividend_q = 34'd0; wire dividerout_valid_q; wire[71:0] div_axis_dout_tdata_q; wire[33:0] dividerout_data_q; assign dividerout_data_q = div_axis_dout_tdata_q[65:32]; divider_ChnEst divider_ChnEst_q ( .aclk (clk), // input wire aclk .s_axis_divisor_tvalid (dividerin_valid), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata ({4'd0,dividerin_divisor}), // input wire [31 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid (dividerin_valid), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata ({6'd0,dividerin_dividend_q}), // input wire [39 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid (dividerout_valid_q), // output wire m_axis_dout_tvalid .m_axis_dout_tdata (div_axis_dout_tdata_q) // output wire [71 : 0] m_axis_dout_tdata ); //------------------------------------------信道估计部分共做两次fft,对其进行延时,并监测溢出情况------------------------------------------// reg [1:0] state_flag_overflow1 = 2'd0; reg [25:0] fft_out_i_d1 = 26'd0; reg [25:0] fft_out_q_d1 = 26'd0; reg fft_out_nd_d1 = 1'd0; always @(posedge clk) begin if(rst) begin state_flag_overflow1<= 2'd0; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; fft_out_nd_d1 <= 1'd0; flagoverflow_fftpilot_26to14 <= 1'd0; flagoverflow_ChnZF_26to18 <= 1'd0; end else begin case(state_flag_overflow1) //帧间复位结束后,等待第一个数据段的pilot数据nd,开始做fft 2'd0: begin flagoverflow_fftpilot_26to14 <= 1'd0; flagoverflow_ChnZF_26to18 <= 1'd0; if(nd_pilot2) begin state_flag_overflow1<= state_flag_overflow1 + 2'd1; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; fft_out_nd_d1 <= 1'd0; end else begin state_flag_overflow1<= state_flag_overflow1; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; fft_out_nd_d1 <= 1'd0; end end //第1段fft,输出最大允许14bit 2'd1: begin fft_out_i_d1 <= fft_out_i; fft_out_q_d1 <= fft_out_q; fft_out_nd_d1 <= fft_out_nd; if(fft_index==8'd255) state_flag_overflow1 <= state_flag_overflow1 + 2'd1; else state_flag_overflow1 <= state_flag_overflow1; if(fft_out_i[25:13]!=13'd8191&&fft_out_i[25:13]!=13'd0) flagoverflow_fftpilot_26to14 <= 1'd1; else begin if(fft_out_q[25:13]!=13'd8191&&fft_out_q[25:13]!=13'd0) flagoverflow_fftpilot_26to14 <= 1'd1; else flagoverflow_fftpilot_26to14 <= 1'd0; end flagoverflow_ChnZF_26to18 <= 1'd0; end //第2段fft,输出最大允许18bit 2'd2: begin fft_out_i_d1 <= fft_out_i; fft_out_q_d1 <= fft_out_q; fft_out_nd_d1 <= fft_out_nd; if(fft_index==8'd255) state_flag_overflow1 <= 2'd0; else state_flag_overflow1 <= state_flag_overflow1; if(fft_out_i[25:17]!=9'd511&&fft_out_i[25:17]!=9'd0) flagoverflow_ChnZF_26to18 <= 1'd1; else begin if(fft_out_q[25:17]!=9'd511&&fft_out_q[25:17]!=9'd0) flagoverflow_ChnZF_26to18 <= 1'd1; else flagoverflow_ChnZF_26to18 <= 1'd0; end flagoverflow_fftpilot_26to14 <= 1'd0; end default: state_flag_overflow1 <= 2'd0; endcase end end //-------------------------------------------------------------fft输入控制状态机---------------------------------------------------------------// //---------------------------------------顶层输入增强导频->①信道估计第一次fft的输入--------------------------------------// //-------------------------------------①信道估计第一次fft的输出->②复数除法分子乘法输入--------------------------------------// //-------------------------------------③信道估计第一次除法器的输出->④信道估计第一次ifft的输入--------------------------------------// //-------------------------------------④信道估计第一次ifft的输出->⑤信道估计第二次fft的输入--------------------------------------// //-------------------------------------⑤信道估计第二次fft的输出,截位--------------------------------------// reg [4:0] state_pilot_fft = 5'd0; reg [0:0] ChnEst_ZF_nd = 1'd0; //ZF信道估计结果 reg [17:0] ChnEst_ZF_i = 18'd0; reg [17:0] ChnEst_ZF_q = 18'd0; always @(posedge clk) begin if(rst) begin state_pilot_fft <= 5'd0; fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; addr_fft_piloti <= 8'd0; addr_fft_pilotq <= 8'd0; comdiv_ac_a <= 14'd0; comdiv_ac_c <= 8'd0; comdiv_bd_b <= 14'd0; comdiv_bd_d <= 8'd0; comdiv_bc_b <= 14'd0; comdiv_bc_c <= 8'd0; comdiv_ad_a <= 14'd0; comdiv_ad_d <= 8'd0; nd_comdiv_mulin <= 1'd0; ChnEst_ZF_nd <= 1'd0; ChnEst_ZF_i <= 18'd0; ChnEst_ZF_q <= 18'd0; flagoverflow_ifftzero_29to17i <= 1'd0; flagoverflow_ifftzero_29to17q <= 1'd0; flag_ChnEstFFT_done <= 1'd0; end else begin case(state_pilot_fft) //帧间复位结束后,等待第一个数据段的pilot数据nd,开始做fft 5'd0: begin if(nd_pilot2) begin fft_in_i <= {{7{pilot_datai[9]}},pilot_datai}; fft_in_q <= {{7{pilot_dataq[9]}},pilot_dataq}; fft_in_nd <= 1'd1; state_pilot_fft <= state_pilot_fft + 5'd1; end else begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; state_pilot_fft <= state_pilot_fft; end end //等待256点的fft输入完毕 5'd1: begin if(nd_pilot2==1'd0) begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; state_pilot_fft <= state_pilot_fft + 5'd1; end else begin fft_in_i <= {{7{pilot_datai[9]}},pilot_datai}; fft_in_q <= {{7{pilot_dataq[9]}},pilot_dataq}; fft_in_nd <= 1'd1; state_pilot_fft <= state_pilot_fft; end addr_fft_piloti <= 8'd0; addr_fft_pilotq <= 8'd0; end //等待fft结果到达 5'd2: begin if(fft_out_nd) begin addr_fft_piloti <= addr_fft_piloti + 8'd1; addr_fft_pilotq <= addr_fft_pilotq + 8'd1; state_pilot_fft <= state_pilot_fft + 5'd1; end else begin addr_fft_piloti <= 8'd0; addr_fft_pilotq <= 8'd0; state_pilot_fft <= state_pilot_fft; end nd_comdiv_mulin <= 1'd0; end //等待fft结果到达后,送入复数除法的实数乘法部分 5'd3: begin nd_comdiv_mulin <= fft_out_nd_d1; if(fft_out_nd_d1==1'd0) begin addr_fft_piloti <= 8'd0; addr_fft_pilotq <= 8'd0; comdiv_ac_a <= 14'd0; comdiv_ac_c <= 8'd0; comdiv_bd_b <= 14'd0; comdiv_bd_d <= 8'd0; comdiv_bc_b <= 14'd0; comdiv_bc_c <= 8'd0; comdiv_ad_a <= 14'd0; comdiv_ad_d <= 8'd0; state_pilot_fft <= state_pilot_fft + 5'd1; end else begin addr_fft_piloti <= addr_fft_piloti + 8'd1; addr_fft_pilotq <= addr_fft_pilotq + 8'd1; comdiv_ac_a <= fft_out_i_d1[13:0]; //根据仿真结果,fft结果最多14bit有符号数 comdiv_ac_c <= dout_fft_piloti; comdiv_bd_b <= fft_out_q_d1[13:0]; comdiv_bd_d <= dout_fft_pilotq; comdiv_bc_b <= fft_out_q_d1[13:0]; comdiv_bc_c <= dout_fft_piloti; comdiv_ad_a <= fft_out_i_d1[13:0]; comdiv_ad_d <= dout_fft_pilotq; state_pilot_fft <= state_pilot_fft; end end //等待ifft结果到达,将结果直接给回fft模块的输入,做第二次fft(根据仿真,只保留低17bit) 5'd4: begin nd_comdiv_mulin <= 1'd0; if(ifft_out_nd) begin fft_in_nd <= 1'd1; state_pilot_fft <= state_pilot_fft + 5'd1; if(ifft_out_i[28:24]!=5'd31&&ifft_out_i[28:24]!=5'd0) begin flagoverflow_ifftzero_29to17i <= 1'd1; fft_in_i <= (ifft_out_i[28])? 17'b1_0000_0000_0000_0000 : 17'b0_1111_1111_1111_1111; end else begin flagoverflow_ifftzero_29to17i <= 1'd0; fft_in_i <= ifft_out_i[24:8]; end if(ifft_out_q[28:24]!=5'd31&&ifft_out_q[28:24]!=5'd0) begin flagoverflow_ifftzero_29to17q <= 1'd1; fft_in_q <= (ifft_out_q[28])? 17'b1_0000_0000_0000_0000 : 17'b0_1111_1111_1111_1111; end else begin flagoverflow_ifftzero_29to17q <= 1'd0; fft_in_q <= ifft_out_q[24:8]; end end else begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; state_pilot_fft <= state_pilot_fft; flagoverflow_ifftzero_29to17i <= 1'd0; flagoverflow_ifftzero_29to17q <= 1'd0; end end //零域估计,去噪 5'd5: begin if(ifft_index>=Zerozone_vio) begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd1; state_pilot_fft <= state_pilot_fft + 5'd1; flagoverflow_ifftzero_29to17i <= 1'd0; flagoverflow_ifftzero_29to17q <= 1'd0; end else begin fft_in_nd <= 1'd1; state_pilot_fft <= state_pilot_fft; if(ifft_out_i[28:24]!=5'd31&&ifft_out_i[28:24]!=5'd0) begin flagoverflow_ifftzero_29to17i <= 1'd1; fft_in_i <= (ifft_out_i[28])? 17'b1_0000_0000_0000_0000 : 17'b0_1111_1111_1111_1111; end else begin flagoverflow_ifftzero_29to17i <= 1'd0; fft_in_i <= ifft_out_i[24:8]; end if(ifft_out_q[28:24]!=5'd31&&ifft_out_q[28:24]!=5'd0) begin flagoverflow_ifftzero_29to17q <= 1'd1; fft_in_q <= (ifft_out_q[28])? 17'b1_0000_0000_0000_0000 : 17'b0_1111_1111_1111_1111; end else begin flagoverflow_ifftzero_29to17q <= 1'd0; fft_in_q <= ifft_out_q[24:8]; end end flag_ChnEstFFT_done <= 1'd0; end //等待全部256个点第二次输入fft核 5'd6: begin if(ifft_out_nd==1'd0) begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; state_pilot_fft <= state_pilot_fft + 5'd1; flag_ChnEstFFT_done <= 1'd1; end else begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd1; state_pilot_fft <= state_pilot_fft; flag_ChnEstFFT_done <= 1'd0; end flagoverflow_ifftzero_29to17i <= 1'd0; flagoverflow_ifftzero_29to17q <= 1'd0; end //等待第二次fft的结果,即ZF信道估计结果(只保留低18bit),将其单独缓存,用于计算MMSE信道估计 5'd7: begin if(fft_out_nd_d1) begin ChnEst_ZF_nd <= 1'd1; ChnEst_ZF_i <= fft_out_i_d1[17:0]; ChnEst_ZF_q <= -fft_out_q_d1[17:0]; state_pilot_fft <= state_pilot_fft + 5'd1; end else begin ChnEst_ZF_nd <= 1'd0; ChnEst_ZF_i <= 18'd0; ChnEst_ZF_q <= 18'd0; state_pilot_fft <= state_pilot_fft; end flag_ChnEstFFT_done <= 1'd0; end //等待第二次fft的结果全部输出,状态机转回状态0等待下一段导频 5'd8: begin if(fft_out_nd_d1==1'd0) begin ChnEst_ZF_nd <= 1'd0; ChnEst_ZF_i <= 18'd0; ChnEst_ZF_q <= 18'd0; state_pilot_fft <= 5'd0; end else begin ChnEst_ZF_nd <= 1'd1; ChnEst_ZF_i <= fft_out_i_d1[17:0]; ChnEst_ZF_q <= -fft_out_q_d1[17:0]; state_pilot_fft <= state_pilot_fft; end flag_ChnEstFFT_done <= 1'd0; end default: state_pilot_fft <= 5'd0; endcase end end //--------------------------------------------------------ifft输入控制状态机----------------------------------------------------------// //-------------------------------------③信道估计第一次除法器的输出->④信道估计第一次ifft的输入--------------------------------------// reg [1:0] state_pilot_ifft = 2'd0; always @(posedge clk) begin if(rst) begin state_pilot_ifft <= 2'd0; ifft_in_i <= 20'd0; ifft_in_q <= 20'd0; ifft_in_nd <= 1'd0; flagoverflow_comdiv_34to20i <= 1'd0; flagoverflow_comdiv_34to20q <= 1'd0; end else begin case(state_pilot_ifft) //帧间复位结束后,等待第一个数据段的pilot数据nd 2'd0: begin if(nd_pilot2) begin state_pilot_ifft <= state_pilot_ifft + 2'd1; end else begin state_pilot_ifft <= state_pilot_ifft; end end //等待③信道估计第一次除法器的输出 2'd1: begin if(dividerout_valid_i) begin ifft_in_nd <= 1'd1; state_pilot_ifft <= state_pilot_ifft + 2'd1; if(dividerout_data_i[33:19]!=15'd32767&÷rout_data_i[33:19]!=15'd0) begin flagoverflow_comdiv_34to20i <= 1'd1; ifft_in_i <= (dividerout_data_i[33])? 20'b1000_0000_0000_0000_0000 : 20'b0111_1111_1111_1111_1111; end else begin flagoverflow_comdiv_34to20i <= 1'd0; ifft_in_i <= dividerout_data_i[19:0]; end if(dividerout_data_q[33:19]!=15'd32767&÷rout_data_q[33:19]!=15'd0) begin flagoverflow_comdiv_34to20q <= 1'd1; ifft_in_q <= (dividerout_data_q[33])? 20'b1000_0000_0000_0000_0000 : 20'b0111_1111_1111_1111_1111; end else begin flagoverflow_comdiv_34to20q <= 1'd0; ifft_in_q <= dividerout_data_q[19:0]; end end else begin ifft_in_i <= 20'd0; ifft_in_q <= 20'd0; ifft_in_nd <= 1'd0; state_pilot_ifft <= state_pilot_ifft; flagoverflow_comdiv_34to20i <= 1'd0; flagoverflow_comdiv_34to20q <= 1'd0; end end //等待256点的ifft输入完毕 2'd2: begin if(dividerout_valid_i==1'd0) begin ifft_in_i <= 20'd0; ifft_in_q <= 20'd0; ifft_in_nd <= 1'd0; state_pilot_ifft <= 2'd0; flagoverflow_comdiv_34to20i <= 1'd0; flagoverflow_comdiv_34to20q <= 1'd0; end else begin ifft_in_nd <= 1'd1; state_pilot_ifft <= state_pilot_ifft; if(dividerout_data_i[33:19]!=15'd32767&÷rout_data_i[33:19]!=15'd0) begin flagoverflow_comdiv_34to20i <= 1'd1; ifft_in_i <= (dividerout_data_i[33])? 20'b1000_0000_0000_0000_0000 : 20'b0111_1111_1111_1111_1111; end else begin flagoverflow_comdiv_34to20i <= 1'd0; ifft_in_i <= dividerout_data_i[19:0]; end if(dividerout_data_q[33:19]!=15'd32767&÷rout_data_q[33:19]!=15'd0) begin flagoverflow_comdiv_34to20q <= 1'd1; ifft_in_q <= (dividerout_data_q[33])? 20'b1000_0000_0000_0000_0000 : 20'b0111_1111_1111_1111_1111; end else begin flagoverflow_comdiv_34to20q <= 1'd0; ifft_in_q <= dividerout_data_q[19:0]; end end end default: state_pilot_ifft <= 2'd0; endcase end end //---------------------------------------ZF->MMSE信道估计的计算(除法分母部分);对齐分母分子时序----------------------------------------// wire abs_ZF_nd; wire [18:0] abs_ZF; ApproxAbs_18bit ApproxAbs_18bit ( .clk (clk), .ND (ChnEst_ZF_nd), .Din_I (ChnEst_ZF_i), .Din_Q (ChnEst_ZF_q), .Rdy (abs_ZF_nd), .Dout (abs_ZF) ); reg squ_abs_ZF_nd = 1'd0; wire [29:0] squ_abs_ZF; squ_abs_ZF squ_abs_ZF1 ( .CLK (clk), // input wire CLK .A (abs_ZF[18:4]), // input wire [14 : 0] A .B (abs_ZF[18:4]), // input wire [14 : 0] B .P (squ_abs_ZF) // output wire [29 : 0] P ); always @(posedge clk) begin if(rst) squ_abs_ZF_nd <= 1'd0; else squ_abs_ZF_nd <= abs_ZF_nd; end reg div_MMSE_nd = 1'd0; reg [30:0] div_MMSE = 31'd0; always @(posedge clk) begin if(rst) begin div_MMSE_nd <= 1'd0; div_MMSE <= 31'd0; end else begin if(squ_abs_ZF_nd) begin div_MMSE_nd <= 1'd1; div_MMSE <= {{3{EstNoise_i[27]}},EstNoise_i} + {squ_abs_ZF[29],squ_abs_ZF}; end else begin div_MMSE_nd <= 1'd0; div_MMSE <= 31'd0; end end end //除法器分母根据仿真结果截位到28bit位宽,同时设置溢出标志用于监测 reg div2_MMSE_nd = 1'd0; reg [27:0] div2_MMSE = 28'd0; always @(posedge clk) begin if(rst) begin div2_MMSE_nd <= 1'd0; div2_MMSE <= 28'd0; flagoverflow_MMSEdiv_divisor_31to28 <= 1'd0; end else begin if(div_MMSE_nd) begin div2_MMSE_nd <= 1'd1; if(div_MMSE[30:27]==4'd0||div_MMSE[30:27]==4'd15) begin flagoverflow_MMSEdiv_divisor_31to28 <= 1'd0; div2_MMSE <= div_MMSE[27:0]; end else begin flagoverflow_MMSEdiv_divisor_31to28 <= 1'd1; div2_MMSE <= (div_MMSE[30])? 28'b1000_0000_0000_0000_0000_0000_0000: 28'b0111_1111_1111_1111_1111_1111_1111; end end else begin div2_MMSE_nd <= 1'd0; div2_MMSE <= 28'd0; flagoverflow_MMSEdiv_divisor_31to28 <= 1'd0; end end end //总共6+1+1+1=9clk延时,缓存ChnEst_ZF_i/q reg [0:0] ChnEst_ZF_nd_d1 = 1'd0; reg [0:0] ChnEst_ZF_nd_d2 = 1'd0; reg [0:0] ChnEst_ZF_nd_d3 = 1'd0; reg [0:0] ChnEst_ZF_nd_d4 = 1'd0; reg [0:0] ChnEst_ZF_nd_d5 = 1'd0; reg [0:0] ChnEst_ZF_nd_d6 = 1'd0; reg [0:0] ChnEst_ZF_nd_d7 = 1'd0; reg [0:0] ChnEst_ZF_nd_d8 = 1'd0; reg [0:0] ChnEst_ZF_nd_d9 = 1'd0; reg [17:0] ChnEst_ZF_i_d1 = 18'd0; reg [17:0] ChnEst_ZF_i_d2 = 18'd0; reg [17:0] ChnEst_ZF_i_d3 = 18'd0; reg [17:0] ChnEst_ZF_i_d4 = 18'd0; reg [17:0] ChnEst_ZF_i_d5 = 18'd0; reg [17:0] ChnEst_ZF_i_d6 = 18'd0; reg [17:0] ChnEst_ZF_i_d7 = 18'd0; reg [17:0] ChnEst_ZF_i_d8 = 18'd0; reg [17:0] ChnEst_ZF_i_d9 = 18'd0; reg [17:0] ChnEst_ZF_q_d1 = 18'd0; reg [17:0] ChnEst_ZF_q_d2 = 18'd0; reg [17:0] ChnEst_ZF_q_d3 = 18'd0; reg [17:0] ChnEst_ZF_q_d4 = 18'd0; reg [17:0] ChnEst_ZF_q_d5 = 18'd0; reg [17:0] ChnEst_ZF_q_d6 = 18'd0; reg [17:0] ChnEst_ZF_q_d7 = 18'd0; reg [17:0] ChnEst_ZF_q_d8 = 18'd0; reg [17:0] ChnEst_ZF_q_d9 = 18'd0; always @(posedge clk) begin if(rst) begin ChnEst_ZF_nd_d1 <= 1'd0; ChnEst_ZF_nd_d2 <= 1'd0; ChnEst_ZF_nd_d3 <= 1'd0; ChnEst_ZF_nd_d4 <= 1'd0; ChnEst_ZF_nd_d5 <= 1'd0; ChnEst_ZF_nd_d6 <= 1'd0; ChnEst_ZF_nd_d7 <= 1'd0; ChnEst_ZF_nd_d8 <= 1'd0; ChnEst_ZF_nd_d9 <= 1'd0; ChnEst_ZF_i_d1 <= 18'd0; ChnEst_ZF_i_d2 <= 18'd0; ChnEst_ZF_i_d3 <= 18'd0; ChnEst_ZF_i_d4 <= 18'd0; ChnEst_ZF_i_d5 <= 18'd0; ChnEst_ZF_i_d6 <= 18'd0; ChnEst_ZF_i_d7 <= 18'd0; ChnEst_ZF_i_d8 <= 18'd0; ChnEst_ZF_i_d9 <= 18'd0; ChnEst_ZF_q_d1 <= 18'd0; ChnEst_ZF_q_d2 <= 18'd0; ChnEst_ZF_q_d3 <= 18'd0; ChnEst_ZF_q_d4 <= 18'd0; ChnEst_ZF_q_d5 <= 18'd0; ChnEst_ZF_q_d6 <= 18'd0; ChnEst_ZF_q_d7 <= 18'd0; ChnEst_ZF_q_d8 <= 18'd0; ChnEst_ZF_q_d9 <= 18'd0; end else begin ChnEst_ZF_nd_d1 <= ChnEst_ZF_nd; ChnEst_ZF_nd_d2 <= ChnEst_ZF_nd_d1; ChnEst_ZF_nd_d3 <= ChnEst_ZF_nd_d2; ChnEst_ZF_nd_d4 <= ChnEst_ZF_nd_d3; ChnEst_ZF_nd_d5 <= ChnEst_ZF_nd_d4; ChnEst_ZF_nd_d6 <= ChnEst_ZF_nd_d5; ChnEst_ZF_nd_d7 <= ChnEst_ZF_nd_d6; ChnEst_ZF_nd_d8 <= ChnEst_ZF_nd_d7; ChnEst_ZF_nd_d9 <= ChnEst_ZF_nd_d8; ChnEst_ZF_i_d1 <= ChnEst_ZF_i; ChnEst_ZF_i_d2 <= ChnEst_ZF_i_d1; ChnEst_ZF_i_d3 <= ChnEst_ZF_i_d2; ChnEst_ZF_i_d4 <= ChnEst_ZF_i_d3; ChnEst_ZF_i_d5 <= ChnEst_ZF_i_d4; ChnEst_ZF_i_d6 <= ChnEst_ZF_i_d5; ChnEst_ZF_i_d7 <= ChnEst_ZF_i_d6; ChnEst_ZF_i_d8 <= ChnEst_ZF_i_d7; ChnEst_ZF_i_d9 <= ChnEst_ZF_i_d8; ChnEst_ZF_q_d1 <= ChnEst_ZF_q; ChnEst_ZF_q_d2 <= ChnEst_ZF_q_d1; ChnEst_ZF_q_d3 <= ChnEst_ZF_q_d2; ChnEst_ZF_q_d4 <= ChnEst_ZF_q_d3; ChnEst_ZF_q_d5 <= ChnEst_ZF_q_d4; ChnEst_ZF_q_d6 <= ChnEst_ZF_q_d5; ChnEst_ZF_q_d7 <= ChnEst_ZF_q_d6; ChnEst_ZF_q_d8 <= ChnEst_ZF_q_d7; ChnEst_ZF_q_d9 <= ChnEst_ZF_q_d8; end end //-------------------------------------------------------------控制状态机---------------------------------------------------------------// //-------------------------------------②复数除法分子乘法输出->③信道估计第一次除法器的输入--------------------------------------// //---------------------⑤信道估计第二次fft的输出->MMSE信道估计的计算(除法分母部分)->⑥信道估计第二次除法器的输入-----------------------// reg [4:0] state_pilot_div = 5'd0; always @(posedge clk) begin if(rst) begin state_pilot_div <= 5'd0; addr_abs_pilot2 <= 8'd0; dividerin_valid <= 1'd0; dividerin_divisor <= 28'd0; dividerin_dividend_i<= 34'd0; dividerin_dividend_q<= 34'd0; end else begin case(state_pilot_div) //帧间复位结束后,等待数据段的pilot数据nd 5'd0: begin if(nd_pilot2) begin state_pilot_div <= state_pilot_div + 5'd1; end else begin state_pilot_div <= state_pilot_div; end dividerin_valid <= 1'd0; dividerin_divisor <= 28'd0; dividerin_dividend_i <= 34'd0; dividerin_dividend_q <= 34'd0; end //等待第一次乘法器的输出有效信号,此时结果是复数除法的分子nd前一clk 5'd1: begin if(nd_comdiv_mulout_d1) begin addr_abs_pilot2 <= addr_abs_pilot2 + 8'd1; state_pilot_div <= state_pilot_div + 5'd1; end else begin addr_abs_pilot2 <= 8'd0; state_pilot_div <= state_pilot_div; end dividerin_valid <= 1'd0; dividerin_divisor <= 28'd0; dividerin_dividend_i <= 34'd0; dividerin_dividend_q <= 34'd0; end //复数除法的分子nd结束后,转入下一状态,等待 5'd2: begin if(nd_comdiv_mulout_d2==1'd0) begin addr_abs_pilot2 <= 8'd0; dividerin_valid <= 1'd0; dividerin_divisor <= 28'd0; dividerin_dividend_i <= 34'd0; dividerin_dividend_q <= 34'd0; state_pilot_div <= state_pilot_div + 5'd1; end else begin addr_abs_pilot2 <= addr_abs_pilot2 + 8'd1; dividerin_valid <= 1'd1; dividerin_divisor <= {{13{dout_abs_pilot2[14]}},dout_abs_pilot2}; dividerin_dividend_i <= {comdiv_temp_ac_bd2,8'd0}; dividerin_dividend_q <= {comdiv_temp_bc_ad2,8'd0}; state_pilot_div <= state_pilot_div; end end //等待div2_MMSE_nd,即MMSE信道估计除法的分子分母准备好的nd,开始向除法器中第二次给输入 5'd3: begin if(div2_MMSE_nd) begin dividerin_valid <= 1'd1; dividerin_divisor <= div2_MMSE; dividerin_dividend_i <= {{4{ChnEst_ZF_i_d9[17]}},ChnEst_ZF_i_d9,12'd0}; dividerin_dividend_q <= {{4{ChnEst_ZF_q_d9[17]}},ChnEst_ZF_q_d9,12'd0}; state_pilot_div <= state_pilot_div + 5'd1; end else begin dividerin_valid <= 1'd0; dividerin_divisor <= 28'd0; dividerin_dividend_i <= 34'd0; dividerin_dividend_q <= 34'd0; state_pilot_div <= state_pilot_div; end end //等待除法器中第二次给输入结束 5'd4: begin if(div2_MMSE_nd==1'd0) begin dividerin_valid <= 1'd0; dividerin_divisor <= 28'd0; dividerin_dividend_i <= 34'd0; dividerin_dividend_q <= 34'd0; state_pilot_div <= 5'd0; end else begin dividerin_valid <= 1'd1; dividerin_divisor <= div2_MMSE; dividerin_dividend_i <= {{4{ChnEst_ZF_i_d9[17]}},ChnEst_ZF_i_d9,12'd0}; dividerin_dividend_q <= {{4{ChnEst_ZF_q_d9[17]}},ChnEst_ZF_q_d9,12'd0}; state_pilot_div <= state_pilot_div; end end default: state_pilot_div <= 5'd0; endcase end end //-------------------------------------------------------------控制状态机---------------------------------------------------------------// //-------------------------------------⑥信道估计第二次除法器的输出,此时为MMSE的结果,截位后保存在rom中--------------------------------// //--------------------------------------------------------截位设置溢出标志,保留低11bit--------------------------------// reg div2_out_ce = 1'd0; always @(posedge clk) begin if(rst) begin div2_out_ce <= 1'd0; write_MMSE_wea <= 1'd0; addrin_MMSE <= 8'd255; din_MMSE <= 22'd0; flagoverflow_divmmse_34to11 <= 1'd0; end else begin if(div2_out_ce==1'd0) begin if(div2_MMSE_nd) begin div2_out_ce <= 1'd1; end else begin div2_out_ce <= 1'd0; end write_MMSE_wea <= 1'd0; addrin_MMSE <= 8'd255; din_MMSE <= 22'd0; flagoverflow_divmmse_34to11 <= 1'd0; end else begin if(dividerout_valid_i) begin if(addrin_MMSE==8'd254) div2_out_ce <= 1'd0; else div2_out_ce <= 1'd1; write_MMSE_wea <= 1'd1; addrin_MMSE <= addrin_MMSE + 8'd1; din_MMSE <= {dividerout_data_q[10:0],dividerout_data_i[10:0]}; if(dividerout_data_i[33:10]!=24'd16777215&÷rout_data_i[33:10]!=24'd0) flagoverflow_divmmse_34to11 <= 1'd1; else begin if(dividerout_data_q[33:10]!=24'd16777215&÷rout_data_q[33:10]!=24'd0) flagoverflow_divmmse_34to11 <= 1'd1; else flagoverflow_divmmse_34to11 <= 1'd0; end end else begin div2_out_ce <= div2_out_ce; write_MMSE_wea <= 1'd0; addrin_MMSE <= 8'd255; din_MMSE <= 22'd0; flagoverflow_divmmse_34to11 <= 1'd0; end end end end //------------------------------------------------------仿真文件保存---------------------------------------------------// // integer handle01; // integer handle02; // integer handle03; // integer handle04; // reg enable1 = 0; // initial begin // handle01=$fopen("din_MMSEi.txt","w"); $fclose(handle01); // handle02=$fopen("din_MMSEq.txt","w"); $fclose(handle02); // handle03=$fopen("dividerout_data_i.txt","w"); $fclose(handle03); // handle04=$fopen("dividerout_data_q.txt","w"); $fclose(handle04); // #10; // enable1 = 1; // end // always@(posedge clk)begin // if(enable1)begin // if(write_MMSE_wea)begin // handle01=$fopen("din_MMSEi.txt","a+");$fwrite(handle01,"%d\n",$signed(din_MMSE[10:0]));$fclose(handle01); // handle02=$fopen("din_MMSEq.txt","a+");$fwrite(handle02,"%d\n",$signed(din_MMSE[21:11]));$fclose(handle02); // end // if(dividerout_valid_i)begin // handle03=$fopen("dividerout_data_i.txt","a+");$fwrite(handle03,"%d\n",$signed(dividerout_data_i));$fclose(handle03); // handle04=$fopen("dividerout_data_q.txt","a+");$fwrite(handle04,"%d\n",$signed(dividerout_data_q));$fclose(handle04); // end // end // end endmodule