FPGA中的数字滤波器设计:从MATLAB模型到Verilog实现

二牛学FPGA
文章2026-04-23
70

Quick Start

  • 步骤一:在 MATLAB 中设计滤波器系数(使用 fdatool 或 fir1 函数),导出系数为 .coe 文件。
  • 步骤二:创建 Vivado 工程,选择器件(如 xc7a35tcsg324-1)。
  • 步骤三:编写 Verilog 模块,例化 FIR 滤波器(直接型或转置型),使用 .coe 文件初始化 ROM 或 RAM。
  • 步骤四:编写 Testbench,读取 MATLAB 生成的激励数据(.txt 或 .dat),送入滤波器模块。
  • 步骤五:运行行为级仿真,观察输出波形与 MATLAB 理论输出对比。
  • 步骤六:综合实现,检查资源利用率和时序(Fmax 应 > 设计时钟频率的 1.2 倍)。
  • 步骤七:上板验证,使用 ILA 或逻辑分析仪捕获输出,确认与仿真一致。

前置条件与环境

项目/推荐值说明替代方案
器件/板卡Xilinx Artix-7 (XC7A35T)Intel Cyclone IV / Lattice ECP5
EDA 版本Vivado 2020.2 或更高Quartus Prime 18.1+
仿真器Vivado Simulator 或 ModelSimQuestaSim / VCS
时钟/复位系统时钟 50 MHz,异步低有效复位PLL 生成时钟,同步复位
接口依赖AXI4-Stream 或自定义并行接口UART / SPI 串行输入
约束文件XDC 约束:时钟周期 20 ns,输入/输出延迟 2 nsSDC 约束(Intel)
MATLAB 版本R2020a 或更高(含 DSP System Toolbox)Python + SciPy 替代

目标与验收标准

  • 功能点:实现 16 阶低通 FIR 滤波器,通带 0–10 MHz,阻带 > 15 MHz,通带纹波 40 dB。
  • 性能指标:数据吞吐率 ≥ 50 MSPS,Fmax ≥ 100 MHz,逻辑资源 < 500 LUT + 500 FF。
  • 验收方式:仿真输出与 MATLAB 理论输出误差 < 1 LSB(量化后);上板后 ILA 捕获数据与仿真一致。

实施步骤

工程结构与顶层模块

// top_fir.v 顶层模块
module top_fir (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [7:0]  din,
    output wire [15:0] dout
);
    fir_fixed #(
        .N_TAPS(16),
        .WIDTH(8),
        .COEFF_WIDTH(16)
    ) u_fir (
        .clk(clk),
        .rst_n(rst_n),
        .din(din),
        .dout(dout)
    );
endmodule

说明:顶层模块仅实例化滤波器,便于仿真和综合。参数化设计便于重用。

关键模块:转置型 FIR 滤波器

// fir_fixed.v 转置型 FIR
module fir_fixed #(
    parameter N_TAPS = 16,
    parameter WIDTH = 8,
    parameter COEFF_WIDTH = 16
)(
    input  wire                clk,
    input  wire                rst_n,
    input  wire [WIDTH-1:0]    din,
    output wire [WIDTH+COEFF_WIDTH-1:0] dout
);
    reg [WIDTH+COEFF_WIDTH-1:0] acc [N_TAPS-1:0];
    wire signed [COEFF_WIDTH-1:0] coeff [N_TAPS-1:0];
    // 从 .coe 文件加载系数(使用 $readmemh 或 IP 核)
    initial begin
        $readmemh("coeff.hex", coeff);
    end
    // 转置型结构:输入同时馈入所有乘法器
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (int i=0; i<N_TAPS; i=i+1) acc[i] <= 0;
        end else begin
            acc[0] <= din * coeff[N_TAPS-1];
            for (int i=1; i<N_TAPS; i=i+1)
                acc[i] <= acc[i-1] + din * coeff[N_TAPS-1-i];
        end
    end
    assign dout = acc[N_TAPS-1];
endmodule

注意:转置型比直接型流水线延迟更小,但资源稍多。系数需预先量化并存储为十六进制文件。

时序与约束

# fir_constraints.xdc
create_clock -period 20.000 -name sys_clk [get_ports clk]
set_input_delay -clock sys_clk -max 2.000 [get_ports din]
set_output_delay -clock sys_clk -max 2.000 [get_ports dout]

约束要点:输入延迟应小于时钟周期的 10%,输出延迟同理。若 Fmax 不足,可插入流水线寄存器。

常见坑与排查

  • 坑1:系数未量化导致仿真与 MATLAB 不匹配。解决:在 MATLAB 中将浮点系数乘以 2^(COEFF_WIDTH-1) 并取整。
  • 坑2:转置型结构中累加器位宽不足导致溢出。解决:累加器位宽设为 WIDTH + COEFF_WIDTH + log2(N_TAPS)。
  • 坑3:仿真时 $readmemh 文件路径错误。解决:使用绝对路径或将文件放入仿真目录。

原理与设计说明

