这一篇在干嘛?

最常用的滤波器:从卷积公式讲到转置结构、线性相位、流水线与分布式算法(DA),最后落地到 FIR 设计与 IP 内核。 原书代码为 VHDL,本篇所有代码已改写为 Verilog。

  • 3.1 数字滤波器概述
  • 3.2 FIR理论
  • 例3.1 可编程FIR滤波器
  • 3.3 设计 FIR 滤波器
  • 3.4 常系数FIR设计
  • 例3.2 4抽头直接FIR滤波器
  • 例3.3 改进的4抽头直接FIR滤波器
  • 直接形式的流水线 FIR 滤波器
  • 算法3.4 简化加法器图
  • 例3.5 F6半带滤波器的简化加法器图
  • 定理3.6 RAG等价变换
  • 流水线 RAG FIR 滤波器
  • 例 3.7 有符号 DA FIR 滤波器
  • 采用逻辑单元的分布式算法
  • 例3.8 5输入DA表
  • 采用嵌入式阵列模块的 DA
  • 加速 DA 滤波器
  • 例3.9 DA FIR滤波器的开环形式
  • BEGIN
  • 例 3.10 F6 半带滤波器的 IP 生成
  • 3.5 练习

自测一下

第3章 FIR 数字滤波器(上):结构、设计与常系数实现

3.1 数字滤波器概述

什么是数字滤波器

数字滤波器的任务,是按照我们的意愿去修正或改变信号的特性——可以是在时域里,也可以是在频域里。最常见、最重要的一类数字滤波器是线性时不变滤波器(Linear Time-Invariant, LTI)。“线性”指输入叠加时输出也叠加,“时不变”指今天输入一个信号和明天输入同样的信号,系统行为完全一样。

LTI 滤波器与输入信号的相互作用,通过一个叫线性卷积的过程完成,记作 : 是滤波器的脉冲响应(可以理解为滤波器的”指纹”), 是输入信号, 是输出。卷积的正式定义是:

直观地说:想要算出第 个输出点,就把滤波器系数”反着套”在输入序列最近的一段时间上,逐点相乘再全部加起来。

FIR 与 IIR 的区别

LTI 数字滤波器分为两大类:

  • FIR(Finite Impulse Response,有限脉冲响应):脉冲响应只有有限个采样值,式(3-1)的无限累加退化成每个输出时刻的有限次累加;
  • IIR(Infinite Impulse Response,无限脉冲响应):脉冲响应理论上无限长,需要实现无限累加和(第 4 章讨论)。

“不用会怎样”的反问在这里很自然:正因为 FIR 的累加是有限的,它天然稳定、可以做到严格线性相位,也最容易在 FPGA 上用流水线跑出高速度——这是本章选择它的原因。

为什么用数字滤波器取代模拟滤波器

研究数字滤波器的动机在于:它们正日益成为最主要的 DSP 运算,正在迅速取代用 RLC 元件和运算放大器搭建的传统模拟滤波器。两者思路完全不同:

  • 模拟滤波器用拉普拉斯变换的微分方程描述,在时域或 s(拉普拉斯)域分析,只能用于 IIR 设计;
  • FIR 通常直接用计算机规范和算法设计,天然适合数字实现。

本章假定 FIR 滤波器已经设计完成,重点放在:先简要回顾 FIR 的设计过程,再讨论如何用 FPGA 高效地实现它。

3.2 FIR 理论

从卷积到传递函数

带常系数的 FIR 滤波器是一种 LTI 系统。对输入序列 ,长度为 (即 阶)的 FIR 输出由有限卷积和给出:

其中 到 是滤波器的 个系数,它们恰好就是 FIR 的脉冲响应。在 z 域中描述更便捷,传递函数 定义为:

抽头延迟线结构

图 3-1 直接形式的 FIR 滤波器

