Files
MM7020/hdl/data_equalizer.v
T
2024-07-19 21:31:49 +08:00

625 lines
18 KiB
Verilog
Raw 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 / 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