【DSP笔记 · 第5章】数字滤波器的蓝图:从数学公式到硬件实现的艺术

数字滤波器的蓝图:从数学公式到硬件实现的艺术

在前几章,我们已经领略了数字信号处理的魅力。在未来的章节(第六、七章),我们将深入学习如何设计一个滤波器------也就是根据需求,计算出一套神奇的数学系数,来"筛"出我们想要的信号。

但是,在拿到这套完美的系数(也就是滤波器的系统函数 H ( z ) H(z) H(z) 或差分方程)之后,我们面临一个更现实的问题:如何将这个数学公式,转化为可以在计算机软件或硬件芯片上高效运行的实际代码或电路?

这,就是数字滤波器网络结构要解决的问题。它就像建筑师(滤波器设计者)完成了宏伟的建筑设计图(系统函数)后,结构工程师(我们)需要绘制出具体的施工蓝图(网络结构),告诉施工队(CPU或FPGA)该如何用最少的材料(计算资源)、最稳固的方式(数值稳定性),把大楼盖起来。

今天,我们将一起探索这些"施工蓝图"。你会发现,同一个滤波器设计,可以有多种不同的实现结构,而选择哪一种结构,将直接影响到你的程序的运行效率、内存占用,甚至是最终结果的精度。

信号流图:滤波器的可视化语言

要讨论结构,我们首先需要一种通用的、可视化的语言来描述它。这就是信号流图(Signal Flow Graph)。它用非常简单的符号,就能清晰地表达出信号在滤波器内部的流动和处理过程。

一个信号流图主要由三种基本构件组成:

  1. 加法器 (Adder): 在图中用一个节点表示,所有指向它的信号在这里相加。
  2. 乘法器 (Multiplier): 在图中用一个带系数的支路表示,流过这条支路的信号会被乘以该系数。
  3. 单位延迟器 (Unit Delay) : 在图中用一个标有 z − 1 z^{-1} z−1 的支路表示。信号每经过一个延迟器,就会在时间上延迟一个采样周期。这在硬件上对应一个寄存器,在软件上对应数组中的上一个元素。

(上图展示了信号流图的三个基本构件:加法器、乘法器和单位延迟器)

有了这套语言,我们就可以开始绘制各种滤波器的"施工蓝图"了。我们将分别探讨IIR和FIR这两大家族的结构。

IIR滤波器:构建带有"记忆"的系统

IIR(无限脉冲响应)滤波器的特点是其差分方程中包含输出信号 y ( n ) y(n) y(n) 的反馈项。这意味着它的当前输出,不仅与当前和过去的输入有关,还与过去的输出有关。这种"记忆"或"反馈"特性,使得它的结构设计更为复杂,也更有趣。

一个通用的IIR系统函数如下:
H ( z ) = Y ( z ) X ( z ) = ∑ k = 0 M b k z − k 1 + ∑ k = 1 N a k z − k H(z) = \frac{Y(z)}{X(z)} = \frac{\sum_{k=0}^{M} b_k z^{-k}}{1 + \sum_{k=1}^{N} a_k z^{-k}} H(z)=X(z)Y(z)=1+∑k=1Nakz−k∑k=0Mbkz−k

其中, b k b_k bk 是前向路径的系数(零点相关), a k a_k ak 是反馈路径的系数(极点相关)。

直接型:最直观的翻译

直接型结构,顾名思义,就是将上述系统函数或其对应的差分方程"直译"成信号流图。

直接I型 (Direct Form I)

这是最朴素、最不假思索的实现方式。我们可以把 H ( z ) H(z) H(z) 看成两部分级联:一个只有分母(全极点)的系统 H 1 ( z ) H_1(z) H1(z) 和一个只有分子(全零点)的系统 H 2 ( z ) H_2(z) H2(z)。

  1. 先实现 H 2 ( z ) H_2(z) H2(z):输入信号 X ( z ) X(z) X(z) 经过一系列延迟和乘法( b k b_k bk 系数),得到一个中间信号 W ( z ) W(z) W(z)。
  2. 再实现 H 1 ( z ) H_1(z) H1(z):中间信号 W ( z ) W(z) W(z) 作为 H 1 ( z ) H_1(z) H1(z) 的输入,经过反馈环路( a k a_k ak 系数)的处理,得到最终输出 Y ( z ) Y(z) Y(z)。