图 3-1 画出了长度为 的 FIR:它由”抽头延迟线”、加法器和乘法器混合构成。输入信号沿一串寄存器逐拍向后传递,每个寄存器节点引出一个”抽头”,抽头信号乘以对应的滤波器系数(也叫”抽头权重”),所有乘积累加就是输出。过去人们也称 FIR 为”横向滤波器”,说的就是这种抽头延迟线结构。

看懂这张图,FIR 的硬件成本就一目了然: 个乘法器、 个加法器、 级延迟寄存器。后面所有优化都在压缩这三样东西。

全零点滤波器

式(3-4)中多项式 的根定义了滤波器的零点,根的个数就是阶数 。FIR 只有零点、没有极点,所以有时被称作”全零点滤波器”。

有一个容易混淆的点:第 5 章会讲一类重要的 CIC 滤波器,它是递归的,但仍然是 FIR。这之所以可能,是因为递归部分产生的极点恰好被非递归部分抵消掉了,等效的零极点图只剩零点。也就是说:非递归滤波器一定是 FIR,但递归滤波器既可能是 FIR 也可能是 IIR。

图 3-2 结构和脉冲长度之间的关系

3.2.1 具有转置结构的 FIR 滤波器

直接 FIR 模型(图 3-1)有一个重要变形:转置 FIR 滤波器。构造方法只有三步:

  1. 交换输入和输出;
  2. 颠倒信号流的方向;
  3. 加法器与分支节点互换角色。

图 3-3 转置结构的 FIR 滤波器

数学上转置结构与原结构完全等价(同样的传递函数),但硬件上转置结构通常是 FIR 的首选实现方式,原因有二:

  • 输入 广播到所有乘法器,不需要为输入准备额外的移位寄存器链;
  • 各乘积沿寄存器逐级累加,寄存器天然分布在加法器之间,无须为高吞吐量再给加法器树添加额外的流水线级。

例3.1 可编程 FIR 滤波器

先回顾用 PDSP 计算积之和(SOP)的位宽要求(参阅 2.8 节):数据/系数位宽为 、滤波长度为 时,无符号 SOP 需要额外 位,有符号运算需要 个保护位。对 9 位有符号数据/系数、 的情况,加法器宽度必须是

为什么是 19 位? 两个 9 位有符号数相乘得 18 位;4 个这样的乘积相加,最坏情况下结果最多增大 倍,需要 2 个额外位,但其中 1 位被”两个符号位相乘只贡献一个有效符号位”抵消,所以净增 位,合计 19 位。少算一位会溢出,多算一位浪费资源。

原书 VHDL 改写为 Verilog,下面是长度为 4 的可编程滤波器(转置结构,系数可在线加载):

// 原书 VHDL 改写为 Verilog:可编程 FIR 滤波器发生器(转置结构)
module fir_gen #(
    parameter W1 = 9,    // 输入数据/系数位宽
    parameter W2 = 18,   // 乘积位宽 = 2*W1
    parameter W3 = 19,   // 加法器位宽 = W2 + log2(L) - 1
    parameter W4 = 11,   // 输出位宽
    parameter L  = 4     // 滤波器长度
)(
    input  wire               clk,
    input  wire               reset,    // 异步复位
    input  wire               load_x,   // 0:加载系数 1:加载数据
    input  wire signed [W1-1:0] x_in,   // 系统输入
    input  wire signed [W1-1:0] c_in,   // 系数输入
    output wire signed [W4-1:0] y_out   // 系统输出
);
    reg signed [W1-1:0] x;
    reg signed [W1-1:0] c [0:L-1];      // 系数(抽头)阵列
    reg signed [W3-1:0] a [0:L-1];      // 部分和阵列
    wire signed [W2-1:0] p [0:L-1];     // 乘积阵列
    integer i;
 
    // 用 generate 例化 L 个乘法器(便于以后插入流水线级)
    genvar g;
    generate
        for (g = 0; g < L; g = g + 1) begin : mul_gen
            assign p[g] = c[g] * x;
        end
    endgenerate
 
    // 加载过程:load_x=0 时系数沿抽头延迟线逐拍移位
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            x <= 0;
            for (i = 0; i < L; i = i + 1) c[i] <= 0;
        end else if (!load_x) begin
            c[L-1] <= c_in;             // 新系数从最高抽头进入
            for (i = L-2; i >= 0; i = i - 1)
                c[i] <= c[i+1];         // 系数向前移一格
        end else begin
            x <= x_in;                  // 每次装入一个数据样本
        end
    end
 
    // SOP 过程:计算积之和(转置结构加法链)
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            for (i = 0; i < L; i = i + 1) a[i] <= 0;
        end else begin
            for (i = 0; i < L-1; i = i + 1)
                a[i] <= {{(W3-W2){p[i][W2-1]}}, p[i]} + a[i+1]; // 符号扩展后累加
            a[L-1] <= {{(W3-W2){p[L-1][W2-1]}}, p[L-1]};       // 第一个抽头只有寄存器
        end
    end
 
    assign y_out = a[0][W3-1 -: W4];    // 系数为小数(|f[k]|<=1.0),相当于除以 256
