一、什么是11阶FIR滤波器?
1.FIR滤波器(Finite Impulse Response Filter)的中文名叫做有限长单位冲激响应滤波器
2.它的作用就是对输入的数字信号进行"加工",比如滤除不需要的噪音,或者提取特定频率的信号。
3.看代码更简单
二、代码
1.FIR的代码:
a.构建延迟线(数据缓存):代码利用 tap0 到 tap10 这组寄存器,将输入信号 x 逐级向后传递,从而在内部同时保存了当前及过去10个时刻的采样数据,为滤波计算提供完整的历史数据窗口。
b.利用对称性简化计算:通过 t0 到 t5 的赋值操作,将对称位置的抽头数据(如首尾的 tap0 和 tap10)进行两两相加。这种预处理利用了线性相位FIR滤波器的对称特性,有效减少了后续乘法器的使用数量。
c.采用移位相加代替乘法:在计算累加和 sum 时,代码完全避开了硬件资源消耗极大的乘法运算符,而是通过巧妙的位移(<<)和位拼接({})操作来凑出特定的滤波系数(如 16.875、-11.25 等),极大地优化了硬件面积和运算速度。
拆解 t1 的计算逻辑:
t1 << 4:左移 4 位 ,也就是 乘以 16。
{t1[7], t1[7:1]}:这是算术右移 1 位(最高位补符号位) ,也就是 乘以 0.5。
{t1[7], t1[7], t1[7:2]}:这是算术右移 2 位 ,也就是 乘以 0.25。
{t1[7], t1[7], t1[7], t1[7:3]}:这是算术右移 3 位 ,也就是 乘以 0.125。
把它们加起来:
总系数 = 16+0.5+0.25+0.125=16.875
d.位宽扩展与结果输出:最终的计算结果经过 16 位寄存器 sum 暂存,并通过符号位扩展的方式(将最高位重复拼接)赋值给 16 位输出端口 y,确保了有符号定点数在位宽转换过程中的数值准确性。
c
`timescale 1ns / 1ps
module FIR_11(
input clk ,
input [7:0]x ,
output reg[15:0] y
);
reg [15:0] sum;
reg [7:0] tap0 ;
reg [7:0] tap1 ;
reg [7:0] tap2 ;
reg [7:0] tap3 ;
reg [7:0] tap4 ;
reg [7:0] tap5 ;
reg [7:0] tap6 ;
reg [7:0] tap7 ;
reg [7:0] tap8 ;
reg [7:0] tap9 ;
reg [7:0] tap10 ;
reg [7:0] tap11 ;
reg [7:0] t0 ;
reg [7:0] t1 ;
reg [7:0] t2 ;
reg [7:0] t3 ;
reg [7:0] t4 ;
reg [7:0] t5 ;
always @(posedge clk)
begin
//-------------------------
t0<=tap5;
t1<=tap4+tap6;
t2<=tap3+tap7;
t3<=tap2+tap8;
t4<=tap1+tap9;
t5<=tap0+tap10;
//------------------
tap10<=tap9;
tap9<=tap8;
tap8<=tap7;
tap7<=tap6;
tap6<=tap5;
tap5<=tap4;
tap4<=tap3;
tap3<=tap2;
tap2<=tap1;
tap1<=tap0;
tap0<=x;
//---------------------------------
sum<=(t1<<4)+{t1[7],t1[7:1]}+{t1[7],t1[7],t1[7:2]}+
{t1[7],t1[7],t1[7],t1[7:3]}-(t2<<3)-(t2<<2)+t2-{t2[7],t2[7],t2[7:2]}
+(t3<<2)+t3+{t3[7],t3[7],t3[7:2]}+{t3[7],t3[7],t3[7],t3[7],t3[7:4]}
+{t3[7],t3[7],t3[7],t3[7],t3[7],t3[7:5]}
-t4-{t4[7],t4[7:1]}-{t4[7],t4[7],t4[7],t4[7:3]}
+{t5[7],t5[7:1]}-{t5[7],t5[7],t5[7],t5[7],t5[7],t5[7:5]}
+(t0<<7)-((t0<<2)<<2)-(t0<<2)+{t0[7],t0[7:1]}
+{t0[7],t0[7],t0[7:2]}+{t0[7],t0[7],t0[7],t0[7],t0[7:4]};
y<={sum[15],sum[15],sum[15],sum[15],sum[15],sum[15],sum[15],sum[15:7]};
end
endmodule
仿真测试代码:
c
`timescale 1ns / 1ps
module tb_FIR_11;
reg clk;
reg [7:0] x;
wire [15:0] y;
FIR_11 u_FIR_11 (
.clk(clk),
.x(x),
.y(y)
);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
x = 8'd0;
#20;
#10 x = 8'd127;
#10 x = 8'd0;
#10 x = 8'd0;
#10 x = 8'd0;
#200;
#10 x = 8'd50;
#200;
#10 x = -8'd50;
#200;
#10 x = 8'd100;
#200;
repeat (20) begin
#10 x = $random % 256;
end
#100;
$stop;
end
endmodule
三、仿真