这种结构非常直观,但它有一个明显的缺点:延迟器是冗余的 。全零点部分和全极点部分各自用了一套延迟器,总共需要 N + M N+M N+M 个。在硬件实现中,每一个延迟器都意味着一个存储单元,这无疑是一种浪费。

直接II型 (Direct Form II)

为了解决直接I型的浪费问题,聪明的工程师想到了一个绝妙的办法。既然两套延迟器链上的信号是一样的(都是中间信号的延迟版本),我们为什么不把它们合并呢?

于是,我们交换一下 H 1 ( z ) H_1(z) H1(z) 和 H 2 ( z ) H_2(z) H2(z) 的顺序,让输入信号 X ( z ) X(z) X(z) 先经过全极点部分,再经过全零点部分。这样做之后,两条延迟器链就奇迹般地可以合并成一条了!

(上图清晰地对比了直接I型和直接II型结构。可以看到,直接II型通过交换零点和极点部分,将两串延迟器合并为一串,大大节省了存储资源。)

直接II型是IIR最经典的结构之一 。它使用的延迟器数量为 max ⁡ ( N , M ) \max(N, M) max(N,M),是所有直接型结构中最少的,因此也被称为典范型(Canonical Form) 。在软件实现(如MATLAB的filter函数)和教科书中,这是一种非常常见的结构。

但是,直接型有一个潜在的"致命"弱点 :当滤波器的阶数很高时(比如N>4),系数 a k , b k a_k, b_k ak,bk 的微小量化误差(由于计算机使用有限字长存储)会被反馈环路不断放大,可能导致滤波器的极点偏离单位圆,从而使系统变得不稳定,或者频率响应严重偏离设计目标。这就像盖一栋超高层摩天大楼,如果地基有微小的沉降不均,到了顶层就会被放大成巨大的倾斜。

级联型:化整为零的智慧

为了解决高阶直接型结构的数值稳定性问题,我们引入了级联型(Cascade Form) 结构。

它的核心思想是 "分而治之" 。我们不直接实现那个高阶的、敏感的系统函数 H ( z ) H(z) H(z),而是先在数学上将它因式分解成一系列低阶(通常是一阶或二阶)系统函数的乘积:
H ( z ) = G ⋅ H 1 ( z ) ⋅ H 2 ( z ) ⋯ H K ( z ) H(z) = G \cdot H_1(z) \cdot H_2(z) \cdots H_K(z) H(z)=G⋅H1(z)⋅H2(z)⋯HK(z)

其中,每个 H k ( z ) H_k(z) Hk(z) 都是一个简单的二阶系统(也称为二阶节,Second-Order Section, SOS ):
H k ( z ) = b 0 k + b 1 k z − 1 + b 2 k z − 2 1 + a 1 k z − 1 + a 2 k z − 2 H_k(z) = \frac{b_{0k} + b_{1k}z^{-1} + b_{2k}z^{-2}}{1 + a_{1k}z^{-1} + a_{2k}z^{-2}} Hk(z)=1+a1kz−1+a2kz−2b0k+b1kz−1+b2kz−2

然后,我们在硬件或软件上,将这些简单的二阶节的直接II型结构一个个串联起来,前一个的输出是后一个的输入。

(上图展示了一个级联型IIR滤波器结构,它由多个简单的二阶节(SOS)串联而成。)

为什么这样做更好?

  1. 提高数值稳定性:每个二阶节都是一个低阶系统,其系数的量化误差对极点位置的影响被限制在节内部,不会像高阶直接型那样被累积放大。这使得整个滤波器的性能对系数的精度不那么敏感。就像用预制好的、坚固的楼层模块来盖高楼,比从地基开始一点点往上浇筑要稳固得多。
  2. 模块化设计:这种结构非常适合模块化实现。你只需要设计和优化一个标准的二阶节模块,然后根据需要复制和串联它们即可。

在专业的DSP库和硬件实现中,级联型是实现高阶IIR滤波器的首选方法,因为它极大地改善了实际应用中的稳定性和精度问题。

并联型:多路并进的策略

除了级联,还有一种"分而治之"的策略,叫做并联型(Parallel Form)

