【教程4>第6章>第26节】基于FPGA的MMSE信道估计与均衡系统实现与整体测试,并对比LS信道估计

目录

1.软件版本

2.基于FPGA的MMSE信道估计与均衡系统整体实现

2.1 信道估计误差计算模块

2.2 顶层模块修改

2.3 testbench修改

2.4 MMSE信道估计整体工程

3.基于FPGA的MMSE信道估计与均衡系统整体测试

4.视频操作步骤演示


欢迎订阅FPGA/MATLAB/Simulink系列教程

《★教程1:matlab入门100例》

《★教程2:fpga入门100例》

《★教程3:simulink入门60例》

《★教程4:FPGA/MATLAB/Simulink联合开发入门与进阶X例》

《★专题3:人工智能基础应用研究》

1.软件版本

vivado2019.2

2.基于FPGA的MMSE信道估计与均衡系统整体实现

       通过前面几个章节的学习,我们完成了MMSE信道估计和均衡系统。为了进一步验证MMSE信道估计的性能,我们在系统的最后,增加一个信道估计误差计算程序。

2.1 信道估计误差计算模块

      这里,我们使用的信道估计误差计算公式如下:

为了计算方便,我们使用m*mse,即:

这样方便FPGA中的误差计算。

然后m值,我们不考虑一个固定值,而是一直累加,直到所设置的仿真时间结束。

我们编写如下的verilog程序:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/22 20:05:37
// Design Name: 
// Module Name: hmse
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module hmse(
input i_clk,
input i_rst,
input signed[1:0]ien,
input signed[15:0]i_hi,
input signed[15:0]i_hq,
input signed[15:0]i_HestI,
input signed[15:0]i_HestQ,
output signed[31:0]o_mse
);
    
reg signed[15:0]r1_X;
reg signed[15:0]r2_X;
reg signed[15:0]r3_X;
reg signed[15:0]r4_X;
reg signed[15:0]r5_X;
reg signed[15:0]r6_X;
reg signed[15:0]r7_X;
reg signed[15:0]r8_X;
reg signed[15:0]r9_X;
reg signed[15:0]r10_X;
reg signed[15:0]r11_X;
reg signed[15:0]r12_X;

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     r1_X <= 16'd0;
     r2_X <= 16'd0;
     r3_X <= 16'd0;
     r4_X <= 16'd0;
     r5_X <= 16'd0;
     r6_X <= 16'd0;
     r7_X <= 16'd0;
     r8_X <= 16'd0;
     r9_X <= 16'd0;
     r10_X <= 16'd0;
     r11_X <= 16'd0;
     r12_X <= 16'd0;
     end
else begin
     r1_X <= i_hi;
     r2_X <= r1_X;
     r3_X <= r2_X;
     r4_X <= r3_X;
     r5_X <= r4_X;
     r6_X <= r5_X;
     r7_X <= r6_X;
     r8_X <= r7_X;
     r9_X <= r8_X;
     r10_X <= r9_X;
     r11_X <= r10_X;
     r12_X <= r11_X;
     end
end  
 
reg signed[15:0]r1_Xb;
reg signed[15:0]r2_Xb;
reg signed[15:0]r3_Xb;
reg signed[15:0]r4_Xb;
reg signed[15:0]r5_Xb;
reg signed[15:0]r6_Xb;
reg signed[15:0]r7_Xb;
reg signed[15:0]r8_Xb;
reg signed[15:0]r9_Xb;
reg signed[15:0]r10_Xb;
reg signed[15:0]r11_Xb;
reg signed[15:0]r12_Xb;

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     r1_Xb <= 16'd0;
     r2_Xb <= 16'd0;
     r3_Xb <= 16'd0;
     r4_Xb <= 16'd0;
     r5_Xb <= 16'd0;
     r6_Xb <= 16'd0;
     r7_Xb <= 16'd0;
     r8_Xb <= 16'd0;
     r9_Xb <= 16'd0;
     r10_Xb <= 16'd0;
     r11_Xb <= 16'd0;
     r12_Xb <= 16'd0;
     end
else begin
     r1_Xb <= i_hq;
     r2_Xb <= r1_Xb;
     r3_Xb <= r2_Xb;
     r4_Xb <= r3_Xb;
     r5_Xb <= r4_Xb;
     r6_Xb <= r5_Xb;
     r7_Xb <= r6_Xb;
     r8_Xb <= r7_Xb;
     r9_Xb <= r8_Xb;
     r10_Xb <= r9_Xb;
     r11_Xb <= r10_Xb;
     r12_Xb <= r11_Xb;
     end
end
 
 
reg signed[47:0]ww_sI;
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     ww_sI <= 48'd0;
     end
else begin
          if(ien==0)
          ww_sI<=ww_sI;
          else
          ww_sI<=ww_sI+$signed(r10_X-i_HestI) *$signed(r10_X-i_HestI)+$signed(r10_Xb-i_HestQ)*$signed(r10_Xb-i_HestQ);

 
     end
