自适应滤波-LMS算法的FPGA实现

时间:2025-11-01  作者:Diven  阅读:0

其实所有的数字滤波器都逃不过延时加权求和的六字真谛,但我们之前讨论的FIR滤波器,其截止频率等参数都是事先已经定好;如果事先已知有用信号与噪声信号的频率相差较远,用这种滤波器是可以完成滤波的。

自适应滤波-LMS算法的FPGA实现

但如果噪声与有用信号频率相差不大或者噪声近似高斯白噪声呢,这个情况该如何面对?这意味着滤波器参数不能再保持固定不变,也就意味着加权系数不能是定值,而是应该根据信号的某些统计特性改变。

维纳滤波器就是这样自适应滤波器,根据维纳霍夫方程可以求得维纳滤波器的加权系数。但是,维纳滤波器有其本身的局限性,在求解加权系数时,需要知道期望信号与输入信号的互相关函数,输入信号的自相关函数。这导致计算过程设计到矩阵运算,并且滤波器不适合非平稳信号,非平稳信号的相关性不是仅仅跟时间有关。

为了简化计算量,LMS不通过求均方误差的数学期望最小去获得最佳权值,而是直接对均方误差求最小值获得权值,然后不断地重复这个过程,直到接近最优维纳解。

维纳的权值更新方程:所以,LMS算法相比于前面讲过的FIR滤波器,不仅要对输入信号进行加权求和,还要求滤波器输出信号与期望信号的差值,然后根据差值更新权值信息。

LMS算法的FPGA实现结构里,我们依然使用FIR的基础模块,基础模块实现加权和权值更新,然后通过generate for调用基础模块,对所有结果求和;顶层求误差;

示例中使用的输入信号为带噪信号,期望信号是带噪的语音信号。

base_generator.v 基础模块实现过程,当时使用的是Altera的芯片,所以设置了如果FPGA_FAMILY为“ALTERA”,会调用Altera的乘法器IP核进行权值增量的计算和加权计算过程。

wire signed [X_W+E_W-1:0]coef_tmp;// xin * err
reg signed [X_W+E_W:0]coef_nxt;// wout(k+1)
reg signed [X_W+E_W-1:0]coef;// wout(k)
reg signed [X_W-1:0]x_r;// Save xin value for later calculation
reg signed [E_W-1:0]e_r;// Save err value for later calculation
reg[2:0]state;

//因为调用了Altera的IP核,不使用Altera就用*代替
generate if (FPGA_FAMILY == "ALTERA")
begin
mult16 m1(
.dataa(x_r),
.datab(e_r),
.result(coef_tmp)
);

mult16 m2(
.dataa(x_r),
.datab(wout),
.result(yout)
);
end
else
begin
assign coef_tmp = x_r * e_r;
assign yout = x_r * wout;
end
endgenerate

always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
state<='d0;
coef_nxt<='d0;
coef<='d0;
wout<='d0;
update<='d0;
x_r<='d0;
e_r<='d0;
end
else
case (state)
3'd0:
begin
if (en)
begin
state<=3'd1;
x_r<=xin;
e_r<=err;
end
update<=1'b0;
end
3'd1:
begin
coef_nxt<=coef_tmp + coef;
coef<=coef_nxt[X_W-1+E_W:0];
wout<=coef_nxt[X_W-1+E_W-:W_W];
state<=3'd0;
update<=1'b1;
end
default: state<=3'd0;
endcase
end

always块里面,首先保存输入信号和误差信号,然后进行加权结果输出,权值更新。

lms16_order.v中间模块部分代码,首先使用generate for调用了基础模块,然后对计算输出结果进行了扩位;这里没有使用Shift-RAM代替输入信号的延迟数组,也没有在求和过程使用流水线;这两个地方其实是需要改进的。

genvar i;
generate for (i = 1; i < 16; i = i + 1) begin:order
base_generator
#(
.FPGA_FAMILY(FPGA_FAMILY),
.X_W(X_W),
.E_W(E_W),
.W_W(W_W)
)
bg_inst
(
.clk(clk),
.rst_n(rst_n),
.en(en),

.xin(xin_arr[i-1]),
.err(err),
.yout(yout_arr[i]),
.wout(wout[(((i+1)*W_W)-1)-:W_W]),
.update(b_update[i])

);assign yout_exp[i] = {{4{yout_arr[i][X_W+W_W-1]}}, yout_arr[i]};endendgeneratealways @ (posedge clk or negedge rst_n)beginif (!rst_n)beginen<=1'b0;state<=3'd0;yout_ori<='d0;update<=1'b0;endelsecase (state)3'd0:beginif (en_i)beginen<=1'b1;state<=3'd1;endupdate<=1'b0;end3'd1:beginen<=1'b0;if (b_update == 16'hffff)beginyout_ori <= yout_exp[0] + yout_exp[1] + yout_exp[2] + yout_exp[3] + yout_exp[4] + yout_exp[5] + yout_exp[6] + yout_exp[7] +yout_exp[8] + yout_exp[9] + yout_exp[10] + yout_exp[11] + yout_exp[12] + yout_exp[13] + yout_exp[14] + yout_exp[15];state<=3'd0;update<=1'b1;endenddefault: state <= 3'd0;endcaseend

lms.v顶层实现部分代码,对滤波器求和结果与期望信号求误差信号,这里,u值采取了截位填充符号位的做法,信号右移N位,同时最高位填入N位符号位,误差数据相当于除以2的N次方

lms16_order
#(
.FPGA_FAMILY(FPGA_FAMILY),
.X_W(X_W),
.E_W(E_W),
.W_W(W_W),
.Y_W(D_W)
)
l_inst
(
.clk(clk),
.rst_n(rst_n),
.en_i(en_i),
.xin(xin),
.err(err_tmp),
.update(lms_up),
.xnxt(),
.wout(wout),
.yout(lms_yout)
);

