Files
MM7020/hdl/Chn_Estimate.v

1193 lines
42 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: 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&&dividerout_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&&dividerout_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&&dividerout_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&&dividerout_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&&dividerout_data_i[33:10]!=24'd0)
flagoverflow_divmmse_34to11 <= 1'd1;
else
begin
if(dividerout_data_q[33:10]!=24'd16777215&&dividerout_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