1. 脉动阵列与FIR滤波器的天生契合
第一次接触脉动阵列时,我盯着那个像心电图一样规律跳动的数据流示意图看了整整半小时。这种由多个相同处理单元(PE)组成的计算阵列,通过数据流水和局部互联实现高效运算的特性,简直就是为FIR滤波器量身定制的解决方案。
为什么这么说?让我们拆解一个典型的3抽头FIR滤波器公式:y[n] = h[0]x[n] + h[1]x[n-1] + h[2]x[n-2]。你会发现其中包含三个关键特征:
- 规则的数据复用(每个输入x要参与多次计算)
- 固定的计算模式(乘累加操作重复出现)
- 局部数据依赖(只需相邻时间步的数据)
这正好对应脉动阵列的三大优势:
- 模块化设计:所有PE结构相同,VLSI实现时只需设计一个PE单元重复布局
- 数据驱动:系数h[k]和输入x[n]像血液一样在PE间规律流动
- 高并行度:多个PE同时处理数据流的不同阶段
实际项目中遇到过这样的情况:传统串行实现需要跑在500MHz才能满足吞吐量要求,而改用脉动阵列后,200MHz时钟就能达到相同性能,这让我深刻体会到硬件架构选择的重要性。
2. 从数学到硅片:脉动阵列设计方法论
2.1 依赖图的空间魔法
设计脉动阵列的第一步是构建算法的规则依赖图(DG)。以3抽头FIR为例,我们可以画出如下的二维空间表示:
x[0]h[0] -> x[0]h[1] -> x[0]h[2] x[1]h[0] -> x[1]h[1] -> x[1]h[2] x[2]h[0] -> x[2]h[1] -> x[2]h[2]图中每个节点代表一个乘累加操作,三个基本向量定义了数据流动:
- 输入向量(0,1):x[n]沿垂直方向传播
- 系数向量(1,0):h[k]沿水平方向传播
- 输出向量(1,-1):部分结果沿对角线传播
2.2 关键设计向量的选择艺术
将二维DG映射到一维脉动阵列时,需要精心选择三个核心向量:
# 以输入广播型设计为例 projection_vector = [1, 0] # 沿h轴投影 processor_vector = [0, 1] # PE沿x轴排列 schedule_vector = [1, 1] # 时间推进方向这三个向量必须满足两个铁律:
- 正交性约束:projection_vector · processor_vector = 0
- 时序约束:projection_vector · schedule_vector ≠ 0
在某个音频处理芯片项目中,我们通过调整schedule_vector将硬件利用率从60%提升到85%,关键就是找到了更优的(1,2)调度方案。
3. 实战优化:五种经典架构对比
3.1 输入广播型(设计2改进版)
这是最直观的实现方式,特点包括:
- 输入x同时广播到所有PE
- 系数h从左向右流动
- 输出y在PE内部累加
硬件连接示意图:
PE0 --D--> PE1 --D--> PE2 | | | (x广播) (x广播) (x广播)优势:控制简单,适合固定系数场景劣势:输入带宽要求高,动态更新系数时不灵活
3.2 输出驻留型(设计3)
我们团队在5G基带芯片中采用的变体:
- 每个PE固定存储一个h系数
- 输入x从左向右流动
- 输出y在阵列中累积移动
Verilog关键代码片段:
always @(posedge clk) begin if (valid_in) begin x_reg <= x_in; y_acc <= y_in + h_local * x_reg; end end这种结构在TSMC 7nm工艺下实现时,面积比广播型节省18%,但需要更复杂的数据对齐控制。
4. 进阶优化技巧:超越教科书
4.1 混合维度投影
当处理长抽头FIR时(比如128抽头),可以尝试二维脉动阵列。通过将投影向量选为(1,1),能得到类似下面的结构:
PE00 -> PE01 -> PE02 ↓ ↓ ↓ PE10 -> PE11 -> PE12在某雷达信号处理项目中,这种设计使吞吐量提升了3倍,代价是增加了15%的路由复杂度。
4.2 动态重配置技巧
现代通信系统常需要可变系数FIR。我们开发了一种系数预加载方案:
- 空闲周期将新系数串行移入PE
- 通过shadow register实现无缝切换
- 切换时插入2个周期的bubble
实测切换过程信噪比恶化仅0.2dB,远优于传统方案。
5. 性能评估与折衷艺术
5.1 量化评估指标
设计选择时需要权衡多个维度:
| 指标 | 输入广播型 | 输出驻留型 | 二维阵列 |
|---|---|---|---|
| 吞吐量(Msps) | 320 | 280 | 500 |
| latency(周期) | N | 2N | √N |
| 面积(mm²) | 0.12 | 0.09 | 0.25 |
| 功耗(mW) | 45 | 38 | 80 |
5.2 选择决策树
根据项目需求可以这样决策:
- 需要最低延迟 → 输入广播型
- 追求最低功耗 → 输出驻留型
- 要求最高吞吐 → 二维阵列
- 需要系数可调 → 带shadow register的变体
记得在某次流片前三天,我们突然接到算法更新需求,幸亏选择了带动态配置的设计,否则项目就得延期一个月。这个教训让我明白:架构的可扩展性有时比峰值性能更重要。