`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/01/04 21:09:20 // Design Name: // Module Name: data_equalizer // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module data_equalizer( input clk, input rst, input EQUenable_vio, input nd_pilot2, input flag_ChnEstFFT_done, //信道估计两次fft输入完毕后拉高1clk(Chn_Estimate给出) //数据的fifo,4个 input [9:0] dout_data1i, input [9:0] dout_data1q, output reg rd_en_data1 = 1'd0, input [9:0] dout_data2i, input [9:0] dout_data2q, output reg rd_en_data2 = 1'd0, input flag_dataow, //拉高1clk,说明一段数据ow存储完毕,后端可开始连续读取 //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, //MMSE信道估计结果RAM output reg [7:0] addrout_MMSE = 8'd0, input [21:0] dout_MMSE, //均衡结果输出 output reg nd_SC_FDE_dout = 1'd0, output reg [9:0] SC_FDE_douti = 10'd0, output reg [9:0] SC_FDE_doutq = 10'd0, //debug,溢出标志 output reg flagoverflow_ifftindata_28to20i = 1'd0, //均衡完毕后(频域结果)的截位,即乘法器输出结果的截位,28截到20 output reg flagoverflow_ifftindata_28to20q = 1'd0, //均衡完毕后(频域结果)的截位,即乘法器输出结果的截位,28截到20 output reg flagoverflow_fftdata_26to16i = 1'd0, //数据段ow的fft输出截位,26截到16 output reg flagoverflow_fftdata_26to16q = 1'd0, //数据段ow的fft输出截位,26截到16 output reg flagoverflow_FDE_dataout_29to10i = 1'd0, //ifft结果截位,即均衡结果处,结果先除掉低8位,29-7=22截到10 output reg flagoverflow_FDE_dataout_29to10q = 1'd0 //ifft结果截位,即均衡结果处,结果先除掉低8位,29-7=22截到10 ); //----------------------------------------------------fft的输入控制状态机---------------------------------------------------------// reg [3:0] state_fftin = 4'd0; reg [7:0] cnt_256 = 8'd0; always @(posedge clk)begin if(rst)begin state_fftin <= 4'd0; cnt_256 <= 8'd0; rd_en_data1 <= 1'd0; rd_en_data2 <= 1'd0; fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; end else begin case(state_fftin) //帧间复位结束后,等待nd_pilot2,即导频部分全部到达 4'd0:begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; if(nd_pilot2) state_fftin <= state_fftin + 4'd1; else state_fftin <= state_fftin; end //等待flag_ChnEstFFT_done,即信道估计的两次fft输入全部完成 4'd1:begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; if(flag_ChnEstFFT_done) state_fftin <= state_fftin + 4'd1; else state_fftin <= state_fftin; end //计数60clk,开始输入第一组data的ow给fft,保证其输出的时候MMSE信道估计结果已全部准备完毕 4'd2:begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; rd_en_data2 <= 1'd0; if(cnt_256==8'd60) begin rd_en_data1 <= 1'd1; cnt_256 <= 8'd0; state_fftin <= state_fftin + 4'd1; end else begin rd_en_data1 <= 1'd0; cnt_256 <= cnt_256 + 8'd1; state_fftin <= state_fftin; end end //从rd_en_data1为1的第一个clk开始,输出第0组数据。rd_en_data1保持有效共需256clk,即最后一个clk的数据出到出口时仍需一个读nd(用于读空fifo) 4'd3:begin rd_en_data2 <= 1'd0; if(cnt_256==8'd254) begin rd_en_data1 <= 1'd1; fft_in_i <= {{7{dout_data1i[9]}},dout_data1i}; fft_in_q <= {{7{dout_data1q[9]}},dout_data1q}; fft_in_nd <= 1'd1; cnt_256 <= 6'd0; state_fftin <= state_fftin + 4'd1; end else begin rd_en_data1 <= 1'd1; fft_in_i <= {{7{dout_data1i[9]}},dout_data1i}; fft_in_q <= {{7{dout_data1q[9]}},dout_data1q}; fft_in_nd <= 1'd1; cnt_256 <= cnt_256 + 6'd1; state_fftin <= state_fftin; end end 4'd4:begin rd_en_data2 <= 1'd0; rd_en_data1 <= 1'd0; fft_in_i <= {{7{dout_data1i[9]}},dout_data1i}; fft_in_q <= {{7{dout_data1q[9]}},dout_data1q}; fft_in_nd <= 1'd1; cnt_256 <= 6'd0; state_fftin <= state_fftin + 4'd1; end //data1读空,等待flag_dataow,说明下一个256数据段缓存完毕,可以取用 4'd5:begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; rd_en_data1 <= 1'd0; cnt_256 <= 8'd0; if(flag_dataow) begin rd_en_data2 <= 1'd1; state_fftin <= state_fftin + 4'd1; end else begin rd_en_data2 <= 1'd0; state_fftin <= state_fftin; end end //从rd_en_data2为1的第一个clk开始,输出第0组数据。rd_en_data2保持有效共需256clk,即最后一个clk的数据出到出口时仍需一个读nd(用于读空fifo) 4'd6:begin rd_en_data1 <= 1'd0; if(cnt_256==8'd254) begin rd_en_data2 <= 1'd1; fft_in_i <= {{7{dout_data2i[9]}},dout_data2i}; fft_in_q <= {{7{dout_data2q[9]}},dout_data2q}; fft_in_nd <= 1'd1; cnt_256 <= 6'd0; state_fftin <= state_fftin + 4'd1; end else begin rd_en_data2 <= 1'd1; fft_in_i <= {{7{dout_data2i[9]}},dout_data2i}; fft_in_q <= {{7{dout_data2q[9]}},dout_data2q}; fft_in_nd <= 1'd1; cnt_256 <= cnt_256 + 6'd1; state_fftin <= state_fftin; end end 4'd7:begin rd_en_data2 <= 1'd0; rd_en_data1 <= 1'd0; fft_in_i <= {{7{dout_data2i[9]}},dout_data2i}; fft_in_q <= {{7{dout_data2q[9]}},dout_data2q}; fft_in_nd <= 1'd1; cnt_256 <= 6'd0; state_fftin <= state_fftin + 4'd1; end //data2读空,等待flag_dataow,说明下一个256数据段缓存完毕,可以取用;或等待nd_pilot2,说明本数据段结束,下一数据段的导频缓存完毕 4'd8:begin fft_in_i <= 17'd0; fft_in_q <= 17'd0; fft_in_nd <= 1'd0; rd_en_data2 <= 1'd0; cnt_256 <= 8'd0; if(flag_dataow) begin rd_en_data1 <= 1'd1; state_fftin <= 4'd3; end else begin if(nd_pilot2) begin rd_en_data1 <= 1'd0; state_fftin <= 4'd1; end else begin rd_en_data1 <= 1'd0; state_fftin <= state_fftin; end end end default:state_fftin <= 4'd0; endcase end end //----------------------------------------------------fft的输出控制状态机---------------------------------------------------------// reg [1:0] state_fftout = 2'd0; reg fft_out_nd_d1 = 1'd0; reg [25:0] fft_out_i_d1 = 26'd0; reg [25:0] fft_out_q_d1 = 26'd0; always @(posedge clk)begin if(rst)begin state_fftout <= 2'd0; fft_out_nd_d1 <= 1'd0; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; end else begin case(state_fftout) //帧间复位结束后,等待nd_pilot2,即导频部分全部到达 2'd0:begin fft_out_nd_d1 <= 1'd0; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; if(nd_pilot2) state_fftout <= state_fftout + 2'd1; else state_fftout <= state_fftout; end //等待flag_ChnEstFFT_done,即信道估计的两次fft输入全部完成 2'd1:begin fft_out_nd_d1 <= 1'd0; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; if(flag_ChnEstFFT_done) state_fftout <= state_fftout + 2'd1; else state_fftout <= state_fftout; end //等待第一组fft结果输出完毕。此组结果应为信道估计的第二次fft结果,本模块不取用 2'd2:begin fft_out_nd_d1 <= 1'd0; fft_out_i_d1 <= 26'd0; fft_out_q_d1 <= 26'd0; if(fft_index==8'd255) state_fftout <= state_fftout + 2'd1; else state_fftout <= state_fftout; end //fft_out_nd指示fft结果有效。将fft输出延时1clk。nd_pilot2有效说明下一帧的导频部分输入完毕,转回状态1 2'd3:begin fft_out_nd_d1 <= fft_out_nd; fft_out_i_d1 <= fft_out_i; fft_out_q_d1 <= fft_out_q; if(nd_pilot2) state_fftout <= 2'd1; else state_fftout <= state_fftout; end endcase end end //----------------------------------------------------复数乘法器+输出截位及溢出标志---------------------------------------------------------// reg mulin_nd = 1'd0; reg [15:0] mulin_ai = 16'd0; reg [15:0] mulin_aq = 16'd0; reg [10:0] mulin_bi = 11'd0; reg [10:0] mulin_bq = 11'd0; wire mulout_nd; wire[63:0] mulout_data; SC_FDE_commul SC_FDE_commul ( .aclk (clk), // input wire aclk .s_axis_a_tvalid (mulin_nd), // input wire s_axis_a_tvalid .s_axis_a_tdata ({mulin_aq,mulin_ai}), // input wire [31 : 0] s_axis_a_tdata .s_axis_b_tvalid (mulin_nd), // input wire s_axis_b_tvalid .s_axis_b_tdata ({5'd0,mulin_bq,5'd0,mulin_bi}), // input wire [31 : 0] s_axis_b_tdata .m_axis_dout_tvalid (mulout_nd), // output wire m_axis_dout_tvalid .m_axis_dout_tdata (mulout_data) // output wire [63 : 0] m_axis_dout_tdata ); wire [27:0] mulout_datai; wire [27:0] mulout_dataq; assign mulout_datai = mulout_data[27:0]; assign mulout_dataq = mulout_data[59:32]; reg mulifft_nd = 1'd0; reg [19:0] mulifft_datai = 20'd0; reg [19:0] mulifft_dataq = 20'd0; always @(posedge clk)begin if(rst)begin mulifft_nd <= 1'd0; mulifft_datai <= 20'd0; mulifft_dataq <= 20'd0; flagoverflow_ifftindata_28to20i <= 1'd0; flagoverflow_ifftindata_28to20q <= 1'd0; end else begin if(mulout_nd) begin mulifft_nd <= 1'd1; if(mulout_datai[27:19]!=9'd511&&mulout_datai[27:19]!=9'd0) begin flagoverflow_ifftindata_28to20i <= 1'd1; mulifft_datai <= (mulout_datai[27])? 20'b1000_0000_0000_0000_0000 : 20'b0111_1111_1111_1111_1111; end else begin flagoverflow_ifftindata_28to20i <= 1'd0; mulifft_datai <= mulout_datai[19:0]; end if(mulout_dataq[27:19]!=9'd511&&mulout_dataq[27:19]!=9'd0) begin flagoverflow_ifftindata_28to20q <= 1'd1; mulifft_dataq <= (mulout_dataq[27])? 20'b1000_0000_0000_0000_0000 : 20'b0111_1111_1111_1111_1111; end else begin flagoverflow_ifftindata_28to20q <= 1'd0; mulifft_dataq <= mulout_dataq[19:0]; end end else begin mulifft_nd <= 1'd0; mulifft_datai <= 20'd0; mulifft_dataq <= 20'd0; flagoverflow_ifftindata_28to20i <= 1'd0; flagoverflow_ifftindata_28to20q <= 1'd0; end end end //----------------------------------------------------复数乘法器输入控制状态机---------------------------------------------------------// reg mulin_nd_d0 = 1'd0; reg [15:0] mulin_i_d0 = 16'd0; reg [15:0] mulin_q_d0 = 16'd0; always @(posedge clk)begin if(rst)begin addrout_MMSE <= 8'd0; mulin_nd_d0 <= 1'd0; mulin_i_d0 <= 16'd0; mulin_q_d0 <= 16'd0; flagoverflow_fftdata_26to16i <= 1'd0; flagoverflow_fftdata_26to16q <= 1'd0; mulin_nd <= 1'd0; mulin_ai <= 16'd0; mulin_aq <= 16'd0; mulin_bi <= 11'd0; mulin_bq <= 11'd0; end else begin //fft输出再延时1clk,利用这个延时取出mmse信道估计结果。截位到16bit,设置溢出标志 if(fft_out_nd_d1) begin addrout_MMSE <= addrout_MMSE + 8'd1; mulin_nd_d0 <= 1'd1; if(fft_out_i_d1[25:15]!=11'd2047&&fft_out_i_d1[25:15]!=11'd0) begin flagoverflow_fftdata_26to16i <= 1'd1; mulin_i_d0 <= (fft_out_i_d1[25])? 16'b1000_0000_0000_0000 : 16'b0111_1111_1111_1111; end else begin flagoverflow_fftdata_26to16i <= 1'd0; mulin_i_d0 <= fft_out_i_d1[15:0]; end if(fft_out_q_d1[25:15]!=11'd2047&&fft_out_q_d1[25:15]!=11'd0) begin flagoverflow_fftdata_26to16q <= 1'd1; mulin_q_d0 <= (fft_out_q_d1[25])? 16'b1000_0000_0000_0000 : 16'b0111_1111_1111_1111; end else begin flagoverflow_fftdata_26to16q <= 1'd0; mulin_q_d0 <= fft_out_q_d1[15:0]; end end else begin addrout_MMSE <= 8'd0; mulin_nd_d0 <= 1'd0; mulin_i_d0 <= 16'd0; mulin_q_d0 <= 16'd0; flagoverflow_fftdata_26to16i <= 1'd0; flagoverflow_fftdata_26to16q <= 1'd0; end if(mulin_nd_d0) begin mulin_nd <= 1'd1; mulin_ai <= mulin_i_d0; mulin_aq <= mulin_q_d0; if(EQUenable_vio) begin mulin_bi <= dout_MMSE[10:0]; mulin_bq <= dout_MMSE[21:11]; end else begin mulin_bi <= 11'd1; mulin_bq <= 11'd0; end end else begin mulin_nd <= 1'd0; mulin_ai <= 16'd0; mulin_aq <= 16'd0; mulin_bi <= 11'd0; mulin_bq <= 11'd0; end end end //----------------------------------------------------乘法器输出->ifft的输入控制------------------------------------------------------// always @(posedge clk)begin if(rst)begin ifft_in_i <= 20'd0; ifft_in_q <= 20'd0; ifft_in_nd <= 1'd0; end else begin if(mulifft_nd) begin ifft_in_i <= mulifft_datai; ifft_in_q <= mulifft_dataq; ifft_in_nd <= 1'd1; end else begin ifft_in_i <= 20'd0; ifft_in_q <= 20'd0; ifft_in_nd <= 1'd0; end end end //-----------------------------------------------ifft的输出控制+截位+溢出标志设置--------------------------------------------------// reg ifft_out_ce = 1'd0; reg ifft_out_nd_d1 = 1'd0; reg [28:0] ifft_out_i_d1 = 29'd0; reg [28:0] ifft_out_q_d1 = 29'd0; always @(posedge clk)begin if(rst)begin ifft_out_ce <= 1'd0; ifft_out_nd_d1 <= 1'd0; ifft_out_i_d1 <= 29'd0; ifft_out_q_d1 <= 29'd0; end else begin if(ifft_out_ce==1'd0) begin if(flag_ChnEstFFT_done) begin ifft_out_ce <= 1'd1; end else begin ifft_out_ce <= 1'd0; end ifft_out_nd_d1 <= 1'd0; ifft_out_i_d1 <= 29'd0; ifft_out_q_d1 <= 29'd0; end else begin if(nd_pilot2) begin ifft_out_ce <= 1'd0; end else begin ifft_out_ce <= 1'd1; end ifft_out_nd_d1 <= ifft_out_nd; ifft_out_i_d1 <= ifft_out_i; ifft_out_q_d1 <= ifft_out_q; end end end always @(posedge clk)begin if(rst)begin nd_SC_FDE_dout <= 1'd0; SC_FDE_douti <= 10'd0; SC_FDE_doutq <= 10'd0; flagoverflow_FDE_dataout_29to10i <= 1'd0; flagoverflow_FDE_dataout_29to10q <= 1'd0; end else begin if(ifft_out_nd_d1) begin nd_SC_FDE_dout <= 1'd1; if(EQUenable_vio) begin //均衡开启,结果保留10bit,低位截掉8+5=13bit if(ifft_out_i_d1[28:22]!=7'd127&&ifft_out_i_d1[28:22]!=7'd0) begin flagoverflow_FDE_dataout_29to10i <= 1'd1; SC_FDE_douti <= (ifft_out_i_d1[28])? 10'b100000_0000 : 10'b01_1111_1111; end else begin flagoverflow_FDE_dataout_29to10i <= 1'd0; SC_FDE_douti <= ifft_out_i_d1[22:13]; end if(ifft_out_q_d1[28:22]!=7'd127&&ifft_out_q_d1[28:22]!=7'd0) begin flagoverflow_FDE_dataout_29to10q <= 1'd1; SC_FDE_doutq <= (ifft_out_q_d1[28])? 10'b100000_0000 : 10'b01_1111_1111; end else begin flagoverflow_FDE_dataout_29to10q <= 1'd0; SC_FDE_doutq <= ifft_out_q_d1[22:13]; end end else begin //均衡关闭,结果保留10bit,低位截掉8bit(结果应与输入相同) if(ifft_out_i_d1[28:17]!=12'd4095&&ifft_out_i_d1[28:17]!=12'd0) begin flagoverflow_FDE_dataout_29to10i <= 1'd1; SC_FDE_douti <= (ifft_out_i_d1[28])? 10'b100000_0000 : 10'b01_1111_1111; end else begin flagoverflow_FDE_dataout_29to10i <= 1'd0; SC_FDE_douti <= ifft_out_i_d1[17:8]; end if(ifft_out_q_d1[28:17]!=12'd4095&&ifft_out_q_d1[28:17]!=12'd0) begin flagoverflow_FDE_dataout_29to10q <= 1'd1; SC_FDE_doutq <= (ifft_out_q_d1[28])? 10'b100000_0000 : 10'b01_1111_1111; end else begin flagoverflow_FDE_dataout_29to10q <= 1'd0; SC_FDE_doutq <= ifft_out_q_d1[17:8]; end end end else begin nd_SC_FDE_dout <= 1'd0; SC_FDE_douti <= 10'd0; SC_FDE_doutq <= 10'd0; flagoverflow_FDE_dataout_29to10i <= 1'd0; flagoverflow_FDE_dataout_29to10q <= 1'd0; end end end //------------------------------------------------------仿真文件保存---------------------------------------------------// // integer handle01; // integer handle02; // integer handle03; // integer handle04; // integer handle05; // integer handle06; // reg enable1 = 0; // initial begin // handle01=$fopen("mulin_ai.txt","w"); $fclose(handle01); // handle02=$fopen("mulin_aq.txt","w"); $fclose(handle02); // handle03=$fopen("mulin_bi.txt","w"); $fclose(handle03); // handle04=$fopen("mulin_bq.txt","w"); $fclose(handle04); // handle05=$fopen("mulout_datai.txt","w"); $fclose(handle05); // handle06=$fopen("mulout_dataq.txt","w"); $fclose(handle06); // #10; // enable1 = 1; // end // always@(posedge clk)begin // if(enable1)begin // if(mulin_nd)begin // handle01=$fopen("mulin_ai.txt","a+");$fwrite(handle01,"%d\n",$signed(mulin_ai));$fclose(handle01); // handle02=$fopen("mulin_aq.txt","a+");$fwrite(handle02,"%d\n",$signed(mulin_aq));$fclose(handle02); // handle03=$fopen("mulin_bi.txt","a+");$fwrite(handle03,"%d\n",$signed(mulin_bi));$fclose(handle03); // handle04=$fopen("mulin_bq.txt","a+");$fwrite(handle04,"%d\n",$signed(mulin_bq));$fclose(handle04); // end // if(mulout_nd)begin // handle05=$fopen("mulout_datai.txt","a+");$fwrite(handle05,"%d\n",$signed(mulout_datai));$fclose(handle05); // handle06=$fopen("mulout_dataq.txt","a+");$fwrite(handle06,"%d\n",$signed(mulout_dataq));$fclose(handle06); // end // end // end endmodule