4. PolarFire逻辑资源与DSP建模
在PolarFire器件上做算法加速,第一步不是写RTL,而是建立一张“资源账本”:算法里每一次乘加、每一级缓存、每一个状态寄存器,最终都要落到具体的LUT、DFF、LSRAM、uSRAM和Math Block上。只有把账算清楚,才能判断一个设计是“能装下”还是“装不下”,以及该用Math Block硬核还是用LUT拼软乘法器。本节围绕这五类资源,讲清它们的配置方式、位宽约束、流水级设计,以及一套可复用的资源估算方法。
五类资源的定位与配置粒度
PolarFire的逻辑资源可以按“组合—时序—存储—运算”四个维度理解。LUT是4输入查找表,每个LUT可实现任意4变量组合逻辑,是组合逻辑的基本单元;DFF是与之配对的触发器,用于寄存LUT输出或独立寄存信号。在Libero SoC的综合报告中,LUT和DFF通常以“4LUT+DFF”成对统计,但二者可独立使用——纯组合路径只消耗LUT,纯寄存器只消耗DFF。
LSRAM是大容量单端口/双端口SRAM,PolarFire中每个LSRAM块容量为20 Kbit,支持最高72位数据宽度,适合做大块数据缓存、行缓冲、查找表存储。uSRAM是小型分布式SRAM,每块容量为64×12 bit(即768 bit),可级联扩展,适合小容量、多实例、低延迟的存储需求,例如系数表、小FIFO、移位寄存器组。Math Block是18×18位有符号乘法器加48位累加器,是DSP运算的核心硬核,每个Math Block还带有预加器和级联通路,可构建FIR、FFT蝶形、矩阵乘等结构。
配置粒度上,LUT/DFF以“个”为单位,LSRAM以“块”为单位,uSRAM以“块”为单位,Math Block以“个”为单位。资源估算时,必须把算法映射到这些粒度上,而不是停留在“大概需要多少逻辑”的模糊判断。
位宽约束与流水级设计
位宽是资源估算中最容易出错的环节。LUT本身不限制位宽,但一个N位组合运算需要N个LUT并行实现,例如32位加法器约消耗32个LUT(进位链可优化,实际略少)。DFF的位宽直接等于寄存器数量,一个32位流水寄存器就是32个DFF。LSRAM的位宽配置需要特别注意:每个LSRAM块最大72位,若数据位宽为128位,则必须用两块LSRAM并联,且地址深度减半。uSRAM每块只有12位宽,做16位存储时需要两块级联,做32位时需要三块(36位)或按实际需求拼接。
Math Block的位宽约束更为关键。每个Math Block是18×18位有符号乘法器,若算法需要16×16位乘法,正好一个Math Block;若需要24×24位乘法,则需要拆分为多个18×18乘法并做部分积累加,通常消耗4个Math Block。PolarFire的Math Block支持级联,相邻块之间可通过专用通路传递部分积,减少LUT消耗。流水级设计上,Math Block内部已含寄存器,可配置为0级、1级或2级流水。0级流水组合延迟大,适合低频;1级流水在乘法后加寄存器,可提升频率;2级流水在乘法前后各加一级,适合高频设计。实际工程中,建议至少使用1级流水,否则Math Block的时序可能成为瓶颈。
资源估算方法:从算法到资源账本
资源估算不是事后统计,而是设计前的“预算”。以一个64点复数FFT为例,说明估算过程。64点FFT需要6级蝶形,每级32个蝶形,共192个蝶形。每个蝶形包含1个复数乘法(4个实数乘法+2个加法)和2个复数加法。若全部用Math Block实现,每个实数乘法占1个Math Block,则192×4=768个Math Block,这显然超出PolarFire器件容量(通常几十到几百个)。因此必须采用时分复用:用1个Math Block在多个时钟周期内完成多个乘法。若系统时钟200 MHz,采样率10 MHz,则每个采样周期有20个时钟周期可用。64点FFT每采样需要192个蝶形,若每蝶形用1个Math Block分时完成4个实数乘法,则需要192个Math Block同时工作,仍不可行。实际做法是进一步降低并行度:用16个Math Block,每个处理12个蝶形,则每个蝶形有20/12≈1.67个时钟周期,不够。因此需要重新评估:要么提高时钟频率,要么降低FFT点数,要么改用LUT实现部分乘法。
这个例子说明,资源估算必须与吞吐率、时钟频率联合考虑。正确的估算顺序是:先确定算法运算量(乘法次数、加法次数、存储量),再确定目标吞吐率(每秒多少采样),然后计算可用时钟周期数,最后反推所需并行资源数。公式为:所需Math Block数 = 每采样乘法次数 / (时钟频率 / 采样率)。若结果大于器件容量,则必须降低并行度或改用其他实现方式。
对于存储资源,估算方法类似。一个64点FFT需要存储64个复数,每个复数32位(16位实部+16位虚部),共64×32=2048位。LSRAM每块20 Kbit,一块足够。但若做1024点FFT,则需要1024×32=32768位,约1.6块LSRAM,实际用2块。uSRAM适合存储旋转因子:64点FFT需要64个旋转因子,每个32位,共2048位,用3块uSRAM(每块768位)即可。注意uSRAM的深度只有64,若旋转因子数量超过64,需要多块级联并增加地址译码逻辑。
可复用的资源估算检查表
下表给出一个可直接用于工程项目的资源估算检查表,按资源类型列出关键参数和估算公式,设计时逐项填写即可得到初步资源预算。
| 资源类型 | 关键参数 | 估算公式 | 示例(64点FFT) |
|---|---|---|---|
| LUT | 组合逻辑项数、输入变量数 | Σ(每项LUT数),4输入以内为1 | 控制逻辑约200 LUT |
| DFF | 流水级数、数据位宽、状态位 | Σ(位宽×级数) + 状态位 | 32位×6级 + 16状态位 ≈ 208 DFF |
| LSRAM | 总存储bit、位宽、深度 | ceil(总bit / 20480) | 2048 bit → 1块 |
| uSRAM | 总存储bit、位宽、深度 | ceil(总bit / 768) | 2048 bit → 3块 |
| Math Block | 每采样乘法次数、时钟频率、采样率 | 乘法次数 / (fclk / fs) | 768 / (200M/10M) = 38.4 → 39个 |
最后强调一点:资源估算的精度取决于对算法结构的理解深度。建议在RTL编码前,先用电子表格建立“运算—资源”映射表,逐项列出每个运算单元的类型、位宽、流水级数和复用次数,再套用上述公式。这样得到的资源账本,既能指导RTL设计,也能在综合报告出来后快速定位偏差原因——是LUT超了,还是Math Block不够,或是存储配置不合理。只有把账算清楚,PolarFire上的算法加速才能从“能跑”走向“跑得好”。