FIR滤波器的直接型硬件实现——延迟线与MAC
直接型(Direct Form)是FIR最自然的实现结构,直接对应差分方程y[n]=Σh[k]x[n-k]。硬件由移位寄存器(延迟线)和乘累加器(MAC)组成。关键路径:1个乘法器延迟+log₂(M+1)个加法器延迟。
//=============================================
// dsp_fir_pipelined.v
// 流水线直接型FIR
// 加法树+流水线寄存器优化时序
//=============================================
module dsp_fir_pipelined #(
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] sr [0:TAP-1];
reg signed [DATA_WIDTH+COEFF_WIDTH-1:0] products [0:TAP-1];
reg prod_valid;
reg signed [OUT_WIDTH-1:0] partial [0:TAP/2-1];
reg partial_valid;
integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (i=0;i<TAP;i=i+1) begin sr[i]<=0; products[i]<=0; end
prod_valid <= 0;
end else if (data_valid) begin
sr[0] <= data_in;
for (i=1;i<TAP;i=i+1) sr[i] <= sr[i-1];
for (i=0;i<TAP;i=i+1) products[i] <= sr[i]*coeffs[i];
prod_valid <= 1;
end else prod_valid <= 0;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (i=0;i<TAP/2;i=i+1) partial[i]<=0;
partial_valid <= 0;
end else if (prod_valid) begin
for (i=0;i<TAP/2;i=i+1)
partial[i] <= products[2*i]+products[2*i+1];
partial_valid <= 1;
end else partial_valid <= 0;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin data_out<=0; out_valid<=0; end
else if (partial_valid) begin
data_out <= 0;
for (i=0;i<TAP/2;i=i+1) data_out <= data_out+partial[i];
out_valid <= 1;
end else out_valid <= 0;
end
endmodule
//=============================================
// dsp_fir_circular.v
// 循环缓冲区FIR——避免数据搬移
//=============================================
module dsp_fir_circular #(
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] buffer [0:TAP-1];
reg [$clog2(TAP)-1:0] write_ptr;
integer i; reg [$clog2(TAP)-1:0] read_ptr;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin write_ptr<=0; data_out<=0; out_valid<=1'b0;
for (i=0;i<TAP;i=i+1) buffer[i]<=0;
end else if (data_valid) begin
buffer[write_ptr] <= data_in;
data_out <= 0;
for (i=0;i<TAP;i=i+1) begin
read_ptr = (write_ptr-i)%TAP;
data_out <= data_out + buffer[read_ptr]*coeffs[i];
end
write_ptr <= write_ptr+1'b1;
out_valid <= 1'b1;
end else out_valid <= 1'b0;
end
endmodule
| 量化位数 | 阻带衰减退化 | 适用场景 |
|---|---|---|
| 32位浮点 | 无 | 仿真验证 |
| 24位定点 | <1dB | 高精度音频 |
| 16位定点 | 1-3dB | 通用信号处理 |
| 12位定点 | 3-10dB | 低精度应用 |
| 技术 | 乘法器数 | 适用场景 |
|---|---|---|
| 对称系数优化 | (M+1)/2 | 线性相位FIR |
| 时分复用单MAC | 1 | 低速应用 |
| CSD编码 | 0(用加法) | 常数系数 |
| 子滤波器共享 | (M+1)/L | 多通道 |
64阶直接型FIR,乘法器延迟3ns,加法器延迟1ns,求最大时钟频率。若插入2级流水线,频率提升多少?
用仿真验证dsp_fir_circular.v与dsp_fir_direct.v在相同输入下输出一致。
设计单乘法器时分复用FIR:工作时钟为采样率的TAP倍,每TAP个时钟周期完成一次完整MAC。
将系数h[k]={0.125,0.375,0.5,0.375,0.125}转换为CSD编码,统计非零位数。
✅ 深入理解了FIR直接型结构
✅ 实现了流水线优化的直接型FIR
✅ 掌握了循环缓冲区FIR设计
✅ 理解了关键路径与时序优化
✅ 了解了CSD编码等面积优化技术
✅ 掌握了系数量化对频率响应的影响
在电池供电的嵌入式系统中,FIR滤波器的功耗是关键指标:
关键路径分析是高性能FIR设计的核心:
其中T_setup为触发器建立时间,T_mult为乘法器延迟,T_add为加法器延迟,T_wire为布线延迟。对于64阶FIR:T_mult=3ns, T_add=1ns, log₂65≈7,关键路径≈3+7×1=10ns,最大频率100MHz。插入流水线后:T_clk≈max(T_mult, T_add+T_setup)≈4ns,最大频率250MHz。
正则有符号数字(CSD)编码将每个系数表示为最少的非零位,用加法/减法替代乘法器:
| 十进制 | 二进制 | CSD | 非零位数 |
|---|---|---|---|
| 0.125 | 0.0010 | 0.0010 | 1 |
| 0.375 | 0.0110 | 0.10̄10 | 2 |
| 0.5 | 0.1000 | 0.1000 | 1 |
| 0.6875 | 0.1011 | 1.0̄10̄1 | 3 |
关键路径分析是高性能FIR设计的核心。对于M阶直接型FIR:
其中T_setup为触发器建立时间,T_mult为乘法器延迟,T_add为加法器延迟,T_wire为布线延迟。
| 阶数M | 加法树深度 | T_critical(ns) | Fmax(MHz) |
|---|---|---|---|
| 16 | 4 | 3+4×1=7 | 143 |
| 32 | 5 | 3+5×1=8 | 125 |
| 64 | 7 | 3+7×1=10 | 100 |
| 128 | 8 | 3+8×1=11 | 91 |
插入2级流水线后:T_clk ≈ max(T_mult, T_add+T_setup) ≈ 4ns,Fmax ≈ 250MHz
正则有符号数字(CSD)编码将系数表示为最少非零位,用加减法替代乘法器:
| 十进制 | 二进制 | CSD | 非零位数(二进制) | 非零位数(CSD) | 节省 |
|---|---|---|---|---|---|
| 0.125 | 0.0010 | 0.0010 | 1 | 1 | 0% |
| 0.375 | 0.0110 | 0.10̄10 | 2 | 2 | 0% |
| 0.6875 | 0.1011 | 1.0̄10̄1 | 3 | 3 | 0% |
| 0.4375 | 0.0111 | 0.100̄1 | 3 | 2 | 33% |
| 0.9375 | 0.1111 | 1.000̄1 | 4 | 2 | 50% |
CSD编码对FIR的面积优化:16位系数平均非零位数从8位降至4-5位,加法器数量减半。在FPGA上,每个非零位对应一个LUT+加法器,CSD编码可将DSP slice使用量降低40-60%。
Xilinx FPGA的DSP48E2 slice天然适配FIR的MAC运算:
| FIR组件 | DSP48功能 | 说明 |
|---|---|---|
| 乘法器 | 25×18 pre-adder+multiplier | 支持对称预加 |
| 累加器 | 48-bit accumulator | 自动扩展精度 |
| 流水线 | 内部3级寄存器 | 最高~500MHz |
| 级联 | PCOUT→PCIN级联 | 无额外路由延迟 |
关键:DSP48E2的A:B端口支持25×18乘法,B端口18位可用于系数。内部预加器(B+D)×A支持对称FIR的x[n]+x[n-M]预加,节省一半乘法器。
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)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。
在实际工程中,FIR直接型结构的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。