FPGA 数字信号处理:并行 FIR 与串行滤波器设计原理、对比与完整 Verilog 实现

FIR 滤波器是 FPGA 数字信号处理中最核心、应用最广泛的模块之一,在音频去噪、通信中频滤波、传感器信号预处理等场景中无处不在。在 FPGA 工程实现中,并行结构串行结构是两种最基础的架构,二者本质是「运算速度」与「硬件资源」的经典权衡。

本文基于 15 阶(16 抽头)线性相位低通 FIR 滤波器为实例,从原理架构、代码实现、性能对比三个维度完整拆解两种设计,并提供可直接综合、跨平台通用的纯 Verilog 代码。


一、设计前提与基础公式

1.1 线性相位与系数对称性

绝大多数工程场景下的 FIR 滤波器都设计为线性相位,其单位脉冲响应满足对称特性: \(h(k) = h(N-1-k)\) 其中N为抽头总数(阶数 + 1)。利用该特性可将卷积公式优化为「先加后乘」,直接减少一半乘法运算量,是两种结构共同的优化基础。

1.2 核心卷积公式

标准 FIR 输出为输入序列与系数的线性卷积: \(y(n) = \sum_{k=0}^{N-1} h(k) \cdot x(n-k)\) 对称优化后(本文实例 N=16,合并为 8 组): \(y(n) = \sum_{k=0}^{7} h(k) \cdot \left x(n-k) + x(n-(15-k)) \\right\)

1.3 实例统一参数

本文所有代码采用完全一致的设计参数,便于横向对比:

  • 滤波器阶数:15 阶(16 个抽头)
  • 输入数据位宽:12bit 有符号补码
  • 系数量化位宽:12bit 有符号补码
  • 输出位宽:29bit 全精度无截位,无溢出风险

二、并行 FIR 滤波器设计

2.1 原理与架构特点

并行 FIR 的核心思想是硬件全展开:所有抽头的乘加运算在单个时钟周期内同时完成。

  • 硬件结构:8 个对称加法器 + 8 个乘法器 + 一级加法树累加器
  • 时钟要求:系统时钟频率 = 输入采样率
  • 吞吐能力:每个时钟周期输出 1 个有效结果,吞吐率与系统时钟同频
  • 优势:时序逻辑简单,运算速度快,采样率上限高
  • 劣势:硬件资源随滤波器阶数线性增长,高阶设计会占用大量 DSP 乘法器

2.2 完整 Verilog 实现

verilog

复制代码
// 16抽头并行线性相位FIR滤波器
// 纯Verilog实现,无平台IP依赖,可直接综合
module parallel_fir_16tap
(
    input         rst,                // 高电平有效复位
    input         clk,                // 系统时钟 = 采样率
    input signed [11:0] Xin,          // 12bit有符号输入数据
    output reg signed [28:0] Yout     // 29bit全精度滤波输出
);

// 12bit量化滤波器系数(利用对称性仅存储8个)
localparam signed [11:0] COEFF[0:7] = '{
    12'h000, 12'hffd, 12'h00f, 12'h02e,
    12'hf8b, 12'hef9, 12'h24e, 12'h7ff
};

//--------------------------
// 1. 16级输入移位寄存器(抽头延迟线)
//--------------------------
reg signed [11:0] Xin_Reg[0:15];
integer i;
always @(posedge clk or posedge rst) begin
    if(rst) begin
        for(i=0; i<16; i=i+1)
            Xin_Reg[i] <= 12'd0;
    end
    else begin
        for(i=0; i<15; i=i+1)
            Xin_Reg[i+1] <= Xin_Reg[i];
        Xin_Reg[0] <= Xin;
    end
end

//--------------------------
// 2. 对称数据对相加(符号位扩展防止溢出)
//--------------------------
wire signed [12:0] add_res[0:7];
genvar k;
generate
    for(k=0; k<8; k=k+1) begin : SYM_ADD
        assign add_res[k] = {Xin_Reg[k][11], Xin_Reg[k]} 
                          + {Xin_Reg[15-k][11], Xin_Reg[15-k]};
    end
endgenerate

//--------------------------
// 3. 8组乘法并行运算
//--------------------------
wire signed [24:0] mult_res[0:7];
generate
    for(k=0; k<8; k=k+1) begin : MULT_OP
        assign mult_res[k] = COEFF[k] * add_res[k];
    end