end

assign o_mse=ww_sI[47:16];
   
endmodule

2.2 顶层模块修改

我们修改下顶层文件tops,调用2.1给出的信道估计误差计算模块:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/07 20:01:15
// Design Name: 
// Module Name: tops
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tops(
input i_clk,
input i_rst,
input[5:0]i_SNR,
output signed[1:0]o_bitsI,
output signed[1:0]o_bitsQ,
output signed[1:0]o_politI,
output signed[1:0]o_politQ,
output [1:0]o_bit_politI,
output [1:0]o_bit_politQ,

output signed[15:0]o_hI,
output signed[15:0]o_hQ,
output signed[15:0]o_noiseI,
output signed[15:0]o_noiseQ,
output[15:0]o_bitshnI,
output[15:0]o_bitshnQ,

output signed[15:0]o_getpolitI,
output signed[15:0]o_getpolitQ,
output signed[15:0]o_HestI,
output signed[15:0]o_HestQ,
output signed[15:0]o_Hest_insertI,
output signed[15:0]o_Hest_insertQ,
output signed[15:0]o_YeqI, 
output signed[15:0]o_YeqQ,
output reg signed[15:0]o_cnt_err, 
output reg signed[15:0]o_cnt_all,
output signed[31:0]o_mse 
);
    
    
    
//插入导频
Polit_insert Polit_insert_u(
.i_clk         (i_clk),
.i_rst         (i_rst),
.o_bitsI       (o_bitsI),
.o_bitsQ       (o_bitsQ),
.o_politI      (o_politI),
.o_politQ      (o_politQ),
.o_bit_politI  (o_bit_politI),
.o_bit_politQ  (o_bit_politQ)
);

通过信道

channel_tops channel_tops_u(
.i_clk         (i_clk),
.i_rst         (i_rst),
.i_SNR         (i_SNR),
.i_bitsI       (o_bit_politI),
.i_bitsQ       (o_bit_politQ),
.o_hI          (o_hI),
.o_hQ          (o_hQ),
.o_noiseI      (o_noiseI),
.o_noiseQ      (o_noiseQ),
.o_bitshnI     (o_bitshnI),
.o_bitshnQ     (o_bitshnQ)
);
    
R_LS R_LS_u(
.i_clk         (i_clk),
.i_rst         (i_rst),
.i_bitshnI     (o_bitshnI),
.i_bitshnQ     (o_bitshnQ),
.o_getpolitI   (o_getpolitI),
.o_getpolitQ   (o_getpolitQ),
.o_HestI       (o_HestI),
.o_HestQ       (o_HestQ),
.o_Hest_insertI(o_Hest_insertI),
.o_Hest_insertQ(o_Hest_insertQ),
.o_YeqI        (o_YeqI),
.o_YeqQ        (o_YeqQ)  
);  
 
//统计误码
reg[31:0] dlyr1;
reg[31:0] dlyr2;
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     dlyr1 <= 32'd0;
     dlyr2 <= 32'd0;
     end
else begin
     dlyr1 <= {dlyr1[30:0],o_bit_politI[1]};
     dlyr2 <= {dlyr2[30:0],o_bit_politI[0]};
     end
end  
reg[31:0] dlyr1b;
reg[31:0] dlyr2b;
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     dlyr1b <= 32'd0;
     dlyr2b <= 32'd0;
     end
else begin
     dlyr1b <= {dlyr1b[30:0],o_bit_politQ[1]};
     dlyr2b <= {dlyr2b[30:0],o_bit_politQ[0]};
     end
end  

