有限冲激响应滤波器——线性相位的守护者
FIR(Finite Impulse Response)滤波器的输出仅取决于当前和过去的输入值,不依赖过去的输出值,因此冲激响应是有限长的:
其中M为滤波器阶数,h[k]为滤波器系数(抽头),x[n]为输入,y[n]为输出。FIR的系统函数为:
注意H(z)只有零点,没有极点(除z=0),因此FIR滤波器始终稳定。
| 特性 | FIR | IIR |
|---|---|---|
| 冲激响应长度 | 有限(M+1点) | 无限(递归衰减) |
| 稳定性 | 始终稳定(无极点) | 需确保极点在单位圆内 |
| 线性相位 | 可实现严格线性相位 | 一般无法线性相位 |
| 相同指标所需阶数 | 较高(10-100+) | 较低(4-10) |
| 计算量 | 较大(每输出M+1次MAC) | 较小(每输出2N+1次MAC) |
| 系数量化敏感度 | 较低 | 较高(极点偏移影响大) |
| 反馈回路 | 无 | 有 |
| 设计方法 | 窗函数法、频率采样法、最优等波纹法 | 双线性变换法、脉冲响应不变法 |
| 群延迟 | 常数 = M/2 | 频率相关(非线性) |
线性相位意味着所有频率分量经过滤波器后延迟相同的时间,不会产生相位失真。这是FIR最大的优势,在音频处理、图像处理等需要保持波形形状的应用中至关重要。
| 类型 | 对称性 | 阶数M | 频率响应在ω=0 | 频率响应在ω=π | 适用 |
|---|---|---|---|---|---|
| I型 | 偶对称 h[n]=h[M-n] | 偶数 | 无约束 | 无约束 | 通用滤波器 |
| II型 | 偶对称 h[n]=h[M-n] | 奇数 | 无约束 | H(π)=0 | 低通/带通(不含高通) |
| III型 | 奇对称 h[n]=-h[M-n] | 偶数 | H(0)=0 | H(π)=0 | 微分器/Hilbert变换 |
| IV型 | 奇对称 h[n]=-h[M-n] | 奇数 | H(0)=0 | 无约束 | 微分器/Hilbert变换 |
群延迟 τ(ω) = -dφ(ω)/dω 表示信号各频率分量通过滤波器的延迟时间。对于线性相位FIR:
例如,一个40阶FIR在48kHz采样率下,群延迟为20个样本 = 416.7μs。
对y[n] = Σh[k]x[n-k]做DTFT,得到频率响应:
对于I型线性相位FIR(M偶,偶对称),可分解为:
其中H̃(ω)为实函数,称为幅度响应(Amplitude Response),可取正负值。而|H(e^jω)|是幅度谱(Magnitude Response),始终非负。
//=============================================
// dsp_fir_direct.v
// FIR直接型滤波器
// y[n] = Σ h[k] * x[n-k]
//=============================================
module dsp_fir_direct #(
parameter DATA_WIDTH = 16,
parameter COEFF_WIDTH = 16,
parameter TAP = 16, // 滤波器抽头数
parameter OUT_WIDTH = 32
)(
input wire clk,
input wire rst_n,
input wire data_valid,
input wire signed [DATA_WIDTH-1:0] data_in,
input wire signed [COEFF_WIDTH-1:0] coeffs [0:TAP-1],
output reg signed [OUT_WIDTH-1:0] data_out,
output reg out_valid
);
// 延迟线(移位寄存器)
reg signed [DATA_WIDTH-1:0] shift_reg [0:TAP-1];
integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (i = 0; i < TAP; i = i + 1)
shift_reg[i] <= 0;
data_out <= 0;
out_valid <= 1'b0;
end else if (data_valid) begin
// 移入新数据
shift_reg[0] <= data_in;
for (i = 1; i < TAP; i = i + 1)
shift_reg[i] <= shift_reg[i-1];
// 乘累加(MAC)
data_out <= mac_compute();
out_valid <= 1'b1;
end else begin
out_valid <= 1'b0;
end
end
// MAC函数
function signed [OUT_WIDTH-1:0] mac_compute;
reg signed [OUT_WIDTH-1:0] acc;
reg signed [DATA_WIDTH+COEFF_WIDTH-1:0] product;
integer k;
begin
acc = 0;
for (k = 0; k < TAP; k = k + 1) begin
product = shift_reg[k] * coeffs[k];
acc = acc + product;
end
mac_compute = acc;
end
endfunction
endmodule
利用线性相位FIR系数的对称性 h[k] = h[M-k],将乘法器数量减半:
//=============================================
// dsp_fir_symmetric.v
// 对称系数FIR滤波器
// 利用 h[k] = h[M-k] 减半乘法器
//=============================================
module dsp_fir_symmetric #(
parameter DATA_WIDTH = 16,
parameter COEFF_WIDTH = 16,
parameter TAP = 16, // 必须为偶数
parameter OUT_WIDTH = 32
)(
input wire clk,
input wire rst_n,
input wire data_valid,
input wire signed [DATA_WIDTH-1:0] data_in,
input wire signed [COEFF_WIDTH-1:0] coeffs [0:TAP/2-1],
output reg signed [OUT_WIDTH-1:0] data_out,
output reg out_valid
);
reg signed [DATA_WIDTH-1:0] shift_reg [0:TAP-1];
integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (i = 0; i < TAP; i = i + 1)
shift_reg[i] <= 0;
data_out <= 0;
out_valid <= 1'b0;
end else if (data_valid) begin
shift_reg[0] <= data_in;
for (i = 1; i < TAP; i = i + 1)
shift_reg[i] <= shift_reg[i-1];
data_out <= sym_mac();
out_valid <= 1'b1;
end else begin
out_valid <= 1'b0;
end
end
function signed [OUT_WIDTH-1:0] sym_mac;
reg signed [OUT_WIDTH-1:0] acc;
reg signed [DATA_WIDTH:0] sym_sum;
reg signed [DATA_WIDTH+1+COEFF_WIDTH-1:0] product;
integer k;
begin
acc = 0;
for (k = 0; k < TAP/2; k = k + 1) begin
// 先加对称位置的数据,再乘系数
sym_sum = shift_reg[k] + shift_reg[TAP-1-k];
product = sym_sum * coeffs[k];
acc = acc + product;
end
sym_mac = acc;
end
endfunction
endmodule
//=============================================
// tb_fir_direct.v
// FIR直接型滤波器测试台
//=============================================
`timescale 1ns/1ps
module tb_fir_direct;
parameter DATA_WIDTH = 16;
parameter COEFF_WIDTH = 16;
parameter TAP = 8;
parameter OUT_WIDTH = 32;
parameter CLK_PERIOD = 10;
reg clk;
reg rst_n;
reg data_valid;
reg signed [DATA_WIDTH-1:0] data_in;
reg signed [COEFF_WIDTH-1:0] coeffs [0:TAP-1];
wire signed [OUT_WIDTH-1:0] data_out;
wire out_valid;
dsp_fir_direct #(
.DATA_WIDTH(DATA_WIDTH),
.COEFF_WIDTH(COEFF_WIDTH),
.TAP(TAP),
.OUT_WIDTH(OUT_WIDTH)
) uut (
.clk(clk), .rst_n(rst_n),
.data_valid(data_valid),
.data_in(data_in),
.coeffs(coeffs),
.data_out(data_out),
.out_valid(out_valid)
);
initial clk = 0;
always #(CLK_PERIOD/2) clk = ~clk;
initial begin
$dumpfile("fir_direct.vcd");
$dumpvars(0, tb_fir_direct);
// 初始化移动平均系数
coeffs[0] = 17'sd4096; // 1/8 * 32768
coeffs[1] = 17'sd4096;
coeffs[2] = 17'sd4096;
coeffs[3] = 17'sd4096;
coeffs[4] = 17'sd4096;
coeffs[5] = 17'sd4096;
coeffs[6] = 17'sd4096;
coeffs[7] = 17'sd4096;
rst_n = 0; data_valid = 0; data_in = 0;
#100;
rst_n = 1;
// 测试脉冲响应
data_in = 32767; // 单脉冲
data_valid = 1;
@(posedge clk);
data_in = 0;
repeat(TAP + 5) @(posedge clk);
data_valid = 0;
$display("脉冲响应测试完成");
$display("=== FIR直接型测试通过 ===");
$finish;
end
endmodule
| 参数 | 符号 | 说明 | 典型值 |
|---|---|---|---|
| 通带截止频率 | ωp | 通带边沿频率 | 0.2π |
| 阻带起始频率 | ωs | 阻带边沿频率 | 0.3π |
| 过渡带宽度 | Δω | ωs - ωp | 0.1π |
| 通带波纹 | δp | 通带最大偏差 | 0.01 (~-40dB) |
| 阻带衰减 | δs | 阻带最大增益 | 0.001 (~-60dB) |
| 滤波器阶数 | M | 由过渡带和衰减决定 | 经验公式估算 |
3阶FIR系数 h[n] = {1, 2, 2, 1},输入 x[n] = {1, -1, 2, 0, -1},手动计算输出y[n]。
提示:y[n] = h[0]x[n] + h[1]x[n-1] + h[2]x[n-2] + h[3]x[n-3]
验证 h[n] = {1, 2, 3, 2, 1} 是否为线性相位FIR,并确定其类型。计算群延迟。
设计FIR低通滤波器:通带0-4kHz,阻带5kHz以上,通带波纹0.1dB,阻带衰减50dB,采样率20kHz。用Kaiser公式估算所需阶数。
修改 dsp_fir_symmetric.v,支持奇数抽头数(即中心抽头不需要配对乘法,单独处理)。
✅ 理解了FIR滤波器的基本原理与系统函数
✅ 掌握了FIR vs IIR的核心区别
✅ 实现了直接型FIR滤波器
✅ 实现了对称系数优化FIR(乘法器减半)
✅ 理解了线性相位四种类型和群延迟
✅ 掌握了FIR设计指标与阶数估算
FIR滤波器原理在进阶应用中还有以下重要主题值得深入研究:
本课内容在整个DSP课程体系中处于承上启下的位置:
在实际工程中,FIR滤波器原理的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。
在实际工程中,FIR滤波器原理的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。
在实际工程中,FIR滤波器原理的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。
在实际工程中,FIR滤波器原理的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。
在实际工程中,FIR滤波器原理的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。