endgenerate

//--------------------------
// 4. 加法树累加并输出打拍
//--------------------------
integer j;
always @(posedge clk or posedge rst) begin
    if(rst) begin
        Yout <= 29'd0;
    end
    else begin
        Yout = 29'd0;
        for(j=0; j<8; j=j+1)
            Yout = Yout + mult_res[j];
    end
end

endmodule

三、串行 FIR 滤波器设计

3.1 原理与架构特点

串行 FIR 是典型的面积换速度设计:通过时分复用单个乘法器和加法器,分多个时钟周期依次完成所有抽头的乘加运算。

  • 硬件结构:1 个对称加法器 + 1 个乘法器 + 1 个累加器 + 计数器控制逻辑
  • 时钟要求:系统时钟频率 ≥ 采样率 × (N/2) (本实例为 8 倍采样率)
  • 吞吐能力:每 8 个时钟周期输出 1 个有效结果,吞吐率为系统时钟的 1/8
  • 优势:硬件资源极少,滤波器阶数升高时仅控制逻辑小幅增长,高阶场景资源优势极其明显
  • 劣势:吞吐率低,需要更高频率的系统时钟,时序对齐设计更复杂

3.2 完整 Verilog 实现

verilog

复制代码
// 16抽头全串行线性相位FIR滤波器
// 纯Verilog实现,无平台IP依赖,可直接综合
module serial_fir_16tap
(
    input         rst,                // 高电平有效复位
    input         clk,                // 系统时钟 = 采样率 × 8
    input signed [11:0] Xin,          // 12bit有符号输入数据
    output reg signed [28:0] Yout     // 29bit全精度滤波输出
);

// 12bit量化滤波器系数(利用对称性仅存储8个)
localparam signed [11:0] COEFF[0:7] = '{
    12'h000, 12'hffd, 12'h00f, 12'h02e,
    12'hf8b, 12'hef9, 12'h24e, 12'h7ff
};

//--------------------------
// 1. 模8计数器:全局时序调度核心
//--------------------------
reg [2:0] cnt;
always @(posedge clk or posedge rst) begin
    if(rst) cnt <= 3'd0;
    else    cnt <= cnt + 1'd1;
end