这次,我们不是将 H ( z ) H(z) H(z) 分解为乘积,而是通过部分分式展开 ,将其分解为一系列简单系统函数的
H ( z ) = C + ∑ k = 1 K H k ( z ) H(z) = C + \sum_{k=1}^{K} H_k(z) H(z)=C+k=1∑KHk(z)

其中,每个 H k ( z ) H_k(z) Hk(z) 通常也是一个简单的一阶或二阶系统。

在实现时,输入信号 X ( z ) X(z) X(z) 同时送入所有并联的支路 H k ( z ) H_k(z) Hk(z),每个支路独立进行处理,最后将所有支路的输出相加 ,得到最终的输出 Y ( z ) Y(z) Y(z)。

并联型结构同样具有很好的数值稳定性。它在某些特定的分析和设计(如控制系统中根据极点进行模式分解)中非常有用。不过,在通用的数字信号处理应用中,它的普及程度略低于级联型。

FIR滤波器:稳定可靠的"流水线"

与IIR不同,FIR(有限脉冲响应)滤波器没有反馈环路,它的输出只依赖于当前和过去的输入。这使得它的结构更加简单,并且天生稳定。你可以把它想象成一条"流水线",信号从一端流入,经过一系列工位(延迟、乘法、加法)的处理,从另一端流出。

其系统函数是一个只包含分子的多项式:
H ( z ) = ∑ n = 0 N − 1 h ( n ) z − n H(z) = \sum_{n=0}^{N-1} h(n) z^{-n} H(z)=n=0∑N−1h(n)z−n

其中 h ( n ) h(n) h(n) 就是滤波器的系数。

直接型结构

FIR的直接型结构非常简单,就是对上述公式的直接翻译:输入信号经过一串 N − 1 N-1 N−1 个延迟器,每个延迟器的输出(以及原始输入)分别乘以对应的系数 h ( n ) h(n) h(n),然后全部相加得到最终输出。这种结构也被称为横截型(Transversal) 结构。

线性相位结构:天才的优化

在关于FIR设计的博客中我们会讲到,FIR滤波器最大的魅力在于能实现线性相位 ,而实现线性相位的秘诀是其系数 h ( n ) h(n) h(n) 具有对称性 ,即 h ( n ) = h ( N − 1 − n ) h(n) = h(N-1-n) h(n)=h(N−1−n)。

这个对称性,不仅带来了完美的相位特性,还为我们提供了一个绝佳的优化结构的机会!

思考一下,在一个直接型FIR结构中,如果系数 h ( 0 ) h(0) h(0) 和 h ( N − 1 ) h(N-1) h(N−1) 是相等的,我们为什么需要两个独立的乘法器来执行 x(n)*h(0)x(n-(N-1))*h(N-1) 呢?既然乘数一样,我们可以先把两个输入信号加起来,然后再做一次乘法!
x ( n ) ⋅ h ( 0 ) + x ( n − N + 1 ) ⋅ h ( N − 1 ) = [ x ( n ) + x ( n − N + 1 ) ] ⋅ h ( 0 ) x(n) \cdot h(0) + x(n-N+1) \cdot h(N-1) = [x(n) + x(n-N+1)] \cdot h(0) x(n)⋅h(0)+x(n−N+1)⋅h(N−1)=[x(n)+x(n−N+1)]⋅h(0)

这一步简单的代数变换,在硬件实现上是巨大的胜利!我们用一个加法器,换掉了一个乘法器。在数字电路中,乘法器通常比加法器占用更多的芯片面积、消耗更多的功率、运算速度也更慢。

通过利用系数的对称性,我们可以将延迟链"对折",将对称位置的信号先相加,再共享一个乘法器。如果有一个长度N=7的线性相位FIR滤波器结构,通过把延迟链"对折",对称位置的信号在乘法前相加,使得乘法器的数量从7个减少到了4个。

这种线性相位结构 ,可以将FIR滤波器的乘法器数量减少近一半!这对于需要在资源受限的嵌入式系统或追求高性能的FPGA上实现滤波器的工程师来说,是至关重要的优化。因此,只要是设计线性相位的FIR滤波器,几乎总会采用这种优化结构。

频率采样结构

除了直接型和线性相位结构,FIR还有一种比较特殊的结构,叫做频率采样结构。它的思路与我们在FIR设计中会提到的频率采样法相对应。