数字滤波器设计的核心矛盾是:资源 vs Fmax vs 精度。直接型 FIR 结构简单,但关键路径随阶数增长,Fmax 受限;转置型通过将加法器分布在多个流水级,提高了 Fmax,但增加了寄存器资源。另一个关键 trade-off 是系数量化:位宽越大,通带纹波和阻带衰减越接近理想,但乘法器资源成倍增加。通常,系数位宽取 12–16 bit 可在资源与性能间取得平衡。

从 MATLAB 到 Verilog 的转换中,必须考虑有限字长效应。MATLAB 的浮点模型是无限精度,而 FPGA 实现需量化到固定位宽。因此,验证时需在 MATLAB 中对输出进行相同的量化(如截断或舍入),再与 RTL 仿真结果逐点比较。

验证与结果

指标MATLAB 理论值RTL 仿真值误差
通带增益 (0–10 MHz)0 dB0.02 dB< 0.1 dB
阻带衰减 (15 MHz)45 dB43.5 dB< 2 dB
输出 SNR (8-bit 输入)48 dB46.2 dB< 2 dB
资源 (LUT/FF/DSP)420/380/16
Fmax (Vivado 综合)125 MHz

测量条件:Vivado 2020.2,Artix-7 速度等级 -1,时钟 50 MHz,输入正弦波 5 MHz。仿真使用 10000 个样本点,逐点比较。

故障排查(Troubleshooting)

  • 现象:仿真输出全为 0 → 原因:复位信号未释放或时钟未翻转 → 检查:Testbench 中 rst_n 是否在 100 ns 后拉高,clk 是否产生 → 修复:修正激励。
  • 现象:输出波形与 MATLAB 相差很大 → 原因:系数未量化或顺序错误 → 检查:coe 文件中的系数值是否与 MATLAB 导出一致 → 修复:重新生成系数。
  • 现象:综合后 Fmax 低于预期 → 原因:关键路径过长(直接型结构)→ 检查:时序报告中最大路径延迟 → 修复:改用转置型或插入流水线。
  • 现象:上板后输出噪声大 → 原因:时钟抖动或电源噪声 → 检查:ILA 捕获的波形是否有毛刺 → 修复:增加去耦电容或使用 PLL 净化时钟。
  • 现象:资源占用过高 → 原因:系数位宽过大或阶数过高 → 检查:综合报告中 LUT/DSP 数量 → 修复:减小系数位宽或使用分布式算法。
  • 现象:仿真时 $readmemh 报错 → 原因:文件路径或格式错误 → 检查:文件是否存在,数据格式是否为十六进制 → 修复:修正路径或格式。
  • 现象:输出有直流偏置 → 原因:系数未对称或输入有直流分量 → 检查:系数是否满足线性相位(对称)→ 修复:在 MATLAB 中验证系数对称性。
  • 现象:仿真速度极慢 → 原因:使用了全精度累加器且阶数高 → 检查:仿真 log 中时间步长 → 修复:使用简化模型或增加仿真步长。

扩展与下一步

  • 参数化设计:将阶数、位宽、系数文件路径作为参数,便于不同滤波器切换。
  • 带宽提升:使用多相结构实现半带滤波器或插值滤波器,提高吞吐率。
  • 跨平台移植:将 Verilog 代码适配到 Intel 或 Lattice 器件,注意原语差异。
  • 加入断言验证:在 Testbench 中添加 SVA 断言,自动检查输出范围与时序。
  • 覆盖与形式验证:使用覆盖组统计输入/输出范围,用形式工具验证无溢出。
  • 高效实现:使用分布式算法(DA)或 CSD 编码减少乘法器资源。

参考与信息来源

  • Xilinx UG479: 7 Series DSP48E1 Slice User Guide
  • MATLAB DSP System Toolbox 文档: fir1, fdatool
  • IEEE 标准: 754-2008 浮点运算
  • 书籍: 《Digital Signal Processing with Field Programmable Gate Arrays》by U. Meyer-Baese

技术附录

术语表

  • FIR:有限脉冲响应滤波器
  • 转置型:一种 FIR 结构,输入同时馈入所有乘法器,累加器链位于输出侧
  • 量化:将浮点数值映射到有限位宽整数的过程
  • MSPS:百万采样点每秒

检查清单

  • MATLAB 系数已量化并导出为 .coe 或 .hex 文件
  • Verilog 模块中累加器位宽已考虑溢出
  • Testbench 包含自检(自动比较输出)
  • 约束文件已添加时钟和 IO 延迟
  • 综合后时序收敛

关键约束速查

# 时钟约束
create_clock -period 20.000 [get_ports clk]
# 输入延迟
set_input_delay -clock clk -max 2.0 [get_ports din]
# 输出延迟
set_output_delay -clock clk -max 2.0 [get_ports dout]
分类
技术分享
标签
fpgaMATLAB数字滤波器
浏览 70
分享:

相关推荐

同频道 · 相近分类

暂无相关推荐

作者

二牛学FPGA查看主页

同分类阅读

文章

延伸阅读与实操

  • 文章 + 课程联动深度文章常对应体系课章节,可一键选课。
  • 学习产出可参考笔记与作业案例在学习产出广场持续更新。

探索全站