FPGA 中 FIR 滤波器的设计(一)

FIR 是数字信号处理中一种非常的常见运算。我在学校还在上 VHDL 课时,就被要求写这玩意儿。当然当时我 messed up everything, and no one loves me 就是另外一回事儿了。

一个 N 阶的 FIR 滤波器的时域表达式为:

y[n] = \sum_{i = 0}^{N}{h_i \cdot x[n-D-i]}

其中 x[n] 是输入信号,y[n] 是输出信号,h_i 是 FIR 滤波器的系数。D 是一个常数,代表处理的延迟。从公式上来看,FIR 本质上就是一维卷积运算,暴力相乘然后相加。每计算一个 y[n] 需要 N 次乘法和 N-1 次加法。

FIR 的结构取决于很多因素,包括滤波器阶数,时钟速率,吞吐率等等。比较典型的例子是在吞吐率要求非常低时,可以采用 MACC(乘累加)结构;而吞吐率较高时采用多相结构。一般来说 FPGA 中的 FIR 是一个面积敏感的结构,它会消耗比较多 MAC(硬核乘法器)的数量。一个简单的乘法器数量 k_{MAC} 的估算公式是:

k_{dsp} = ceil(\frac{(N+1)f_t}{f_{clk}})

其中 f_t 是 FIR 模块的吞吐率,f_{clk} 是时钟频率,其比值代表了硬件的过采样倍数。例如一个采样率为 100 MHz 的数据采集系统,需要对采集到的信号进行滤波,FIR 的阶数是 7。为了保证能够连续不断的处理,模块的吞吐率至少和采样率相等。如果 FPGA 比较低端,那么时钟可能也会选择 100 MHz。最终可以得出 k_{dsp}=8。在不知道滤波器系数特性时,在资源就已经无法优化了。在结构上,FIR 有很多合适的结构,其中一种如下图所示:

脉动式 FIR

这种结构被称为脉动式(Systolic)结构,它在每个乘或加操作之后都有寄存用于改善时序。在 FIR 的设计中有一个计算的方法:每个寄存器都是 z^-1;当 x[n] 经过 z^-1 之后就会变成 x[n-1]。因此可以轻松写出输出:

y[n] = h_0 \cdot x[n-11] + h_1 \cdot x[n-12] + \cdots + h_7 \cdot x[n-18]

并且 D = 11。至此我们完成了一个通用 FIR 滤波器。接下来我们可以讨论下一些特殊结构的 FIR(TBD):


© 2021 Kele, CC BY-NC-SA 4.0