endmodule

这段代码的工作方式:当 load_x=0 时,系数被逐个装入抽头延迟线 c;否则数据字装入寄存器 x。第二段 always 块实现积之和:每个乘积 p[i] 先做一位符号扩展到 19 位,再与后级部分和 a[i+1] 相加,形成转置结构的加法链。所有乘法器通过 generate 循环统一例化,这为后续插入流水线级留好了口子。最后把 19 位 SOP 的高 11 位送给输出,等效于除以 256——因为假定的系数都是 的小数。该设计使用了 93 个 LE 和 4 个嵌入式乘法器,TimeQuest 缓慢 85C 模型下 。

要仿真这个长度为 4 的滤波器,选一组有代表性的系数——Daubechies DB4 小波滤波器系数:

FPGA 里没有小数,需要量化:把 4 个系数同时乘以 后四舍五入取整,得到 8 位精度(外加 1 位符号)的整数模型:

仿真的时序是:复位释放后的前 4 个时钟节拍,把系数 依次移入抽头延迟线 c;接着向寄存器 x 装入 100,检查滤波器的脉冲响应。一个时钟周期后嵌入式乘法器的结果 p(i) 就绪,第一个有效输出 y_out 出现在 375 ns 之后。输出各拍按 的比例出现——这正是”脉冲输入的响应就是滤波器系数”这一事实的硬件验证。

图 3-4 加载了 Daubechies 滤波器系数的 4 抽头可编程 FIR 滤波器的仿真

3.2.2 FIR 滤波器的对称性

FIR 脉冲响应的中心是一个重要的对称点。为方便起见,把这一点定义成第 0 次采样时刻,这样得到的滤波器描述就是因果的。对奇数长度的 FIR,因果模型为:

令 ,沿单位圆求传递函数就得到频率响应:

用 表示幅频响应,用 表示相位响应:

实际工作中,人们更多用相位和幅值来描述数字滤波器,而较少直接使用 z 域传递函数或复频率响应。

3.2.3 线性相位 FIR 滤波器

为什么需要线性相位

在通信和图像处理等应用中,信号经过滤波器后波形形状不能被扭曲,这一点至关重要。例如图像的边缘、通信码元的形状,一旦不同频率分量被延迟了不同时间,波形就会失真。衡量相位线性度的标准尺度是组延迟:

理想的线性相位滤波器,在关心频段内组延迟是一个常数——所有频率分量”手拉手”一起延迟,波形只平移、不变形。

对称性带来线性相位

从式(3-7)可以看出:只有当频率响应 是纯实或纯虚函数时,才可能实现固定组延迟。这就要求脉冲响应必须满足偶对称或奇对称: