1. 项目概述
作为一名FPGA工程师,我经常需要在嵌入式系统中实现各种数字信号处理功能。高通滤波器作为基础的数字滤波器之一,在信号处理领域有着广泛的应用场景。今天我想分享一个完整的FPGA高通滤波器实现方案,包含FIR和IIR两种实现方式,以及我在实际项目中的一些经验教训。
这个项目的主要目标是使用Verilog HDL在FPGA上实现可配置的高通滤波器,适用于需要滤除低频噪声或提取高频成分的应用场景。我们将从滤波器原理讲起,逐步深入到FPGA实现细节,最后给出完整的代码实现和实测结果。
2. 滤波器基础与选型考量
2.1 高通滤波器基本原理
高通滤波器(High Pass Filter)是一种允许高频信号通过而衰减低频信号的滤波器。在数字信号处理中,我们通常通过设计特定的传递函数来实现这一特性。数字滤波器主要分为两大类:
- FIR(有限脉冲响应)滤波器
- IIR(无限脉冲响应)滤波器
2.2 FIR与IIR滤波器对比
在实际项目中,选择FIR还是IIR需要考虑多个因素:
FIR滤波器特点:
- 绝对稳定(因为只有零点没有极点)
- 可以实现严格的线性相位特性
- 设计方法成熟(如窗函数法、频率采样法等)
- 需要较高的阶数才能达到陡峭的过渡带
IIR滤波器特点:
- 可以用较低的阶数实现较好的频率选择性
- 可能存在稳定性问题(需要仔细设计)
- 相位响应是非线性的
- 设计方法多样(如双线性变换法、脉冲响应不变法等)
提示:在需要严格线性相位的应用(如通信系统)中,FIR是更好的选择;而在资源受限且对相位不敏感的场景,IIR可能更合适。
3. FIR高通滤波器的FPGA实现
3.1 设计参数确定
在开始编码前,我们需要明确滤波器的规格参数:
- 采样频率(Fs):假设为48kHz
- 截止频率(Fc):设计为5kHz
- 通带波纹:≤0.1dB
- 阻带衰减:≥60dB
- 滤波器阶数:51阶(通过MATLAB fir1函数计算得出)
3.2 系数生成与量化
使用MATLAB生成滤波器系数:
matlab复制% FIR高通滤波器设计示例
Fs = 48000; % 采样频率
Fc = 5000; % 截止频率
N = 50; % 滤波器阶数(实际抽头数为N+1)
% 使用汉明窗设计FIR高通滤波器
b = fir1(N, Fc/(Fs/2), 'high', hamming(N+1));
% 系数量化(16位有符号数,14位小数)
b_quant = round(b * 2^14);
量化后的系数需要导出为适合FPGA使用的格式(如COE文件或直接嵌入Verilog代码)。
3.3 Verilog实现核心代码
以下是FIR高通滤波器的完整Verilog实现:
verilog复制module FIR_HPF #(
parameter COEFF_WIDTH = 16, // 系数位宽
parameter DATA_WIDTH = 16, // 数据位宽
parameter TAPS = 51, // 滤波器阶数(奇数)
parameter FRAC_BITS = 14 // 小数位数
)(
input wire clk,
input wire reset_n,
input wire signed [DATA_WIDTH-1:0] data_in,
output reg signed [DATA_WIDTH-1:0] data_out
);
// 滤波器系数(51阶高通滤波器示例)
localparam signed [COEFF_WIDTH-1:0] coeff [0:TAPS-1] = '{
16'hFF9C, 16'hFFA1, 16'hFFA6, /* 其他系数省略 */, 16'h02A3
};
// 移位寄存器存储输入数据
reg signed [DATA_WIDTH-1:0] shift_reg [0:TAPS-1];
integer i;
// 乘法累加中间结果
reg signed [COEFF_WIDTH+DATA_WIDTH-1:0] mac_result;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
// 复位逻辑
for (i = 0; i < TAPS; i = i + 1)
shift_reg[i] <= 0;
data_out <= 0;
end else begin
// 移位寄存器更新
for (i = TAPS-1; i > 0; i = i - 1)
shift_reg[i] <= shift_reg[i-1];
shift_reg[0] <= data_in;
// 乘累加运算
mac_result = 0;
for (i = 0; i < TAPS; i = i + 1)
mac_result = mac_result + shift_reg[i] * coeff[i];
// 输出结果(考虑量化位宽)
data_out <= mac_result >>> FRAC_BITS;
end
end
endmodule
3.4 实现优化技巧
在实际FPGA实现中,我们可以采用以下优化策略:
- 流水线设计:将长关键路径(如乘累加链)分割为多个流水级,提高工作频率
- 对称性利用:对于线性相位FIR滤波器,可以利用系数的对称性减少乘法器数量
- 分布式算法:使用DA(Distributed Arithmetic)技术进一步优化资源使用
注意:高阶FIR滤波器会消耗大量DSP资源,在资源受限的FPGA上需要谨慎选择阶数。
4. IIR高通滤波器的FPGA实现
4.1 IIR滤波器设计考虑
IIR滤波器设计比FIR更复杂,主要考虑因素包括:
- 稳定性保证:极点必须在单位圆内
- 量化效应:系数量化可能影响滤波器特性
- 结构选择:直接型、级联型或并联型
4.2 二阶节(SOS)实现
为避免高阶IIR滤波器的数值问题,通常采用二阶节级联结构:
verilog复制module IIR_HPF_SOS #(
parameter DATA_WIDTH = 16,
parameter COEFF_WIDTH = 16,
parameter FRAC_BITS = 14
)(
input wire clk,
input wire reset_n,
input wire signed [DATA_WIDTH-1:0] data_in,
output wire signed [DATA_WIDTH-1:0] data_out
);
// 定义二阶节系数(示例为5kHz高通,Fs=48kHz)
localparam signed [COEFF_WIDTH-1:0] b0 = 16'h7FFF;
localparam signed [COEFF_WIDTH-1:0] b1 = 16'h8001;
localparam signed [COEFF_WIDTH-1:0] b2 = 16'h7FFF;
localparam signed [COEFF_WIDTH-1:0] a1 = 16'h7F37;
localparam signed [COEFF_WIDTH-1:0] a2 = 16'h3E4F;
// 延迟寄存器
reg signed [DATA_WIDTH-1:0] x1, x2, y1, y2;
// 中间计算结果
wire signed [DATA_WIDTH+COEFF_WIDTH:0] y;
assign y = b0 * data_in + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
assign data_out = y >>> FRAC_BITS;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
x1 <= 0; x2 <= 0;
y1 <= 0; y2 <= 0;
end else begin
x2 <= x1;
x1 <= data_in;
y2 <= y1;
y1 <= data_out;
end
end
endmodule
4.3 稳定性验证
IIR滤波器实现后必须进行稳定性验证:
- 极点位置检查:所有极点必须在单位圆内
- 极限环测试:输入静音信号,观察输出是否趋于零
- 阶跃响应测试:观察瞬态响应是否收敛
5. 测试与验证方法
5.1 测试平台搭建
完整的测试平台应包括:
verilog复制module HPF_TB;
reg clk;
reg reset_n;
reg signed [15:0] stimulus;
wire signed [15:0] fir_out, iir_out;
// 实例化被测模块
FIR_HPF fir_uut (.*, .data_out(fir_out));
IIR_HPF_SOS iir_uut (.*, .data_out(iir_out));
// 时钟生成
initial begin
clk = 0;
forever #10 clk = ~clk;
end
// 复位生成
initial begin
reset_n = 0;
#100 reset_n = 1;
end
// 测试激励生成
initial begin
// 低频信号(1kHz) + 高频信号(8kHz)
for (int i=0; i<1000; i=i+1) begin
stimulus = $sin(2*3.1416*1000*i/48000) * 10000
+ $sin(2*3.1416*8000*i/48000) * 5000;
#20;
end
$finish;
end
endmodule
5.2 实测结果分析
通过ModelSim仿真,我们可以观察到:
- FIR滤波器输出:低频成分(1kHz)被明显衰减,高频成分(8kHz)保留完好
- IIR滤波器输出:同样实现高通特性,但相位响应呈现非线性
- 资源占用对比:
- FIR51阶:占用51个乘法器
- IIR4阶:仅占用5个乘法器
6. 实际项目经验分享
6.1 常见问题与解决
-
系数溢出问题:
- 现象:滤波器输出饱和或异常
- 解决:检查系数量化范围,必要时增加位宽或调整缩放因子
-
极限环振荡:
- 现象:输入为零时输出不归零
- 解决:采用更精细的量化或改用状态空间结构
-
频率响应偏差:
- 现象:实测截止频率与设计不符
- 解决:检查采样率设置和系数计算过程
6.2 优化建议
- 对于高阶FIR滤波器,考虑使用多相分解或FFT卷积方法
- 在高速应用中,使用FPGA的DSP硬核而非逻辑实现乘法器
- 动态可配置滤波器:通过系数重载实现参数可调
6.3 性能权衡
根据项目需求选择合适的实现方式:
| 需求特征 | 推荐实现 | 理由 |
|---|---|---|
| 严格线性相位 | FIR | 保证信号波形不失真 |
| 资源受限 | IIR | 同样性能下阶数更低 |
| 高速处理 | 流水线FIR | 易于实现高时钟频率 |
| 参数可调 | 查表法IIR | 便于运行时更新系数 |
我在最近的一个音频处理项目中,最终选择了72阶FIR高通滤波器实现,虽然资源占用较高,但确保了语音信号的相位特性不被破坏。实际测试表明,该滤波器能有效去除50Hz工频干扰,同时保留语音信号的高频成分。
