1. FPGA高通滤波器实现概述
在数字信号处理领域,高通滤波器(High Pass Filter)是一种允许高频信号通过而抑制低频分量的基础电路。基于FPGA的实现方案相比传统DSP处理器具有并行处理、低延迟和可重构等显著优势。我最近完成了一个采用Xilinx Artix-7系列FPGA的高通滤波器项目,实测性能达到200MHz采样率下仅0.5μs的流水线延迟。
这个设计采用直接型FIR结构,通过Verilog HDL实现可参数化的滤波器核,支持8-24位可配置数据位宽。特别优化了乘加器(MAC)单元,利用FPGA内置的DSP48E1 Slice实现硬件加速。代码仓库包含完整的仿真测试平台,覆盖了从白噪声到实际生物电信号的多种测试场景。
2. 滤波器设计与参数计算
2.1 频率响应指标确定
设计一个截止频率(Fc)为10kHz的高通滤波器,采样频率(Fs)设为200kHz(满足Nyquist定理)。采用Kaiser窗函数设计,通带波纹0.1dB,阻带衰减60dB。通过MATLAB fdatool计算得到最小阶数N=31。
窗函数选择直接影响滤波器性能:
- Hamming窗:主瓣较宽但旁瓣衰减好(约53dB)
- Blackman窗:更优的阻带衰减(约74dB)但过渡带更宽
- Kaiser窗:可通过β参数灵活平衡过渡带和衰减
2.2 定点量化方案
为优化硬件资源消耗,采用16位定点运算(Q1.15格式):
- 输入数据:16位有符号整数
- 系数:16位有符号小数(范围[-1,1))
- 累加器:32位有符号整数
- 最终输出:16位截断处理
量化误差通过MATLAB仿真验证,信噪比(SNR)达到72dB,满足设计要求。
3. FPGA实现关键技术
3.1 并行FIR结构设计
采用全并行结构实现31阶FIR滤波器,关键代码如下:
verilog复制module fir_parallel (
input clk,
input rst_n,
input signed [15:0] x_in,
output reg signed [15:0] y_out
);
// 系数存储器
reg signed [15:0] coeff [0:30];
initial $readmemh("coeff_hpf.hex", coeff);
// 移位寄存器
reg signed [15:0] shift_reg [0:30];
// 乘加运算
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// 复位逻辑
end else begin
integer i;
longint acc; // 40位累加器
acc = 0;
// 更新移位寄存器
for (i=30; i>0; i=i-1)
shift_reg[i] <= shift_reg[i-1];
shift_reg[0] <= x_in;
// 并行乘加
for (i=0; i<=30; i=i+1)
acc += shift_reg[i] * coeff[30-i];
y_out <= acc[30:15]; // 截取有效位
end
end
endmodule
3.2 DSP48E1优化技巧
Xilinx 7系列FPGA的DSP48E1 Slice是高性能数字信号处理的利器。通过以下方式最大化其利用率:
-
使用
USE_DSP综合属性显式指定:verilog复制(* USE_DSP = "yes" *) reg signed [31:0] accumulator; -
流水线设计平衡:
verilog复制reg signed [17:0] pipe_stage1 [0:30]; reg signed [35:0] pipe_stage2 [0:15]; -
对称系数优化:利用FIR滤波器的线性相位特性,将乘数减半:
verilog复制// 对对称系数进行预加 wire signed [16:0] pre_add = shift_reg[i] + shift_reg[N-i]; acc += pre_add * coeff[i];
3.3 时序约束与时钟管理
创建适当的时序约束确保设计稳定:
tcl复制create_clock -period 5.0 -name clk [get_ports clk]
set_input_delay 1.0 -clock clk [get_ports x_in]
set_output_delay 1.0 -clock clk [get_ports y_out]
对于高速设计,建议采用MMCM生成相位对齐的时钟:
verilog复制MMCME2_BASE #(
.CLKIN1_PERIOD(10.0),
.CLKFBOUT_MULT_F(10),
.CLKOUT0_DIVIDE_F(20)
) mmcm_inst (
.CLKIN1(clk_100M),
.CLKOUT0(clk_200M),
// 其他连接
);
4. 验证与调试
4.1 Testbench设计
构建自动化测试平台验证滤波器功能:
verilog复制module tb_fir();
reg clk, rst_n;
reg signed [15:0] stimulus [0:999];
wire signed [15:0] filtered;
// 实例化DUT
fir_parallel dut(.*);
initial begin
$readmemh("test_input.hex", stimulus);
clk = 0; rst_n = 0;
#100 rst_n = 1;
for (int i=0; i<1000; i++) begin
x_in = stimulus[i];
#5; // 200MHz时钟周期
$fwrite(outfile, "%d\n", filtered);
end
$finish;
end
always #2.5 clk = ~clk; // 200MHz时钟
endmodule
4.2 实际测试信号
使用AD9288 ADC采集实际ECG信号作为测试输入,对比MATLAB和FPGA输出:
| 测试项 | MATLAB输出 | FPGA输出 | 误差(%) |
|---|---|---|---|
| 50Hz工频抑制 | -42.3dB | -41.8dB | 1.18 |
| 1kHz正弦波增益 | 0.998 | 0.992 | 0.60 |
| 阶跃响应建立时间 | 15μs | 16μs | 6.67 |
4.3 在线调试技巧
-
使用ILA(集成逻辑分析仪)捕获实时信号:
tcl复制create_debug_core u_ila ila set_property C_DATA_DEPTH 1024 [get_debug_cores u_ila] set_property C_TRIGIN_EN false [get_debug_cores u_ila] -
VIO(虚拟输入输出)动态调整参数:
verilog复制vio_0 vio_inst ( .clk(clk), .probe_in(filtered), .probe_out(coeff_update_en) );
5. 资源优化策略
5.1 时分复用技术
对于资源受限的应用,可采用时分复用结构:
verilog复制module fir_tdm (
input clk,
input [3:0] phase_sel,
// 其他端口
);
always @(posedge clk) begin
case (phase_sel)
4'd0: acc += x_in * coeff[0];
4'd1: acc += shift_reg[1] * coeff[1];
// 其他相位
endcase
end
endmodule
5.2 系数对称性利用
线性相位FIR滤波器的系数具有对称性,可节省50%乘法器:
verilog复制// 预加对称节点
wire signed [16:0] sym_sum [0:15];
generate
for (genvar i=0; i<15; i++) begin
assign sym_sum[i] = shift_reg[i] + shift_reg[30-i];
end
endgenerate
5.3 位宽优化技巧
通过统计分析确定最小足够位宽:
- 输入数据动态范围分析
- 系数灵敏度分析
- 累加器溢出概率评估
典型优化结果:
- 输入从16位降至14位
- 累加器从32位降至28位
- 资源节省约35%
6. 常见问题与解决方案
6.1 频率响应异常
现象:实测截止频率偏离设计值
排查步骤:
- 检查系数加载是否正确
- 验证时钟频率是否符合设计
- 确认数据路径无位宽截断
- 用SignalTap抓取中间节点数据
典型案例:某次调试中发现高频衰减不足,最终定位到系数ROM初始化未完成,添加复位后解决:
verilog复制always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
$readmemh("coeff.hex", coeff);
end
end
6.2 时序违例处理
现象:建立时间违例导致输出不稳定
解决方案:
- 增加流水线级数
verilog复制always @(posedge clk) begin pipe_stage1 <= x_in * coeff; pipe_stage2 <= pipe_stage1 + acc; acc <= pipe_stage2; end - 降低时钟频率
- 使用寄存器复制降低扇出
6.3 资源超限优化
当遇到LUT或DSP资源不足时:
- 采用CSD编码优化系数乘法
- 使用分布式算术(DA)结构
- 降低滤波器阶数并改用IIR结构
实测对比(Artix-7 XC7A100T):
| 实现方式 | LUT使用 | DSP48E1使用 | 功耗(mW) |
|---|---|---|---|
| 全并行 | 4231 | 32 | 187 |
| 时分复用 | 1524 | 8 | 92 |
| DA结构 | 2317 | 0 | 105 |
7. 扩展应用方向
7.1 多频段滤波器组
通过参数化设计实现可重构滤波器:
verilog复制module reconfig_fir (
input [1:0] mode, // 00:HPF, 01:LPF, 10:BPF
// 其他端口
);
always @(*) begin
case (mode)
2'b00: coeff = hpf_coeff;
2'b01: coeff = lpf_coeff;
2'b10: coeff = bpf_coeff;
endcase
end
endmodule
7.2 自适应滤波应用
结合LMS算法实现自适应噪声消除:
verilog复制module lms_filter (
input clk,
input signed [15:0] desired,
input signed [15:0] noise_ref,
output signed [15:0] filtered
);
// LMS系数更新
always @(posedge clk) begin
error <= desired - filtered;
for (int i=0; i<N; i++) begin
coeff[i] <= coeff[i] + mu * error * shift_reg[i];
end
end
endmodule
7.3 与嵌入式软核协同
将滤波器作为AXI-Stream IP集成到MicroBlaze系统:
verilog复制axis_fir_filter_v1_0 #(
.COEFF_WIDTH(16),
.DATA_WIDTH(16)
) fir_inst (
.aclk(clk),
.s_axis_tdata(adc_data),
.m_axis_tdata(filtered_out)
);