wire [1:0]bits1I={dlyr1[16],dlyr2[16]};
wire [1:0]bits2I={o_YeqI[15],1'b1};
wire [1:0]bits1Q={dlyr1b[16],dlyr2b[16]};
wire [1:0]bits2Q={o_YeqQ[15],1'b1};





always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     o_cnt_all <= 16'd0;
     o_cnt_err <= 16'd0;
     end
else begin
          if(o_bit_politI==0  & o_bit_politQ==0)
          begin
          o_cnt_all <= o_cnt_all;
          o_cnt_err <= o_cnt_err;
          end
          else begin
          
              if(bits1I==bits2I & bits1Q==bits2Q)
              begin
              o_cnt_all <= o_cnt_all+1;
              o_cnt_err <= o_cnt_err;
              end
              else
              begin
              o_cnt_all <= o_cnt_all+1;
              o_cnt_err <= o_cnt_err+1;
              end
          end
     end
end   
    
//信道估计MSE误差统计
wire signed[31:0]o_mse;
hmse hmseu(
.i_clk         (i_clk),
.i_rst         (i_rst),
.ien           (o_bit_politI),
.i_hi          (o_hI),
.i_hq          (o_hQ),
.i_HestI       (o_Hest_insertI),
.i_HestQ       (o_Hest_insertQ),
.o_mse         (o_mse)
);
    
 
    
endmodule

2.3 testbench修改

由于2.2修改完顶层模块tops之后,我们增加了一个信道估计误差接口,所以需要修改下testbench:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/02 03:31:40
// Design Name: 
// Module Name: TEST
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module TEST();

reg i_clk;
reg i_rst;
reg[7:0]i_SNR;
wire[1:0]o_bitsI;
wire[1:0]o_bitsQ;
wire[1:0]o_politI;
wire[1:0]o_politQ;
wire[1:0]o_bit_politI;
wire[1:0]o_bit_politQ;

wire signed[15:0]o_hI;
wire signed[15:0]o_hQ;
wire signed[15:0]o_noiseI;
wire signed[15:0]o_noiseQ;
wire signed[15:0]o_bitshnI;
wire signed[15:0]o_bitshnQ;
wire signed[15:0]o_getpolitI;
wire signed[15:0]o_getpolitQ;
wire signed[15:0]o_HestI;
wire signed[15:0]o_HestQ;
wire signed[15:0]o_Hest_insertI;
wire signed[15:0]o_Hest_insertQ;
wire signed[15:0]o_YeqI; 
wire signed[15:0]o_YeqQ; 
wire signed[15:0]o_cnt_err; 
wire signed[15:0]o_cnt_all;
wire signed[31:0]o_mse;
tops topsu(
.i_clk         (i_clk),
.i_rst         (i_rst),
.i_SNR         (i_SNR),

.o_bitsI       (o_bitsI),
.o_bitsQ       (o_bitsQ),
.o_politI      (o_politI),
.o_politQ      (o_politQ),
.o_bit_politI  (o_bit_politI),
.o_bit_politQ  (o_bit_politQ),
.o_hI          (o_hI),
.o_hQ          (o_hQ),
.o_noiseI      (o_noiseI),
.o_noiseQ      (o_noiseQ),
.o_bitshnI     (o_bitshnI),
.o_bitshnQ     (o_bitshnQ),
.o_getpolitI   (o_getpolitI),
.o_getpolitQ   (o_getpolitQ),
.o_HestI       (o_HestI),
.o_HestQ       (o_HestQ),
.o_Hest_insertI(o_Hest_insertI),
.o_Hest_insertQ(o_Hest_insertQ),
.o_YeqI        (o_YeqI),
.o_YeqQ        (o_YeqQ),
.o_cnt_err     (o_cnt_err),
.o_cnt_all     (o_cnt_all),
.o_mse         (o_mse)
);
 

initial
begin
i_clk=1'b1;
i_rst=1'b1;
i_SNR=2;//设置范围5~38
#1000
i_rst=1'b0;
end
always #5 i_clk=~i_clk;



integer fout1;
integer fout2;
integer fout3;
integer fout4;
initial begin
 fout1 = $fopen("IT.txt","w");
 fout2 = $fopen("QT.txt","w"); 
 fout3 = $fopen("IR.txt","w");
 fout4 = $fopen("QR.txt","w"); 
end

always @ (posedge i_clk)
 begin
    if(i_rst==1'b0)
    begin
	 $fwrite(fout1,"%d\n",o_bitshnI);
	 $fwrite(fout2,"%d\n",o_bitshnQ);
	 $fwrite(fout3,"%d\n",o_YeqI);
	 $fwrite(fout4,"%d\n",o_YeqQ);
	 end
end
 


endmodule

2.4 MMSE信道估计整体工程

此时,我们完成了MMSE信道整个工程的FPGA实现,整个系统的代码如下:

3.基于FPGA的MMSE信道估计整体测试-对比LS信道估计

由于MMSE信道估计,其主要优势在SNR较小时提现,因此测试对比时,我们在testbench中,将SNR设置为2db。如下所示:


我们首先测试MMSE信道估计,对本系统进行行为仿真:

可以看到,当SNR=2db时,总共测试12880个符号,错误1519个,信道估计误差为3175974。

然后我们测试LS信道估计,我们可以直接打开MMSE信道估计这个工程,打开Hest这个程序:

把1部分注释,然后换为2部分,相当于把MMSE信道估计公式:

h_mmse= R_HH * inv(R_HH_LS_LS)* H_ls;

变为

h_mmse=  H_ls;

这样就等效为LS信道估计,仿真测试结果如下:

可以看到,当SNR=2db时,总共测试12880个符号,错误1523个,信道估计误差为3317075。

通过对比可以看到,MMSE信道估计性能优于LS信道估计。

4.视频操作步骤演示

如果上述操作有什么不熟悉的地方,也可以参考如下的视频教程完成课程学习。

【教程4>第6章>第26节】基于FPGA的MMSE信道估计与均衡系统实现与整体测试,并对比LS信道估计_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fpga和matlab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值