:并行 FIR 滤波器的 Verilog 全流程设计与实现)
前言作为 FPGA 数字信号处理系列的第二篇本文聚焦 DSP 系统中最常用的 FIR 滤波器从基础理论到硬件落地完整讲解15 阶低通并行 FIR 滤波器的设计全流程包含 FIR 滤波器原理推导、MATLAB 系数量化、Verilog 并行架构实现、Testbench 文件级仿真验证以及最终的工程资源与性能分析所有代码与工程均可直接复现。一、数字滤波器分类与选型数字滤波器是数字信号处理的核心模块通过对输入序列进行数学运算提取特定频率分量、抑制噪声或干扰。从实现结构上可分为两大类FIR有限长单位冲激响应与 IIR无限长单位冲激响应二者核心差异如下表格特性维度FIR 滤波器IIR 滤波器相位特性可实现严格线性相位信号无相位失真非线性相位不同频率分量延时不同系统稳定性无反馈回路系统绝对稳定存在反馈环路设计不当易出现振荡硬件资源阶数越高资源消耗越大相同滤波性能下资源占用显著更少设计难度简单直观窗函数、最优法均可快速实现需兼顾幅度响应与稳定性设计复杂度高线性相位的工程意义绝大多数工程场景优先选择 FIR 滤波器核心原因是其线性相位特性—— 当滤波器系数满足对称条件时通带内所有频率分量的群延时完全一致信号波形不会发生相位失真。时域角度输入信号仅产生固定的整体延时波形形状保持不变频域角度各频率分量的相对相位关系保持恒定不会出现信号畸变。对于调制解调、图像信号处理、高速数据采集等对波形保真度要求高的场景线性相位是硬性要求仅当只关注频率成分、不关心波形失真时如单纯频谱提取可选用 IIR 滤波器节省资源。二、FIR 滤波器核心原理2.1 卷积运算本质FIR 滤波器的输出是输入信号x(n)与单位冲激响应h(n)的线性卷积公式如下 \(y(n) \sum_{k0}^{N-1} h(k) \cdot x(n-k)\) 其中N为滤波器抽头数阶数 1h(k)为滤波器系数。从硬件角度看FIR 的本质是抽头延迟线 乘法器阵列 加法器链输入信号逐级寄存形成延迟链每一级延迟信号与对应系数相乘所有乘积相加得到最终输出。2.2 直接型硬件架构FIR 有直接型、级联型、频率采样型、格型四种结构其中直接型结构最贴合 FPGA 的硬件实现逻辑也是本文采用的架构。对于 N 抽头的线性相位 FIR系数满足偶对称h(k) h(N-1-k)因此可以将对称位置的输入数据先相加、再与系数相乘乘法器数量直接减少一半大幅降低硬件资源消耗。以本文 16 抽头15 阶FIR 为例16 个系数两两对称仅需 8 个乘法器即可完成运算这也是后续 Verilog 代码的核心优化思路。三、MATLAB 滤波器系数设计与量化FPGA 实现 FIR 的第一步是完成系数设计与量化先通过 MATLAB 设计满足指标的浮点系数再量化为定点整数适配 FPGA 的定点运算逻辑。3.1 设计指标采样频率2kHz滤波器类型低通截止频率500Hz滤波器阶数15 阶抽头长度 16系数量化位宽12bit 有符号输入数据位宽12bit 有符号3.2 MATLAB 完整实现代码采用汉明窗函数法设计浮点系数完成 12bit 定点量化并输出可直接用于 Verilog 的十六进制系数同时对比量化前后的幅频响应matlab%% 15阶低通FIR滤波器设计与量化 clear; clc; close all; % 设计参数 Fs 2000; % 采样频率 Hz Fcut 500; % 截止频率 Hz N_order 15; % 滤波器阶数 width_coeff 12; % 系数量化位宽 % 窗函数法设计浮点系数 b fir1(N_order, Fcut/(Fs/2), low, hamming(N_order1)); % 系数量化为12bit有符号整数Q11格式1位符号11位小数 b_quant round(b * 2^(width_coeff-1)); b_quant int16(b_quant); % 打印十进制与十六进制系数 fprintf(十进制系数\n); disp(b_quant); fprintf(十六进制系数3位\n); disp(dec2hex(b_quant, 3)); % 幅频响应对比 figure; freqz(b, 1, 1024, Fs); hold on; freqz(double(b_quant)/2^(width_coeff-1), 1, 1024, Fs); legend(浮点系数,12bit量化系数); title(浮点与量化后滤波器幅频响应对比); grid on;3.3 量化注意事项量化位数直接决定滤波精度与资源消耗设计时需折中权衡量化位宽越低DSP、寄存器资源越少但通带波纹增大、阻带衰减下降必须在 MATLAB 中提前验证量化后的频率响应确保满足设计指标后再移植到 FPGA。本文量化后的 8 个对称系数十六进制为000、ffd、00f、02e、f8b、ef9、24e、7ff与后续 Verilog 代码一一对应。四、Verilog 并行 FIR 架构实现并行结构的核心是所有乘法运算在同一时钟周期内并行完成每个时钟周期输出一个滤波结果吞吐率与系统时钟频率一致适合高速信号处理场景。整体架构分为四级流水线输入移位寄存器 → 对称数据相加 → 系数乘法运算 → 乘积累加输出。4.1 模块接口定义verilogmodule fir_parallel_15taps ( input rst, // 复位信号高电平有效 input clk, // 系统时钟频率2kHz input signed [11:0] Xin, // 输入数据12bit有符号 output signed [28:0] Yout // 输出数据29bit全分辨率 );位宽计算说明12bit 系数 × 13bit 相加数据 25bit 有符号乘积8 个 25bit 数累加需扩展 3bit 位宽最终输出 29bit 全分辨率结果无截位精度损失。4.2 输入移位寄存器链将输入数据逐级寄存形成 16 级延迟线对应卷积公式中的x(n-k)verilogreg signed [11:0] Xin_Reg [15:0]; // 16级移位寄存器每级12bit位宽 reg [3:0] i,j; always (posedge clk or posedge rst) begin if (rst) begin // 复位时所有寄存器清零 for (i 0; i 16; i i 1) Xin_Reg[i] 12d0; end else begin // 数据移位新数据进入第0级其余逐级后移 for (j 0; j 15; j j 1) Xin_Reg[j1] Xin_Reg[j]; Xin_Reg[0] Xin; end end4.3 对称系数数据相加利用系数对称性将对称位置的输入数据先相加将 16 路乘法运算缩减为 8 路verilogreg signed [12:0] Add_Reg [7:0]; // 相加后位宽扩展1bit共13bit有符号 always (posedge clk or posedge rst) begin if (rst) begin for (i 0; i 8; i i 1) Add_Reg[i] 13d0; end else begin // 符号位扩展后相加避免有符号数运算溢出错误 for (i 0; i 8; i i 1) Add_Reg[i] {Xin_Reg[i][11], Xin_Reg[i]} {Xin_Reg[15-i][11], Xin_Reg[15-i]}; end end关键细节两个 12bit 有符号数相加前必须通过拼接运算符{}扩展符号位否则负数运算会出现符号错误导致结果异常。4.4 乘法器阵列例化 8 个带寄存器输出的硬件乘法器 IP 核Vivado 中mult_genIP完成系数与数据的乘法运算verilog// 8个12bit量化系数利用对称性缩减后 wire signed [11:0] coe [7:0]; assign coe[0] 12h000; assign coe[1] 12hffd; assign coe[2] 12h00f; assign coe[3] 12h02e; assign coe[4] 12hf8b; assign coe[5] 12hef9; assign coe[6] 12h24e; assign coe[7] 12h7ff; // 乘法器输出12×13bit有符号乘法结果25bit有符号 wire signed [24:0] Mout [7:0]; // 例化8个乘法器IP核 mult_gen_0 Umult0 (.CLK(clk), .A(coe[0]), .B(Add_Reg[0]), .P(Mout[0])); mult_gen_0 Umult1 (.CLK(clk), .A(coe[1]), .B(Add_Reg[1]), .P(Mout[1])); mult_gen_0 Umult2 (.CLK(clk), .A(coe[2]), .B(Add_Reg[2]), .P(Mout[2])); mult_gen_0 Umult3 (.CLK(clk), .A(coe[3]), .B(Add_Reg[3]), .P(Mout[3])); mult_gen_0 Umult4 (.CLK(clk), .A(coe[4]), .B(Add_Reg[4]), .P(Mout[4])); mult_gen_0 Umult5 (.CLK(clk), .A(coe[5]), .B(Add_Reg[5]), .P(Mout[5])); mult_gen_0 Umult6 (.CLK(clk), .A(coe[6]), .B(Add_Reg[6]), .P(Mout[6])); mult_gen_0 Umult7 (.CLK(clk), .A(coe[7]), .B(Add_Reg[7]), .P(Mout[7]));IP 配置说明mult_gen_0配置为有符号乘法A 端口 12bit、B 端口 13bit开启输出寄存器匹配流水线时序。4.5 乘积累加输出将 8 路乘法结果相加得到最终滤波输出verilogreg signed [28:0] sum; reg signed [28:0] yout; reg [3:0] k; always (posedge clk or posedge rst) begin if (rst) begin sum 29d0; yout 29d0; end else begin yout sum; // 寄存输出改善时序收敛 sum 29d0; // 累加前清零 for (k 0; k 8; k k 1) sum sum Mout[k]; // 8个乘积结果累加 end end assign Yout yout; endmodule五、Testbench 文件级仿真验证为了精准验证滤波效果采用文件读写方式搭建 Testbench从 TXT 文件读取 MATLAB 生成的测试激励将滤波结果写回 TXT 文件便于后续在 MATLAB 中做定量对比与分析。5.1 完整 Testbench 代码verilogtimescale 1ns / 1ps module tb_fir_parallel; // 参数定义 parameter CLK_PERIOD 500000; // 2kHz时钟周期500000ns0.5ms parameter DATA_NUM 1024; // 测试数据总点数 // 信号定义 reg clk; reg rst; reg signed [11:0] din; wire signed [28:0] dout; // 例化待测FIR模块 fir_parallel_15taps u_fir ( .rst(rst), .clk(clk), .Xin(din), .Yout(dout) ); // 生成系统时钟 initial begin clk 0; forever #(CLK_PERIOD/2) clk ~clk; end // 读取TXT激励数据 reg [11:0] stimulus [1:DATA_NUM]; integer i; initial begin $readmemb(sin_input.txt, stimulus); // 读取二进制格式数据文件 i 0; rst 1; #(CLK_PERIOD*2); rst 0; repeat(DATA_NUM) begin i i 1; din stimulus[i]; #CLK_PERIOD; end $finish; end // 将滤波结果写入TXT文件 integer file_out; initial begin file_out $fopen(fir_output.txt); if (!file_out) begin $display(Error: cannot open output file!); $finish; end end wire rst_write clk (~rst); // 复位期间禁止写入数据 always (posedge rst_write) begin $fdisplay(file_out, %d, dout); end endmodule5.2 仿真流程说明先用 MATLAB 生成测试信号如 200Hz800Hz 混合正弦信号、白噪声信号量化为 12bit 后写入sin_input.txtTestbench 通过$readmemb系统任务读取数据逐周期输入到 FIR 模块滤波结果通过$fdisplay系统任务写入fir_output.txt将输出文件导入 MATLAB绘制时域波形与幅频曲线定量验证滤波效果。5.3 文件操作注意事项数据文件需放在仿真工作目录下否则需填写完整绝对路径路径分隔符使用正斜杠/与 Windows 系统默认的反斜杠\不同读取二进制格式用$readmemb读取十六进制格式用$readmemh需与文件内数据格式匹配。六、仿真结果分析6.1 混合正弦信号滤波输入信号为 200Hz800Hz 的混合正弦波经过 500Hz 低通滤波后低于截止频率的 200Hz 分量完整保留幅度衰减符合通带指标高于截止频率的 800Hz 分量被大幅衰减达到阻带抑制要求输出信号波形平滑无明显相位失真验证了线性相位特性。6.2 白噪声信号滤波输入白噪声信号经过低通滤波后高频分量被显著抑制输出信号频谱集中在 0~500Hz 范围内与设计截止频率一致滤波效果符合预期。七、资源与性能分析以 Xilinx Artix-7 系列 FPGA 为例本设计综合后的核心资源占用与性能如下表格资源类型占用数量说明DSP48E18 个对应 8 个硬件乘法器利用对称性缩减了一半触发器 FF约 150 个移位寄存器、流水线寄存器、输出寄存器LUT约 100 个加法逻辑、控制逻辑与布线资源性能特点吞吐率每个时钟周期输出 1 个结果最高吞吐率等于系统时钟频率延迟从输入到输出共 3 级流水线总延迟约 3~4 个时钟周期适用场景中低阶、高速率的滤波需求如高速 AD 采样后实时滤波。八、设计关键注意事项有符号数运算规范Verilog 中进行带符号数加减乘时必须保证位宽匹配、符号位正确扩展避免出现符号错误导致的功能异常。系数量化验证量化前必须在 MATLAB 中验证量化后的频率响应位宽不足会导致阻带衰减不达标、通带波纹增大。时序优化方法高阶并行 FIR 的累加链易成为关键路径可采用加法树结构、插入流水线寄存器提升最高运行频率。输出截位策略全分辨率输出位宽较大实际工程中可根据动态范围需求截位进一步节省后续模块资源。九、完整工程下载本文配套完整可运行 Vivado 工程包包含 Verilog 源码、Testbench、MATLAB 系数生成脚本、仿真脚本、测试数据文件解压后可直接编译运行工程下载地址https://download.csdn.net/download/fpgadesigner/10462288总结与预告本文完整实现了基于系数对称性优化的并行 FIR 滤波器从 MATLAB 系数设计到 Verilog 硬件落地覆盖了 FPGA 数字滤波的全流程。并行结构凭借高吞吐率的优势在高速信号处理场景中应用广泛但资源随阶数线性增长的特性也限制了其在高阶滤波器中的使用。后续系列文章将继续讲解串行结构 FIR 滤波器的 Verilog 设计分布式算术DA结构 FIR 实现Vivado/Quartus FIR IP 核的调用与配置多相滤波、半带滤波器等高级结构