• 正文
  • 相关推荐
申请入驻 产业图谱

多相抽取FIR滤波器之matlab仿真验证

06/03 13:39
Image572
加入交流群
Image 扫码加入
获取工程师必备礼包
参与热点资讯讨论

设计原理:用一根串行延迟线配合并行抽头,将高采样率下的抽取与滤波合并为单时钟域内的高效运算。


一、为什么传统直接实现行不通?

在数字下变频(DDC)或高速数据采集系统中,抽取滤波器需要在高输入采样率下完成低通滤波和降采样。

假设输入速率为Fs ,抽取因子为M,滤波器阶数为 L,则传统直接实现面临双重压力:

运算速率压力:每个输出采样需完成L次乘加,等效运算速率为$ L \cdot F_s/M $,当 Fs 达到数百 MHz 乃至 GHz 时,单时钟域难以承受。

资源浪费:若采用全并行 FIR(每抽头一个乘法器), 个乘法器同时工作,但输出速率仅为 Fs/M,大量运算结果在抽取时刻之间被直接丢弃。

多相分解原理:将原型滤波器 H(z)分解为M个子滤波器,每个子滤波器以 1/M 的速率运行。

FPGA实现时,如何以最小资源实现多相结构的延迟线与系数存储?。


二、SRL多相结构

多相分解

设原型 FIR 滤波器系数为h[0],h[1],…h[L-1] ,抽取因子为M。定义多相子滤波器Ei(z):

$$ E_i(z)=\sum_{n=0}^{S-1} h[nM+i]\cdot z^{-n},\quad i=0,1,\dots,M-1 $$

其中 S=[L/M] 为子滤波器长度。整个抽取系统可表示为:

$$ Y(z)=\sum_{i=0}^{M-1} z^{-i}\cdot E_i(z^M)\cdot X(z) $$

直观上,输入序列 x[n] 被分配到 M 条支路,每条支路间隔M个采样取一个数据,送入对应的子滤波器Ei 。

SLR多路并行抽头

在FPGA中的实现是 M 路独立的子滤波器,每路配有各自的移位寄存器

“单延迟线 + 并行抽头”架构

构建一根长度为 (S-1)M+1 的串行移位寄存器。每进入一个新采样,寄存器整体移位。从寄存器中每隔 M 个位置抽头,可一次性读出:

$$ \text{DBuf}=\big[x[n],\,x[n-M],\,x[n-2M],\dots,x[n-(S-1)M]\big] $$

这组数据恰好是某一相子滤波器在当前时刻所需的全部输入样本。

随着 n 递增,M个连续周期内分别对应M个不同相位,它们的乘加结果累加起来,便构成一个完整的抽取输出。

这种结构实现可以采用Xilinx FPGA的 SRL16E / SRL32E 原语,一个 LUT6 可配置为 32 级移位寄存器,通过地址端口 A[4:0] 可异步读出任意深度的延迟数据。因此,“每隔 M 抽头”在硬件上无需级联大量触发器,只需SRL配合并行地址译码即可。


三、Maltba代码实现与仿真

参数与输入生成

sig_len = 112;  xin = (1:sig_len)';  % 构造测试序列
h = [1 2 3 4 5 6 7 8 9 10 11 12];  % 12 阶 FIR 系数
M = 4;                               % 抽取因子

选取 L=12、M=4,则子滤波器长度S=[12/4]=3 。

