信道估计均衡基于FPGA的MMSE信道估计均衡verilog实现
Posted fpga和matlab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信道估计均衡基于FPGA的MMSE信道估计均衡verilog实现相关的知识,希望对你有一定的参考价值。
1.软件版本
matlab2013b,ISE14.7
2.本算法fpga实现过程
整个系统分为估计和均衡两个模块,其RTL电路图如下所示:
这个系统的各个管脚接口如下所示:
i_clk_40m: | 系统时钟,为40M的时钟频率 |
i_rst: | 复位信号,0的时候系统复位,1的时候正常工作 |
i_en: | 系统使能信号,1的时候,系统正常工作 |
i_ram_data_re: | 接收到的信号的实部 |
i_ram_data_im: | 接收到的信号的虚部 |
i_symbol_real: | 发送的信号的实部 |
i_symbol_imag: | 发送的信号的虚部 |
o_ram_h_real: | 信道估计输出的实部 |
o_ram_h_imag: | 信道估计输出的虚部 |
o_clk_60m: | 60M时钟,通过DCM,将40M转换为60M |
o_start: | FFT工作信号 |
o_d_re: | 将信道估计实部转换为频域值 |
o_d_im: | 将信道估计虚部转换为频域值 |
o_f_re: | 将信道估计的多径信号的实部转换为频域值 |
o_f_im: | 将信道估计的多径信号的虚部转换为频域值 |
o_done_fft: | FFT计算完成使能信号 |
o_xk_re_d: | 将信道估计实部转换为频域值的FFT变换 |
o_xk_im_d: | 将信道估计虚部转换为频域值的FFT变换 |
o_xk_re_f: | 将信道估计的多径信号的实部转换为频域值的FFT变换 |
o_xk_im_f: | 将信道估计的多径信号的虚部转换为频域值的FFT变换 |
o_I_EQ_re: | 均衡输出的实部 |
o_I_EQ_im: | 均衡输出的虚部 |
o_start_ifft: | IFFT开始工作信号 |
o_done: | IFFT计算完成使能信号 |
o_xk_re: | IFFT计算完成使能信号的实部 |
o_xk_im: | IFFT计算完成使能信号的虚部 |
o_data: | 最后的并行信号 |
o_signal_I: | 最后的串行信号 |
系统的资源占用如下所示
整个系统包含如下的程序
这些文件的含义为:
信道估计与均衡顶层模块
信道估计顶层模块
除法模块
均衡顶层模块
时钟管理器模块
双口RAM模块
通过MMSE得到信道矩阵H的转换。
频域除非模块
信号均衡后输出模块
下面对各个模块进行简要的说明:
信道估计与均衡顶层模块
即系统的顶层模块,调用信道估计和信道均衡两个模块。
信道估计顶层模块
channel_est.v
对应的模块:即调用除法模块。
除法模块
div_unit.v
除法模块,用来进行信道估计。
均衡顶层模块
Channel_equalizer.v
这个模块是均衡模块的顶层模块。调用下面的各个均衡子模块。
时钟管理器模块
clk_gen.v
这个模块主要通过DCM时钟IP核进行实现,产生所需要的时钟频率。
双口RAM模块
asyn_ram.v
这个模块是数据存储管理模块,即将数据输入到双口RAM中,进行缓存,然后当需要进行数据处理的时候,产生地址,从RAM中读取对应的数据进行处理。
这里,主要通过调用RAM的IP核进行实现。
通过MMSE得到信道矩阵H的转换。
h_to_f.v
这个部分的主要程序,将信道估计得到的矩阵转换为频域的表达式。
频域除法模块
fft_div_ifft.v
首先将信号进行FFT变换获得其频域信号,然后相除,最后对相除后的均衡信号进行IFFT变换。完成均衡计算。对应的verilog代码如下:
信号均衡后输出模块
fifo_output.v
这个模块的主要功能就是将均衡后的数据进行输出,其主要原理就是通过FIFO模块,将数据进行输出,通过FIFO,可以有效的实现数据稳定的输出。对应的verilog代码如下:
3.仿真结论
仿真结果如下图所示:
4.部分源码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 22:26:02 06/04/2014
// Design Name:
// Module Name: Channel_Est_equ
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module Channel_Est_equ(
i_clk_40m,
i_rst,
i_en,
i_ram_data_re,
i_ram_data_im,
i_symbol_real,
i_symbol_imag,
//est
o_ram_h_real,
o_ram_h_imag,
//equ
o_clk_60m,
o_start,
o_d_re,
o_d_im,
o_f_re,
o_f_im,
o_done_fft,
o_xk_re_d,
o_xk_im_d,
o_xk_re_f,
o_xk_im_f,
o_I_EQ_re,
o_I_EQ_im,
o_start_ifft,
o_done,
o_xk_re,
o_xk_im,
o_data,
o_signal_I
);
input i_clk_40m;
input i_rst;
input i_en;
input signed[11:0] i_ram_data_re;
input signed[11:0] i_ram_data_im;
input signed[11:0] i_symbol_real;
input signed[11:0] i_symbol_imag;
output signed[11:0]o_ram_h_real;
output signed[11:0]o_ram_h_imag;
//output of h_to_f
output o_clk_60m;
output o_start;
output signed [11:0] o_d_re;
output signed [11:0] o_d_im;
output signed [11:0] o_f_re;
output signed [11:0] o_f_im;
//output of fft
output o_done_fft;
output signed [11:0] o_xk_re_d;
output signed [11:0] o_xk_im_d;
output signed [11:0] o_xk_re_f;
output signed [11:0] o_xk_im_f;
output o_start_ifft;
//output of div
output signed [11:0] o_I_EQ_re;
output signed [11:0] o_I_EQ_im;
//output of ifft
output o_done;
output signed [21:0] o_xk_re;
output signed [21:0] o_xk_im;
//output of fifo
output signed [21:0] o_data;
output o_signal_I;
channel_est channel_est_u(
.i_clk (o_clk_60m),
.i_rst (i_rst),
.i_data_real1(i_ram_data_re),
.i_data_imag1(i_ram_data_im),
.i_data_real2(i_symbol_real),
.i_data_imag2(i_symbol_imag),
.o_h_real (o_ram_h_real),
.o_h_imag (o_ram_h_imag)
);
Channel_equalizer Channel_equalizer_u(
.i_clk_40m (i_clk_40m),
.i_rst (i_rst),
.i_en (i_en),
.i_ram_h0_re (o_ram_h_real),
.i_ram_h0_im (o_ram_h_imag),
//多径设置参数
.i_ram_hk_re (o_ram_h_real[11],o_ram_h_real[11:1]),
.i_ram_hk_im (o_ram_h_imag[11],o_ram_h_imag[11:1]),
.i_ram_delay (10'd1),
//=========================================
.i_ram_data_re (i_ram_data_re),
.i_ram_data_im (i_ram_data_im),
//=========================================
.o_clk_5m (),
.o_clk_60m (o_clk_60m),
.o_rd_en (),
.o_rd_add (),
.o_ram_h0_re (),
.o_ram_h0_im (),
.o_ram_hk_re (),
.o_ram_hk_im (),
.o_ram_delay (),
.o_ram_data_re (),
.o_ram_data_im (),
.o_start (o_start),
.o_d_re (o_d_re),
.o_d_im (o_d_im),
.o_f_re (o_f_re),
.o_f_im (o_f_im),
.o_done_fft (o_done_fft),
.o_xk_re_d (o_xk_re_d),
.o_xk_im_d (o_xk_im_d),
.o_xk_re_f (o_xk_re_f),
.o_xk_im_f (o_xk_im_f),
.o_I_EQ_re (o_I_EQ_re),
.o_I_EQ_im (o_I_EQ_im),
.o_start_ifft (o_start_ifft),
.o_done (o_done),
.o_xk_re (o_xk_re),
.o_xk_im (o_xk_im),
.o_data (o_data),
.o_signal_I (o_signal_I)
);
endmodule
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 16:48:39 03/03/2015
// Design Name:
// Module Name: h_to_f
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module h_to_f(i_clk,
i_rst,
i_en,
i_h0_re,
i_h0_im,
i_hk_re,
i_hk_im,
i_delay,//K
i_data_re,
i_data_im,
o_rd_en, // ram的读使能信号
o_rd_add,
o_start,
o_f_re,
o_f_im,
o_d_re,
o_d_im
);
input i_clk;
input i_rst;
input i_en;
input signed [11:0] i_h0_re;
input signed [11:0] i_h0_im;
input signed [11:0] i_hk_re;
input signed [11:0] i_hk_im;
input [9:0] i_delay;
input signed [11:0] i_data_re;
input signed [11:0] i_data_im;
output o_rd_en;
output [9:0] o_rd_add;
output o_start;
output signed [11:0] o_f_re;
output signed [11:0] o_f_im;
output signed [11:0] o_d_re;
output signed [11:0] o_d_im;
reg signed [11:0] o_f_re = 12'd0;
reg signed [11:0] o_f_im = 12'd0;
reg signed [11:0] o_d_re = 12'd0;
reg signed [11:0] o_d_im = 12'd0;
reg o_rd_en = 1'b0;
reg [9:0] o_rd_add = 10'd0;
reg o_start = 1'b0;
reg [5:0] reg_t = 6'd0;
reg start1 = 1'b0;
reg start2 = 1'b0;
reg start3 = 1'b0;
reg o_rst_mul = 1'b0; //乘法器的复位信号
reg en1 = 1'b0;
reg en2 = 1'b0;
wire enable;
wire [5:0] k;
wire [5:0] t;
//wire [5:0] k1;
//wire [5:0] k2;
wire [5:0] t0;
wire [5:0] t1;
wire [5:0] t2;
wire signed [11:0] rcc; //保留一位符号位
wire signed [23:0] o_f_re_tmp;
wire signed [23:0] o_f_im_tmp;
assign k = i_delay/8;
assign t = i_delay%8;
//assign k1=k+1;
//assign k2=k+2;
assign t0=16-t;
assign t1=24-t;
assign t2=32-t;
always @(posedge i_clk) //对异步信号进行同步整形
begin
if(!i_rst)
begin
en1 <= 1'b0;
en2 <= 1'b0;
end
else
begin
en1 <= i_en;
en2 <= en1;
end
end
assign enable=en1&(!en2);
always @(posedge i_clk)
begin
if(!i_rst)
begin
o_rd_add <= 10'd0;
o_rst_mul <= 1'b0;
o_rd_en <= 1'b0;
end
else if(enable)
begin
o_rd_add <= 10'd1;
o_rst_mul <= 1'b0;
o_rd_en <= 1'b1;
end
else if(o_rd_add == 0||o_rd_add == 512)
begin
o_rd_add <= 10'd0;
o_rst_mul <= 1'b0;
o_rd_en <= 1'b0;
end
else
begin
o_rd_add <= o_rd_add + 10'd1;
o_rst_mul <= 1'b1;
o_rd_en <= 1'b1;
end
end
always @(posedge i_clk)
begin
if(!i_rst)
begin
o_start <= 1'b0;
start1 <= 1'b0;
start2 <= 1'b0;
start3 <= 1'b0;
end
else
begin
start1 <= o_rd_en;
start2 <= start1;
start3 <= start2;
o_start <= start3;
end
end
always @(posedge i_clk or negedge i_rst)
begin
if(!i_rst)
reg_t <= 6'd0;
else if(o_rd_add == k)
reg_t <= t0;
else if (o_rd_add == k + 6'd1)
reg_t <= t1;
else if (o_rd_add == k + 6'd2)
reg_t <= t2;
else
reg_t <= 6'd0;
end
rom_rrc unit (.clka(i_clk),
.ena(o_rd_en),
.addra(reg_t), // Bus [5 : 0]
.douta(rcc)); // Bus [11 : 0]
mul_h_rrc re (.clk(i_clk),
.a(i_hk_re), // Bus [11 : 0]
.b(rcc), // Bus [10 : 0]
.ce(o_rst_mul),
.p(o_f_re_tmp)); // Bus [22 : 0]
mul_h_rrc im (.clk(i_clk),
.a(i_hk_im), // Bus [11 : 0]
.b(rcc), // Bus [10 : 0]
.ce(o_rst_mul),
.p(o_f_im_tmp)); // Bus [22 : 0]
always @(posedge i_clk)
begin
if(!i_rst)
begin
o_f_re <= 12'd0;
o_f_im <= 12'd0;
end
else if (o_rd_add == 8) //乘法器和rom???难邮?
begin
o_f_re <= i_hk_re; //截取12位
o_f_im <= i_hk_im;
end
else if(o_rd_add > 8)
begin
o_f_re <= i_hk_re;
o_f_im <= i_hk_im;
end
else
begin
o_f_re <= i_hk_re;
o_f_im <= i_hk_im;
end
end
reg signed [11:0] re_data1 = 12'd0;
reg signed [11:0] re_data2 = 12'd0;
reg signed [11:0] re_data3 = 12'd0;
reg signed [11:0] re_data4 = 12'd0;
reg signed [11:0] re_data5 = 12'd0;
reg signed [11:0] re_data6 = 12'd0;
always @(posedge i_clk)
begin
if(!i_rst)
begin
o_d_re <= 12'd0;
re_data1 <= 12'd0;
re_data2 <= 12'd0;
re_data3 <= 12'd0;
re_data4 <= 12'd0;
re_data5 <= 12'd0;
re_data6 <= 12'd0;
end
else
begin
re_data1 <= i_data_re;
re_data2 <= re_data1;
re_data3 <= re_data2;
re_data4 <= re_data3;
re_data5 <= re_data4;
re_data6 <= re_data5;
o_d_re <= re_data6;
end
end
reg signed [11:0] im_data1 = 12'd0;
reg signed [11:0] im_data2 = 12'd0;
reg signed [11:0] im_data3 = 12'd0;
reg signed [11:0] im_data4 = 12'd0;
reg signed [11:0] im_data5 = 12'd0;
reg signed [11:0] im_data6 = 12'd0;
always @(posedge i_clk)
begin
if(!i_rst)
begin
o_d_im <= 12'd0;
im_data1 <= 12'd0;
im_data2 <= 12'd0;
im_data3 <= 12'd0;
im_data4 <= 12'd0;
im_data5 <= 12'd0;
im_data6 <= 12'd0;
end
else
begin
im_data1 <= i_data_im;
im_data2 <= im_data1;
im_data3 <= im_data2;
im_data4 <= im_data3;
im_data5 <= im_data4;
im_data6 <= im_data5;
o_d_im <= im_data6;
end
end
endmodule
5.参考文献
[1]邵际南. 基于FPGA的TD-LTE系统上行信道估计与均衡部分的实现[D]. 北京交通大学, 2011.A01-99
以上是关于信道估计均衡基于FPGA的MMSE信道估计均衡verilog实现的主要内容,如果未能解决你的问题,请参考以下文章
LS信道估计,MMSE信道估计以及CS信道估计算法的误码率对比仿真