它将滤波器分解为一个梳状滤波器 和一个并联谐振器组的级联。

  • 梳状滤波器 ( 1 − z − N 1 - z^{-N} 1−z−N) 在频域上产生了一系列等间隔的零点。
  • 并联的谐振器组则在这些零点的位置上放置极点,以"抵消"掉梳状滤波器的零点,并根据期望的频率采样值来设定增益。

这种结构在理论上很有启发性,因为它直观地将滤波器的实现与频域上的采样点联系了起来。在某些需要动态调整滤波器频响的应用中,它可能提供便利。但在通用滤波任务中,它的量化噪声特性不如直接型,且可能需要复数乘法,因此应用相对较少。

总结:结构的选择是一门艺术

我们今天走过了一趟数字滤波器内部的结构之旅。现在,让我们站在宏观的视角回顾一下:

  • 没有"最好"的结构,只有"最合适"的结构。你的选择取决于你的应用需求:是追求最低的计算成本,还是最高的数值精度?是在PC上用浮点数编程,还是在单片机上用定点数实现?
  • IIR滤波器结构
    • 直接II型:最节省延迟器,是理论分析和简单软件实现的基础。但对高阶系统,数值稳定性是隐患。
    • 级联型高阶IIR实现的首选。通过"分而治之",大大提高了数值稳定性和对系数误差的鲁棒性。
    • 并联型:提供了另一种高稳定性的实现方式,在特定领域有其优势。
  • FIR滤波器结构
    • 直接型:最基础的实现,稳定可靠。
    • 线性相位型线性相位FIR实现的首选。利用系数对称性,节省了近一半的乘法器,是极致优化的典范。

理解了这些"施工蓝图",你才真正掌握了从理论到实践的桥梁。当你拿到一个滤波器设计任务时,你不仅会思考"我需要一个什么样的频率响应?",更会思考"我应该用哪种结构来实现它,才能在满足性能的同时,最大限度地节省资源?"。这就是从一个信号处理的"使用者"到"创造者"的转变。


习题

来吧,用几个小问题检验一下你是否已经掌握了这些"蓝图"的精髓。

第1题 (看图写函数)

一个直接II型IIR滤波器,反馈系数为 a 1 , a 2 a_1, a_2 a1,a2,前向系数为 b 0 , b 1 , b 2 b_0, b_1, b_2 b0,b1,b2),写出它的系统函数 H ( z ) = Y ( z ) / X ( z ) H(z) = Y(z)/X(z) H(z)=Y(z)/X(z)。

第2题 (概念选择题)

你被要求在-一个资源非常有限的8位单片机上,实现一个10阶的IIR低通滤波器。你主要担心的问题是,有限的8位字长会导致系数存在较大的量化误差,可能会使滤波器变得不稳定。在这种情况下,你优先选择哪种实现结构?

A. 直接II型

B. 级联型

C. 频率采样型

第3题 (资源计算题)

一个线性相位FIR滤波器的脉冲响应为 h = [ 1 , 2 , 3 , 2 , 1 ] h = [1, 2, 3, 2, 1] h=[1,2,3,2,1]。如果使用直接型结构来实现,需要多少个乘法器?如果使用线性相位结构来实现,需要多少个乘法器?


答案

第1题答案:

首先,我们定义中心延迟链上的信号为 W ( z ) W(z) W(z)。我们可以得出:
W ( z ) = X ( z ) − a 1 z − 1 W ( z ) − a 2 z − 2 W ( z ) W(z) = X(z) - a_1 z^{-1} W(z) - a_2 z^{-2} W(z) W(z)=X(z)−a1z−1W(z)−a2z−2W(z)

整理得到 W ( z ) W(z) W(z) 和 X ( z ) X(z) X(z) 的关系:
W ( z ) ( 1 + a 1 z − 1 + a 2 z − 2 ) = X ( z ) W(z)(1 + a_1 z^{-1} + a_2 z^{-2}) = X(z) W(z)(1+a1z−1+a2z−2)=X(z)

然后,根据流图的前向部分,写出输出 Y ( z ) Y(z) Y(z):
Y ( z ) = b 0 W ( z ) + b 1 z − 1 W ( z ) + b 2 z − 2 W ( z ) Y(z) = b_0 W(z) + b_1 z^{-1} W(z) + b_2 z^{-2} W(z) Y(z)=b0W(z)+b1z−1W(z)+b2z−2W(z)

