设计原理:用一根串行延迟线配合并行抽头,将高采样率下的抽取与滤波合并为单时钟域内的高效运算。
一、为什么传统直接实现行不通?
在数字下变频(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 点,确保整数帧处理。
多相系数分解函数 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 个延迟样本。
相位计数器 MCnt:循环0→M-1 。在每个 M 采样周期内,分别用 subh 的第 1 至第 M 列与 DBuf 做点乘,结果累加到同一输出 y(p)。
输出周期:每 M=4 个输入采样,完成一次完整的 L=12 次乘加,产生一个抽取输出。
以 P=2(对应输入N=5~8 )为例验证:

累加后合并同类项,恰好得到标准 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)
四、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 个慢速子滤波器,折叠为单时钟域内通过系数轮询完成的串行-并行混合结构。
572