FPGA 串行与并行 FIR 滤波器全解析

FIR 滤波器是 FPGA 数字信号处理的基础模块,其核心是乘累加(MAC)卷积运算。根据 MAC 单元的调度方式,主要分为串行 FIR (时间换空间,单乘法器分时复用)和并行 FIR(空间换时间,多乘法器全并行)两大类,二者在资源消耗、吞吐速率、时序约束等方面差异显著,需根据采样率、阶数和资源预算选型。


一、FIR 运算本质

有限长单位冲激响应滤波器的输出为输入序列与单位冲激响应的线性卷积: \(yn = \sum_{k=0}^{N-1} hk \cdot xn-k\) 其中:

  • N 为滤波器阶数(抽头数)
  • \(hk\) 为第 k 个抽头的系数
  • \(xn-k\) 为延迟 k 拍的输入数据

所有 FPGA 实现架构的差异,本质上都是对乘累加运算的不同并行度调度。


二、串行 FIR 滤波器(Serial FIR)

1. 架构原理

串行 FIR 是单 MAC 单元分时复用的极致资源节约型架构:整个滤波器仅使用 1 个乘法器 + 1 个累加器,通过计数器 / 状态机调度,在 N 个时钟周期内依次完成 N 个抽头的乘加运算,最终输出一次滤波结果。

完整信号流向

  1. 输入数据进入移位寄存器链,存储 N 个历史输入值
  2. 计数器循环计数 0~N-1,通过多路选择器选通对应延迟数据与系数
  3. 选通数据与系数送入乘法器,结果送入累加器持续求和
  4. 计满 N 个周期后输出最终结果,累加器清零进入下一轮

线性相位优化:若系数满足对称特性 \(hk=hN-1-k\),可先将对称位置的输入数据相加再相乘,乘法次数直接减少一半,仅需 N/2 个周期即可完成一次输出,是工程必用优化手段。

2. 核心特性

  • 时钟约束:系统时钟频率必须 ≥ 输入采样率 × N(对称优化后为 N/2)
  • 吞吐率:每 N 个时钟周期输出 1 个有效采样,最高采样率 \(F_s = F_{clk}/N\)
  • 延迟:输出延迟为 N 个时钟周期,属于高延迟架构
  • 资源占用:仅消耗 1 个 DSP 乘法单元、N 个数据寄存器、少量控制逻辑,资源消耗极低
  • 适用场景:高阶滤波器、低速采样、FPGA 资源紧张的场景,如低速传感器信号滤波

3. 可综合 Verilog 实现(8 阶对称串行 FIR)

verilog

复制代码
module fir_serial_sym #(
    parameter N   = 8,      // 滤波器总阶数
    parameter DW  = 16,     // 输入数据位宽
    parameter CW  = 16      // 系数位宽
)(
    input                clk,
    input                rst_n,
    input                din_valid,  // 输入采样有效标志
    input  signed [DW-1:0] din,      // 输入数据
    output reg           dout_valid, // 输出结果有效标志
    output reg signed [DW+CW+$clog2(N)-1:0] dout  // 全精度输出
);

localparam HALF_N = N / 2;

// 对称系数(仅需存储前半组)
reg signed [CW-1:0] coeff [0:HALF_N-1];
initial begin
    coeff[0] = 16'h0FFF;
    coeff[1] = 16'h1FFF;
    coeff[2] = 16'h2FFF;
    coeff[3] = 16'h3FFF;
end

// 输入移位寄存器链:存储历史数据
reg signed [DW-1:0] shift_reg [0:N-1];
integer i;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        for(i=0; i<N; i=i+1) shift_reg[i] <= 0;
    else if(din_valid) begin
        shift_reg[0] <= din;
        for(i=1; i<N; i=i+1) shift_reg[i] <= shift_reg[i-1];
    end
end

// 运算计数器:调度分时乘加
reg [$clog2(HALF_N)-1:0] cnt;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        cnt <= 0;
    else if(din_valid || cnt != 0)
        cnt <= cnt + 1'b1;
end

// 对称数据相加 + 单乘法器分时复用
wire signed [DW:0] data_add;
wire signed [DW+CW-1:0] mult_out;
assign data_add = shift_reg[cnt] + shift_reg[N-1-cnt];
assign mult_out = data_add * coeff[cnt];

// 累加器
reg signed [DW+CW+$clog2(N)-1:0] acc_reg;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        acc_reg <= 0;
    else if(cnt == 0)
        acc_reg <= mult_out;
    else
        acc_reg <= acc_reg + mult_out;
end

// 输出控制
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dout_valid <= 1'b0;
        dout       <= 0;
    end else if(cnt == HALF_N-1) begin
        dout_valid <= 1'b1;
        dout       <= acc_reg + mult_out;
    end else begin
        dout_valid <= 1'b0;
    end
end

endmodule

三、并行 FIR 滤波器(Parallel FIR)

1. 架构原理

并行 FIR 为每个抽头配备独立乘法器,所有乘法运算在同一时钟周期内并行完成,再通过加法网络求和,1 个时钟周期即可输出一次滤波结果。

工程中优先采用转置型并行结构,替代传统直接型加法树:将累加路径拆分为逐级级联的加法链,加法路径均匀分布,时序收敛更容易,更适配 FPGA 内嵌 DSP 块的级联特性。

转置型并行信号流向

  1. 移位寄存器链同时输出 N 路延迟数据
  2. 对称数据先相加,再送入对应乘法器
  3. 乘法结果沿加法链逐级累加,最后一级输出最终结果

2. 核心特性

  • 时钟约束:系统时钟频率可等于输入采样率,单周期输出
  • 吞吐率:每 1 个时钟周期输出 1 个有效采样,最高采样率 \(F_s \approx F_{clk}\)
  • 延迟:纯组合逻辑延迟 < 1 周期,插入流水线后延迟为数周期,但吞吐率不变
  • 资源占用:消耗 N 个 DSP 单元(对称优化后 N/2 个),资源随阶数线性增长
  • 适用场景:高速 AD 采样、数字通信、雷达信号等低延迟、高吞吐场景

3. 可综合 Verilog 实现(8 阶转置型并行 FIR,对称优化)

verilog

复制代码
module fir_parallel_trans #(
    parameter N   = 8,
    parameter DW  = 16,
    parameter CW  = 16
)(
    input                clk,
    input                rst_n,
    input                din_valid,
    input  signed [DW-1:0] din,
    output reg           dout_valid,
    output reg signed [DW+CW+$clog2(N)-1:0] dout
);

localparam HALF_N = N / 2;

// 对称系数
reg signed [CW-1:0] coeff [0:HALF_N-1];
initial begin
    coeff[0] = 16'h0FFF;
    coeff[1] = 16'h1FFF;
    coeff[2] = 16'h2FFF;
    coeff[3] = 16'h3FFF;
end

// 输入延迟链:生成对称数据对
reg signed [DW-1:0] shift_reg [0:N-1];
integer i;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        for(i=0; i<N; i=i+1) shift_reg[i] <= 0;
    else if(din_valid) begin
        shift_reg[0] <= din;
        for(i=1; i<N; i=i+1) shift_reg[i] <= shift_reg[i-1];
    end
end

// 对称数据相加 + 并行乘法阵列
wire signed [DW:0] add_half [0:HALF_N-1];
wire signed [DW+CW-1:0] mult_out [0:HALF_N-1];
genvar g;
generate
    for(g=0; g<HALF_N; g=g+1) begin : gen_mult
        assign add_half[g] = shift_reg[g] + shift_reg[N-1-g];
        assign mult_out[g] = add_half[g] * coeff[g];
    end
endgenerate

// 转置型累加链(时序优于二叉加法树)
wire signed [DW+CW+$clog2(N)-1:0] sum_chain [0:HALF_N-1];
generate
    assign sum_chain[0] = mult_out[0];
    for(g=1; g<HALF_N; g=g+1) begin : gen_add_chain
        assign sum_chain[g] = sum_chain[g-1] + mult_out[g];
    end
endgenerate

// 输出寄存器打拍
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dout_valid <= 1'b0;
        dout       <= 0;
    end else begin
        dout_valid <= din_valid;
        dout       <= sum_chain[HALF_N-1];
    end
end

endmodule

四、核心指标对比表

表格

对比维度 串行 FIR(对称优化) 全并行 FIR(对称优化)
核心思想 时间换空间,单 MAC 分时复用 空间换时间,多 MAC 全并行
DSP 乘法器数量 1 个 N/2 个
单输出所需时钟周期 N/2 个 1 个
时钟与采样率关系 \(F_{clk} \ge F_s \times N/2\) \(F_{clk} \ge F_s\)
最高采样率 \(2F_{clk}/N\) \(\approx F_{clk}\)
输出延迟 高(N/2 个周期) 低(1~ 数级流水线周期)
逻辑资源占用 极低(移位寄存器 + 控制逻辑) 较高(寄存器 + 加法链)
阶数扩展性 阶数提升不增加乘法器 阶数提升线性消耗 DSP 资源
时序收敛难度 低(单乘法器路径短) 高(多路并行布线复杂)
适用场景 低速、高阶、资源受限 高速、低阶、低延迟

五、工程实践优化技巧

1. 半并行折衷架构

实际工程中极少采用纯串行或纯并行,主流方案是半并行(半串行)架构:配置 M 个乘法器,每 N/M 个周期输出一次结果,可根据采样率和资源预算灵活调整并行度 M,实现资源与性能的最优平衡。

2. FPGA 专属优化

  1. DSP 块原语调用:直接例化 DSP48E1/DSP48E2 原语,避免综合器用逻辑搭建乘法器,大幅提升时序与资源利用率
  2. 流水线插入:并行结构在乘法输出、累加级插入流水线寄存器,最高工作频率可提升 2~3 倍
  3. 移位寄存器优化:使用 SRL16/SRL32 原语实现延迟链,替代触发器节省大量寄存器资源
  4. 位宽规划:全精度位宽 = 输入位宽 + 系数字宽 + \(\lceil log_2(N) \rceil\),输出时按需截位并增加饱和溢出保护
  5. 系数量化:根据通带纹波、阻带衰减要求合理量化系数,减少位宽降低资源消耗