tag 标签: 自适应

相关博文
  • 热度 21
    2013-5-31 10:43
    2019 次阅读|
    0 个评论
              最近在学习进行自适应FIR滤波器的设计,下面是参考别人的设计“基于LMS算法的自适应噪声抵消器”,稍作修改之后得到的。阶数n=8;算法步长u=0.0078;输入输出信号均为16位;滤波器最高32位。主要系统输入:环境噪声信号data_in(用高斯信号来模拟)、经过噪声叠加的正弦信号desired_in(线性叠加)、步长step_size;系统输出:经过滤波的正弦信号error_out、误差e_out、拟合抽头系数w_out。其中关于定标、截位、步长的取值等方面有些疑问,希望大家能提些宝贵意见。         自适应滤波的原理框图:           该设计的系统框图:         测试框架:           ModelSim中的仿真波形:         经测试,除了μ=2^-7(即0.0078),滤波收敛效果较好的μ的取值范围:μ∈ 。        在实际设计中定标、截位和步长的取值很关键,在本次设计中,步长取μ=2^-7(即0.0078),定标采用Q4.11。在代码中,step_size = 16'h0010,由于采用Q4.11 ,因而u=0.0078。在LMS算法的抽头系数更新模块中,    assign product_32 = data_in * step_size;    assign product_16 = product_32 ;    assign weight_in = (reset == 1'b1) ? 16'h0000 : (product_16 + weight_out); 关于系数每次更新累加,都截取噪声输入data_in与步长输入step_size相乘后32位乘积结果的 位。在LMS滤波器的顶层模块,    assign product_32 = step_size * error_in;    assign product_16 = product_32 ; 也都截取32位乘积结果的 位。           问题: 1. 截位为什么截取32位乘积结果的 位?是跟步长定标采用Q4.11有关吗?截位标准是什么样的?如果8抽头换成17抽头,16位输入数据换成13位输入数据呢? 2. 定标是根据什么定的,怎么快速有效地定标? 3. 关于步长的取值,大了小了收敛效果都不好,除了一个个地试,有什么方法可以快速有效地给步长取值?查了资料,收敛条件为:0μ1/λmax,λmax是输入数据的自相关矩阵的最大特征值。具体地,在此次设计中,λmax该如何求?         希望能跟大家交流,希望大家做过自适应FIR滤波器的,能帮帮忙,给些宝贵意见,谢谢!                  模块实现代码:   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  data_in,desired_in,step_size,sine_display; output  signed  error_out,e_out; output  signed w_out;   wire  signed error_in,data_in_reg,                   desired_in_reg,product_16; wire signed product_32,LMSx8_sum_out; wire signed 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 ; 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 ;  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 data_in,step_size; input   signed Sum_in; output  signed Sum_out; output  signed link_out; wire  signed 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 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 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 = LMS_tap_1_weight_out; assign link_out  = LMS_tap_2_weight_out; assign link_out   = LMS_tap_3_weight_out;  assign link_out   = LMS_tap_4_weight_out; assign link_out   = LMS_tap_5_weight_out; assign link_out   = LMS_tap_6_weight_out;  assign link_out   = LMS_tap_7_weight_out; assign link_out    = 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 data_in,step_size; output  signed delay_out; output  signed weight_out; output  signed tap_out; wire signed weight_in,product_16;    wire signed 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 ;    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 data_in; output delay_out; reg 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   data_in,desired_in,step_size,sine_display; reg   sine ,noise ; wire 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;i1000;i=i+1) begin #(CYCLE) data_in = noise ;  sine_display = sine ;  desired_in = sine +noise ; end end endmodule    
相关资源