最近在学习进行自适应FIR滤波器的设计,下面是参考别人的设计“基于LMS算法的自适应噪声抵消器”,稍作修改之后得到的。阶数n=8;算法步长u=0.0078;输入输出信号均为16位;滤波器最高32位。主要系统输入:环境噪声信号data_in(用高斯信号来模拟)、经过噪声叠加的正弦信号desired_in(线性叠加)、步长step_size;系统输出:经过滤波的正弦信号error_out、误差e_out、拟合抽头系数w_out。其中关于定标、截位、步长的取值等方面有些疑问,希望大家能提些宝贵意见。
在实际设计中定标、截位和步长的取值很关键,在本次设计中,步长取μ=2^-7(即0.0078),定标采用Q4.11。在代码中,step_size = 16'h0010,由于采用Q4.11 ,因而u=0.0078。在LMS算法的抽头系数更新模块中,
module lms(clk,reset,enable,data_in,desired_in,sine_display,step_size,error_out,e_out,w_out);
input clk,reset,enable;
input signed [15:0] data_in,desired_in,step_size,sine_display;
output signed [15:0] error_out,e_out;
output signed [127:0] w_out;
wire signed [15:0] error_in,data_in_reg,
desired_in_reg,product_16;
wire signed [31:0] product_32,LMSx8_sum_out;
wire signed [127:0] LMSx8_link_out;
delayUnit data_reg_1 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(data_in),
.delay_out(data_in_reg)
);
delayUnit data_reg_2 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(desired_in),
.delay_out(desired_in_reg)
);
assign product_32 = step_size * error_in;
assign product_16 = product_32[26:11];
LMSx8 LMSx8 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(data_in_reg),
.step_size(product_16),
.Sum_in(32'h0000_0000),
.Sum_out(LMSx8_sum_out),
.link_out(LMSx8_link_out)
);
assign error_in = desired_in_reg - LMSx8_sum_out[26:11];
assign e_out = sine_display - error_out;
assign w_out = LMSx8_link_out;
delayUnit data_reg_3 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(error_in),
.delay_out(error_out)
);
endmodule
///////////////////////////////////////////////////////////////////////////////////////////////////////
module LMSx8(clk,reset,enable,data_in,step_size,Sum_in,Sum_out,link_out);
input clk,reset,enable;
input signed [15:0] data_in,step_size;
input signed [31:0] Sum_in;
output signed [31:0] Sum_out;
output signed [127:0] link_out;
wire signed [15:0] LMS_tap_1_delay_out, LMS_tap_2_delay_out, LMS_tap_3_delay_out, LMS_tap_4_delay_out,
LMS_tap_5_delay_out, LMS_tap_6_delay_out, LMS_tap_7_delay_out, LMS_tap_8_delay_out;
wire signed [15:0] LMS_tap_1_weight_out, LMS_tap_2_weight_out, LMS_tap_3_weight_out, LMS_tap_4_weight_out,
LMS_tap_5_weight_out, LMS_tap_6_weight_out, LMS_tap_7_weight_out, LMS_tap_8_weight_out;
wire signed [31:0] LMS_tap_1_out, LMS_tap_2_out, LMS_tap_3_out, LMS_tap_4_out,
LMS_tap_5_out, LMS_tap_6_out, LMS_tap_7_out, LMS_tap_8_out;
LMS_tap LMS_tap_1 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(data_in),
.step_size(step_size),
.delay_out(LMS_tap_1_delay_out),
.weight_out(LMS_tap_1_weight_out),
.tap_out(LMS_tap_1_out)
);
LMS_tap LMS_tap_2 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_1_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_2_delay_out),
.weight_out(LMS_tap_2_weight_out),
.tap_out(LMS_tap_2_out)
);
LMS_tap LMS_tap_3 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_2_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_3_delay_out),
.weight_out(LMS_tap_3_weight_out),
.tap_out(LMS_tap_3_out)
);
LMS_tap LMS_tap_4 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_3_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_4_delay_out),
.weight_out(LMS_tap_4_weight_out),
.tap_out(LMS_tap_4_out)
);
LMS_tap LMS_tap_5 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_4_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_5_delay_out),
.weight_out(LMS_tap_5_weight_out),
.tap_out(LMS_tap_5_out)
);
LMS_tap LMS_tap_6 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_5_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_6_delay_out),
.weight_out(LMS_tap_6_weight_out),
.tap_out(LMS_tap_6_out)
);
LMS_tap LMS_tap_7 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_6_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_7_delay_out),
.weight_out(LMS_tap_7_weight_out),
.tap_out(LMS_tap_7_out)
);
LMS_tap LMS_tap_8 (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(LMS_tap_7_delay_out),
.step_size(step_size),
.delay_out(LMS_tap_8_delay_out),
.weight_out(LMS_tap_8_weight_out),
.tap_out(LMS_tap_8_out)
);
assign Sum_out = Sum_in + LMS_tap_1_out + LMS_tap_2_out +
LMS_tap_3_out + LMS_tap_4_out + LMS_tap_5_out +
LMS_tap_6_out + LMS_tap_7_out + LMS_tap_8_out;
assign link_out[127:112] = LMS_tap_1_weight_out;
assign link_out[111:96] = LMS_tap_2_weight_out;
assign link_out[95:80] = LMS_tap_3_weight_out;
assign link_out[79:64] = LMS_tap_4_weight_out;
assign link_out[63:48] = LMS_tap_5_weight_out;
assign link_out[47:32] = LMS_tap_6_weight_out;
assign link_out[31:16] = LMS_tap_7_weight_out;
assign link_out[15:0] = LMS_tap_8_weight_out;
endmodule
///////////////////////////////////////////////////////////////////////////////////////////////////////////
module LMS_tap(clk,reset,enable,data_in,step_size,delay_out,weight_out,tap_out);
input clk,reset,enable;
input signed [15:0] data_in,step_size;
output signed [15:0] delay_out;
output signed [15:0] weight_out;
output signed [31:0] tap_out;
wire signed [15:0] weight_in,product_16;
wire signed [31:0] product_32;
delayUnit delay_reg (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(data_in),
.delay_out(delay_out)
);
assign product_32 = data_in * step_size;
assign product_16 = product_32[26:11];
assign weight_in = (reset == 1'b1) ? 16'h0000 : (product_16 + weight_out);
delayUnit data_reg (
.clk(clk),
.reset(reset),
.enable(enable),
.data_in(weight_in),
.delay_out(weight_out)
);
assign tap_out = weight_out * data_in;
endmodule
///////////////////////////////////////////////////////////////////////////////////////////////////////////
module delayUnit(clk,reset,enable,data_in,delay_out);
input clk,reset,enable;
input [15:0] data_in;
output [15:0] delay_out;
reg [15:0] delay_out;
always @(posedge clk or posedge reset)
begin
if (reset ==1'b1)
begin
delay_out <= 0;
end
else
begin
if (enable == 1'b1)
begin
delay_out <= data_in;
end
end
end
endmodule
///////////////////////////////////////////////////////////////////////////////////////////////////////////
测试代码:
`timescale 1 ns / 1 ns //need to run 10 us
module lms_tb();
reg clk,enable,reset;
reg [15:0] data_in,desired_in,step_size,sine_display;
reg [15:0] sine[0:999],noise[0:999];
wire [15:0] error_out;
integer i;
parameter CYCLE = 10;
lms TestUnit (.clk(clk),
.data_in(data_in),
.desired_in(desired_in),
.enable(enable),
.reset(reset),
.step_size(step_size),
.error_out(error_out)
);
always #(CYCLE/2) clk = ~clk;
initial begin
clk = 1'b0;
reset = 1'b0;
enable = 1'b1;
#(CYCLE) reset = 1'b1;
#(CYCLE) reset = 1'b0;
end
initial begin
step_size = 16'h0010; //Q4.11 so u=0.0078
$readmemh("sine.hex",sine);
$readmemh("noise.hex",noise);
for(i=0;i<1000;i=i+1) begin
#(CYCLE) data_in = noise;
sine_display = sine;
desired_in = sine+noise;
end
end
endmodule
文章评论(0条评论)
登录后参与讨论