输入序列被截断为 K`M=28*4=112 点,确保整数帧处理。

Image

多相系数分解函数 SubPolyA

function subh = SubPolyA(h, M)
    K = ceil(length(h)/M);
    hnew = [h(:); zeros(K*M-length(h), 1)];  % 补零到 M 的整数倍
    subh = zeros(K, M);
    for n = 1:K
        htemp = hnew(1+(n-1)*M : M+(n-1)*M);
        subh(n, :) = htemp(end:-1:1);  % 每段反转
    end
end

该函数将系数向量按长度 M 分段,每段反转后填入 `subh` 矩阵的对应行,得到:

$$ \mathrm{subbh}= \begin{bmatrix} 4 & 3 & 2 & 1 \\ 8 & 7 & 6 & 5 \\ 12 & 11 & 10 & 9 \end{bmatrix} $$

观察矩阵结构:

第 j 列恰好是子滤波器 Em-j 的系数(按延迟从大到小排列)。例如第 1 列 [4,8,12]T 对应h[3],h[7],h[11] ,即E3(z)的系数。

主循环:串行移位与相位累加

tap_delay = zeros(1, (S-1)*M+1);  % 长度 9 的移位寄存器
DBuf = zeros(1, S);               % 并行抽头缓存,长度 3
MCnt = 0;  p = 1;
for n = 1:xlen_new
    tap_delay = [xnew(n), tap_delay(1:end-1)];  % 新采样左移进入
    DBuf = tap_delay(1:M:end);                   % 从位置 1,5,9 抽头
    
    y(p) = DBuf * subh(:, MCnt+1) + y(p);        % 当前相的乘积累加
    
    if(MCnt == M-1)
        MCnt = 0;  p = p + 1;    % M 个相位完成后,输出更新
    else
        MCnt = MCnt + 1;         % 切换到下一相系数
    end
end

移位寄存器 tap_delay

长度(S-1)M+1=9。每周期新数据从左侧推入,旧数据右移。这对应 FPGA 中SRL的串行移位行为。

并行抽头 DBuf

tap_delay(1:M:end) 从位置 1,5,9 并行读出数据。当 n≥8 时,DBuf 恰好为 [x[n],;x[n-4],;x[n-8]] 正是子滤波器所需的 3 个延迟样本。

Image

相位计数器 MCnt:循环0→M-1 。在每个 M 采样周期内,分别用 subh 的第 1 至第 M 列与 DBuf 做点乘,结果累加到同一输出 y(p)。

输出周期:每 M=4 个输入采样,完成一次完整的 L=12 次乘加,产生一个抽取输出。

以 P=2(对应输入N=5~8 )为例验证:

Image

累加后合并同类项,恰好得到标准 FIR+抽取结果:

$$ y(2)=1x_8+2x_7+3x_6+4x_5+5x_4+6x_3+7x_2+8x_1 $$

与MATLAB参考 比对

yref = downsample(filter(h,1,xnew), M, M-1)

Image

四、FPGA 工程价值与资源优化

SRL替代触发器链

在 Xilinx 7 系列及 UltraScale 架构中,一个 LUT6 可配置为 SRL32,实现 32 级移位寄存器并支持任意深度的异步读端口。对比传统用触发器(FF)搭建延迟线:

实现方式 32 级延迟资源消耗 并行抽头能力
触发器链 32 个 FF 需额外 MUX,资源高
SRL 链 1 个 LUT6 原生支持地址译码并行读出

运算速率与抽取匹配

主循环每M个输入采样产生 1 个输出,等效输出速率为 Fs/M。若输入为 400 MHz、M=4,则输出为 100 MHz,后续逻辑(如 IIR 补偿、解调)可在低速域从容处理。乘法器在每个周期只执行 S=3 次乘法(而非 L=12 次),通过系数切换完成全部运算,资源效率极高。

可参数化扩展

代码中 M 和 h 均为参数。SubPolyA 函数自动处理补零和矩阵重组,使得同一 RTL 模板可适配不同抽取率和滤波器阶数。在 FPGA 中,这对应于 generate 语句的参数化实例化——编译时根据 M 和 S 展开硬件,而非运行时软件循环。

五、结语

将数学上的多相子滤波器,映射为物理上的一根 SRL 延迟线加多路并行抽头;

将 M 个慢速子滤波器,折叠为单时钟域内通过系数轮询完成的串行-并行混合结构。

相关推荐