always @ (posedge clk or negedge rst_n)beginif (!rst_n)beginupdate<=1'b0;err<='d0;d_r<='d0;endelse if (lms_up)beginupdate<=1'b1;err<=d_r-lms_yout;d_r<=din;endelsebeginupdate<=1'b0;endendalways @ (*)case (u)8'd0: err_tmp<=err;8'd1: err_tmp<={err[E_W-1],err[E_W-1:1]};8'd2: err_tmp<={{2{err[E_W-1]}},err[E_W-1:2]};8'd3: err_tmp<={{3{err[E_W-1]}},err[E_W-1:3]};8'd4: err_tmp<={{4{err[E_W-1]}},err[E_W-1:4]};8'd5: err_tmp<={{5{err[E_W-1]}},err[E_W-1:5]};8'd6: err_tmp<={{6{err[E_W-1]}},err[E_W-1:6]};8'd7: err_tmp<={{7{err[E_W-1]}},err[E_W-1:7]};8'd8: err_tmp<={{8{err[E_W-1]}},err[E_W-1:8]};8'd9: err_tmp<={{9{err[E_W-1]}},err[E_W-1:9]};8'd10: err_tmp<={{10{err[E_W-1]}},err[E_W-1:10]};8'd11: err_tmp<={{11{err[E_W-1]}},err[E_W-1:11]};8'd12: err_tmp<={{12{err[E_W-1]}},err[E_W-1:12]};8'd13: err_tmp<={{13{err[E_W-1]}},err[E_W-1:13]};8'd14: err_tmp<={{14{err[E_W-1]}},err[E_W-1:14]};8'd15: err_tmp<={{15{err[E_W-1]}},err[E_W-1:15]};default: err_tmp<=err;endcase

最终的仿真结果图:第一个是加了噪声的期望信号,第二个为输出的误差信号,第三个为输入的噪声信号,第四个为原始信号(不带噪信号)。

这里没有给出滤波器输出的信号,看起来近似一堆无规律的噪声。这里滤波器的输出更通俗的说,是输出一个输入信号与期望信号高度相关的信号。

所以,并不是大家以为的必须有了干净的原始信号,我才能从实际信号里分离出原始信号,不知道看完文章,你是否对LMS有了更多的认识。

猜您喜欢

在厨房中,切割板是不可少的工具,但不同材质和设计的切割板各有其特点与用途。木质切割板天然的纹理和温暖的触感受到许多家庭的喜爱,适合切割蔬菜和肉类,且对刀具磨损较...
2025-07-27 00:00:00

旋转开关是常见的电气控制元件,应用于家电、照明设备和工业控制系统中。通过旋转操作实现开关的切换,可以方便地调节设备的工作状态。旋转开关通常具有多档位设计,用户可...
2020-07-27 00:00:00

贴片电阻阻值识别是一项电子工程师和爱好者必备的技能。常见的贴片电阻采用三位数字或四位数字标识其阻值。三位数字标识法中,前两位数字表示有效数字,第三位数字表示10...
2025-04-14 15:02:37

电解电容是电子元件,在电路中扮演重要配件。充电是电解电容正常工作的必要步骤。本文将介绍几种给电解电容充电的方法。直流电源充电使用直流电源是最常用的方式。把电源的...
2025-03-27 09:01:39

贴片电阻上的「01R」表示其阻值为0.01欧姆,也就是10毫欧。贴片电阻的阻值通常用数字编码表示,常见的有三位数和四位数编码。三位数编码中,前两位数字表示有效数...
2024-11-26 11:29:23

ROHM(罗姆)作为一家知名的半导体和电子元件制造商,高品质和创新设计赢得了认可。可调电阻作为电子电路中重要的调节元件,ROHM提供了多样化的产品系列,满足不同...
2017-10-26 12:00:25

二极管是重要的半导体器件,应用于电路中。主要功能是允许电流在一个方向上流动,而在相反方向上阻止电流的流动。由于这一特性,二极管被用于开关电路中。本文将详细介绍二...
2025-04-09 13:31:40

立铣刀是应用于金属加工的切削工具,其规格和尺寸直接影响加工效果与效率。常见的立铣刀规格包括刀具直径、刀具长度和刀柄尺寸等。刀具直径通常从几毫米到数十毫米不等,选...
2009-10-02 00:00:00

贴片电阻作为电子电路中不可或缺的元件,其外形并非千篇一律,而是根据不同的需求和应用场景,发展出多种形式。了解这些不同的封装形式,对于电子工程师和爱好者来说至关重...
2024-11-26 11:29:14

贴片电阻,作为电子电路中很重要的元件,其耐压值是一个关键参数。指的是电阻能够承受的最大电压,超过这个值,电阻就可能被击穿损坏。选择合适的耐压值,对电路的稳定性和...
2024-11-29 10:26:00