整理得到 Y ( z ) Y(z) Y(z) 和 W ( z ) W(z) W(z) 的关系:
Y ( z ) = ( b 0 + b 1 z − 1 + b 2 z − 2 ) W ( z ) Y(z) = (b_0 + b_1 z^{-1} + b_2 z^{-2}) W(z) Y(z)=(b0+b1z−1+b2z−2)W(z)

将两个式子联立,消去中间变量 W ( z ) W(z) W(z),即可得到系统函数 H ( z ) H(z) H(z):
H ( z ) = Y ( z ) X ( z ) = b 0 + b 1 z − 1 + b 2 z − 2 1 + a 1 z − 1 + a 2 z − 2 H(z) = \frac{Y(z)}{X(z)} = \frac{b_0 + b_1 z^{-1} + b_2 z^{-2}}{1 + a_1 z^{-1} + a_2 z^{-2}} H(z)=X(z)Y(z)=1+a1z−1+a2z−2b0+b1z−1+b2z−2

第2题答案:

B. 级联型

原因 : 题目中的核心痛点是高阶(10阶)系统在 资源受限(8位字长)平台上的数值稳定性问题。

  • 直接II型在高阶时对系数误差非常敏感,8位字长带来的量化误差很可能会使极点偏移到单位圆外,导致系统不稳定。
  • 级联型通过将10阶系统分解为5个独立的二阶节,将系数误差的影响限制在各个节内部,极大地增强了滤波器的鲁棒性和数值稳定性,是解决这个问题的标准方案。
  • 频率采样型本身对系数的量化也比较敏感,且不是IIR的标准结构。

第3题答案:

该FIR滤波器的长度 N = 5 N=5 N=5,脉冲响应为 h ( n ) h(n) h(n)。
h ( 0 ) = 1 , h ( 1 ) = 2 , h ( 2 ) = 3 , h ( 3 ) = 2 , h ( 4 ) = 1 h(0)=1, h(1)=2, h(2)=3, h(3)=2, h(4)=1 h(0)=1,h(1)=2,h(2)=3,h(3)=2,h(4)=1。

这是一个偶对称的线性相位FIR滤波器( h ( n ) = h ( 4 − n ) h(n) = h(4-n) h(n)=h(4−n))。

  • 使用直接型结构 :

    需要 N N N 个乘法器,即 5个 乘法器。

  • 使用线性相位结构 :

    我们利用系数的对称性: h ( 0 ) = h ( 4 ) = 1 h(0)=h(4)=1 h(0)=h(4)=1, h ( 1 ) = h ( 3 ) = 2 h(1)=h(3)=2 h(1)=h(3)=2。

    • 信号 x ( n ) x(n) x(n) 和 x ( n − 4 ) x(n-4) x(n−4) 相加后,与系数 h ( 0 ) = 1 h(0)=1 h(0)=1 相乘(1个乘法器)。
    • 信号 x ( n − 1 ) x(n-1) x(n−1) 和 x ( n − 3 ) x(n-3) x(n−3) 相加后,与系数 h ( 1 ) = 2 h(1)=2 h(1)=2 相乘(1个乘法器)。
    • 中心的信号 x ( n − 2 ) x(n-2) x(n−2) 自己与系数 h ( 2 ) = 3 h(2)=3 h(2)=3 相乘(1个乘法器)。
      总共需要的乘法器数量为 1 + 1 + 1 = ⌈ N / 2 ⌉ = ⌈ 5 / 2 ⌉ = 3 1 + 1 + 1 = \lceil N/2 \rceil = \lceil 5/2 \rceil = 3 1+1+1=⌈N/2⌉=⌈5/2⌉=3 个。
      所以,使用线性相位结构需要 3个 乘法器。
相关推荐
汇能感知1 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun1 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao2 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾2 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT2 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
ST.J3 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin3 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
明达智控技术3 小时前
MR30分布式I/O模块在化工行业的应用
物联网·自动化
双翌视觉3 小时前
机器视觉的手机柔性屏贴合应用
智能手机·自动化·视觉检测·机器视觉
小憩-4 小时前
【机器学习】吴恩达机器学习笔记
人工智能·笔记·机器学习