基于FPGA的LMS自适应滤波器verilog实现,包括testbench

发布时间 2023-05-21 23:42:16作者: 我爱C编程

1.算法仿真效果

vivado2019.2仿真结果如下:

 

 

 

 

2.算法涉及理论知识概要

        自适应算法是数字信号处理(DSP)的主体。它们被用于各种应用,包括声学回声消除、雷达制导系统、无线信道估计等。

 

        自适应算法用于估算随时间变化的信号。有许多自适应算法,如递归最小二乘(RLS)和卡尔曼滤波,但最常用的是最小均方算法(LMS)。这是一个简单但功能强大的算法,该算法可以利用莱迪思FPGA架构来实现。通过窗口和Hoff的开发,该算法采用的是梯度下降法来估计随时间变化的信号。梯度下降法找到一个最小值,如果它存在,在梯度负方向采取步骤。这样做是通过调整滤波器系数使误差最小化。

 

        LMS参考设计包括两个主要的功能模块 - 一个FIR滤波器和LMS算法。使用一个乘法器和一个具有反馈的加法器串行实现FIR滤波器。 FIR结果归一化,以尽量减少饱和。 LMS算法迭代更新系数,并把其馈送到FIR滤波器。FIR滤波器使用系数cn)和输入的参考信号xn)生成输出yn)。然后所希望的信号dn)与输出yn)相减,产生一个误差,LMS算法用它来计算下一组的系数。

 

        自适应滤波器由参数可调的数字滤波器和自适应算法两部分组成。如图所示。

 

 

 

 

        输入信号x(n) 通过参数可调数字滤波器后产生输出信号 y(n),将其与期望信号d(n)进行比较,形成误差信号e(n), 通过自适应算法对滤波器参数进行调整,最终使 e(n)的均方值最小。自适应滤波可以利用前一时刻已得的滤波器参数的结果,自动调节当前时刻的滤波器参数,以适应信号和噪声未知的或随时间变化的统计特性,从而实现最优滤波。自适应滤波器实质上就是一种能调节自身传输特性以达到最优的维纳滤波器。自适应滤波器不需要关于输入信号的先验知识,计算量小,特别适用于实时处理。维纳滤波器参数是固定的,适合于平稳随机信号。卡尔曼滤波器参数是时变的,适合于非平稳随机信号。然而,只有在信号和噪声的统计特性先验已知的情况下,这两种滤波技术才能获得最优滤波。在实际应用中,常常无法得到信号和噪声统计特性的先验知识。在这种情况下,自适应滤波技术能够获得极佳的滤波性能,因而具有很好的应用价值。

 

        在自适应滤波器设计中,最小均方(Least Mean SquareLMS)算法使用随机梯度下降的方法实现代价函数的最小化,具有计算复杂度低、无需统计数据的先验知识和均值无偏地收敛到维纳解等优点,成为自适应算法中应用最广泛的一种。LMS自适应滤波器本质上是一种将自身传输特性调节到最优的维纳滤波器。

 

        对于输入信号 x ( n ) x(n)x(n),其通过参数可调的横向滤波器后,输出为 y ( n ) y(n)y(n) LMS算法根据滤波器的输出信号 y ( n ) y(n)y(n) 与期望信号 d ( n ) d(n)d(n) 的误差自动地调整滤波器的参数,从而使得滤波器适应随机信号的时变统计特性,LMS自适应滤波器的结构如图1所示。

 

 

 

 

3.verilog核心程序

 

module LMSs(
...................................................................
subLMS subLMS_1(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(i_din), 
.i_Step(i_Step),
.o_dout(LMS_tap_1_delay_out),
.o_Tap(LMS_tap_1_out)
);
 
subLMS subLMS_2(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(LMS_tap_1_delay_out), 
.i_Step(i_Step),
.o_dout(LMS_tap_2_delay_out),
.o_Tap(LMS_tap_2_out)
);
                        
subLMS subLMS_3(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(LMS_tap_2_delay_out), 
.i_Step(i_Step),
.o_dout(LMS_tap_3_delay_out),
.o_Tap(LMS_tap_3_out)
);
          
                        
subLMS subLMS_4(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(LMS_tap_3_delay_out), 
.i_Step(i_Step),
.o_dout(LMS_tap_4_delay_out),
.o_Tap(LMS_tap_4_out)
);
 
subLMS subLMS_5(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(LMS_tap_4_delay_out), 
.i_Step(i_Step),
.o_dout(LMS_tap_5_delay_out),
.o_Tap(LMS_tap_5_out)
);
 
subLMS subLMS_6(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(LMS_tap_5_delay_out), 
.i_Step(i_Step),
.o_dout(LMS_tap_6_delay_out),
.o_Tap(LMS_tap_6_out)
);
 
subLMS subLMS_7(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(i_en),
.i_din(LMS_tap_6_delay_out), 
.i_Step(i_Step),
.o_dout(LMS_tap_7_delay_out),
.o_Tap(LMS_tap_7_out)
);
 
endmodule