//--------------------------
// 2. 16级输入移位寄存器
// 每8个时钟更新一次输入样本,匹配采样率
//--------------------------
reg signed [11:0] Xin_Reg[0:15];
integer i, j;
always @(posedge clk or posedge rst) begin
    if(rst) begin
        for(i=0; i<16; i=i+1)
            Xin_Reg[i] <= 12'd0;
    end
    else if(cnt == 3'd7) begin
        for(j=0; j<15; j=j+1)
            Xin_Reg[j+1] <= Xin_Reg[j];
        Xin_Reg[0] <= Xin;
    end
end

//--------------------------
// 3. 时分复用:逐周期选择对称数据与系数
//--------------------------
reg signed [12:0] add_a, add_b;
reg signed [11:0] coe_reg;
always @(posedge clk or posedge rst) begin
    if(rst) begin
        add_a <= 13'd0;
        add_b <= 13'd0;
        coe_reg <= 12'd0;
    end
    else begin
        // 符号位扩展后送入加法器
        add_a <= {Xin_Reg[cnt][11], Xin_Reg[cnt]};
        add_b <= {Xin_Reg[15-cnt][11], Xin_Reg[15-cnt]};
        coe_reg <= COEFF[cnt];
    end
end

//--------------------------
// 4. 单加法器 + 单乘法器运算
//--------------------------
wire signed [12:0] add_s  = add_a + add_b;
wire signed [24:0] mult_out = coe_reg * add_s;

//--------------------------
// 5. 逐周期累加,完成8组后输出结果
//--------------------------
reg signed [28:0] sum;
always @(posedge clk or posedge rst) begin
    if(rst) begin
        sum  <= 29'd0;
        Yout <= 29'd0;
    end
    else begin
        if(cnt == 3'd2) begin
            Yout <= sum;       // 输出上一轮完整累加结果
            sum  <= mult_out;  // 清零累加器,开启新一轮累加
        end
        else begin
            sum <= sum + mult_out; // 持续累加当前周期乘积
        end
    end
end

endmodule

设计说明:输出时机选在cnt==2是为了匹配乘法器的 1 拍运算延迟,确保累加的 8 个乘积完整有效;加法满足交换律,累加顺序不影响最终计算结果。


四、并行 FIR vs 串行 FIR 核心指标对比

以本文 16 抽头实例为基准,核心对比如下:

表格

对比维度 并行 FIR(16 抽头) 串行 FIR(16 抽头)
乘法器数量 8 个 1 个
核心加法器数量 8 个对称加法 + 加法树 1 个对称加法 + 1 个累加器
系统时钟要求 等于采样率(如 2kHz) 采样率的 8 倍(如 16kHz)
单样本输出周期 1 个时钟 8 个时钟
吞吐率 高,与系统时钟同频 低,为系统时钟的 1/8
资源消耗 高,随阶数线性增长 低,阶数升高资源增长极慢
时序复杂度 低,逻辑简单 高,需匹配运算延迟与控制时序
可扩展性 差,高阶资源暴涨 好,仅需修改计数器位宽与系数
典型适用场景 高速采样、低阶滤波、通信基带 低速采样、高阶滤波、资源受限设计

五、极简仿真验证模板

可通过以下 Testbench 快速验证两种滤波器功能,只需准备好采样数据的 txt 文件即可:

verilog

复制代码
`timescale 1ns/1ns
module tb_fir_compare;

reg clk;
reg rst;
reg signed [11:0] Xin;
wire signed [28:0] Yout_parallel;
wire signed [28:0] Yout_serial;

// 实例化两个滤波器
parallel_fir_16tap u_parallel (
    .rst(rst), .clk(clk), .Xin(Xin), .Yout(Yout_parallel)
);

serial_fir_16tap u_serial (
    .rst(rst), .clk(clk), .Xin(Xin), .Yout(Yout_serial)
);

// 16kHz系统时钟(串行8倍速,并行同样此时钟下每8拍输入1个样本)
initial clk = 0;
always #31250 clk = ~clk;

// 复位与激励
initial begin
    rst = 1;
    Xin = 0;
    #100 rst = 0;
    // 此处可添加$readmemh读取txt激励
    #1000000 $finish;
end

endmodule

六、工程选型总结

  1. 优先选并行的场景:采样率接近 FPGA 最高工作频率、滤波器阶数低于 32 阶、对吞吐率有严格要求,优先使用并行结构;也可直接调用 Vivado/Quartus 的 FIR IP 核,配置为全并行模式。
  2. 优先选串行的场景:采样率较低(如 kHz 级)、滤波器阶数很高(上百阶)、FPGA DSP 资源紧张,串行结构能以极低资源完成滤波功能。
  3. 折中方案:工程中也常使用半串行、多通道时分复用、分布式算术(DA)等中间结构,在资源和速度之间取得平衡。

两种结构的数学本质完全一致,最终滤波结果等价,只是硬件实现的时序与资源分配不同,可根据项目指标灵活选型。

相关推荐
Saniffer_SH1 天前
【高清视频】Gen6 服务器还没到,Gen6 SSD 怎么测?Emily 现场演示三种测试环境
人工智能·驱动开发·测试工具·缓存·fpga开发·计算机外设·压力测试
zlinear数据采集卡1 天前
双核架构深度解析:ARM+FPGA如何让数据采集卡实现500Ksps高性能?
arm开发·fpga开发·架构
9527华安1 天前
FPGA实现GTH Transceivers Wizard传输2路视频,基于aurora 8b10b编解码架构,提供4套工程源码和技术支持
fpga开发·gth·aurora 8b10b·transceivers
FPGA小徐2 天前
FPGA 数字信号处理(二):并行 FIR 滤波器的 Verilog 全流程设计与实现
fpga开发
国科安芯2 天前
基于AS32S601ZIT2型抗辐照MCU的商业航天卫星姿态确定与控制系统研究
单片机·嵌入式硬件·安全·fpga开发·架构·risc-v
ALINX技术博客2 天前
【黑金云课堂】FPGA技术教程FPGA基础:I2C 总线通信技术
fpga开发·i2c
Hello-FPGA2 天前
Xilinx KU040 FPGA Camera Link 图像采集
c++·fpga开发
明德扬2 天前
AD采集卡应用示例交流:从传感器采集到高速信号验证
fpga开发
傻童:CPU2 天前
PS与PL之间的交互
fpga开发