光
大容量片上缓存是很多 FPGA 设计的瓶颈:BRAM 容量不够,URAM 又有使用限制。最近一个图像处理项目里,行缓存 + 帧缓存一共要 20MB 左右,纯 BRAM 塞不下,混用 BRAM 和 URAM 才把设计跑通,分享几点实测经验。
一、先算清楚容量账。BRAM 每块 36Kb、URAM 每块 288Kb,同样存 8MB 数据,URAM 只需要约 1/8 的块数。但 URAM 只有固定 72bit 位宽(可配 72x4096),小位宽数据塞进去浪费严重;位宽小于 36bit 的小表,BRAM 反而更省。我的做法是:大位宽流式数据走 URAM,小表、状态机查表走 BRAM。
二、时序上 URAM 更吃紧。URAM 是同步读写、固定两周期延迟,BRAM 可以配成读写同周期。把 URAM 放在关键路径上,时序收敛会明显变难。实测下来,URAM 输出后至少要加一级寄存器再进后续逻辑,否则 250MHz 以上的设计很难收敛;BRAM 则可以省掉这一级。
三、注意读写冲突规则。URAM 不支持同一地址同周期读写,写冲突时读回的是旧数据还是新数据取决于配置,数据手册里写得很绕。我的做法是把读写地址错开一个周期,或者在控制逻辑里显式插入气泡,避免依赖默认行为。
四、仿真与实测对不上时,先查初始化。URAM 上电后内容是未定义的,仿真里默认是 0;如果设计依赖上电初值,仿真跑得好好的,上板第一帧就错。解决办法是复位后先写一遍清零,或者在状态机里显式标记“未初始化”状态。
最后留一个问题:你们在片上缓存不够用的时候,是优先换大器件,还是先在算法层面砍缓存?比如把帧缓存改成行缓存加片外 DDR,时序和带宽的取舍是怎么算的?
一、先算清楚容量账。BRAM 每块 36Kb、URAM 每块 288Kb,同样存 8MB 数据,URAM 只需要约 1/8 的块数。但 URAM 只有固定 72bit 位宽(可配 72x4096),小位宽数据塞进去浪费严重;位宽小于 36bit 的小表,BRAM 反而更省。我的做法是:大位宽流式数据走 URAM,小表、状态机查表走 BRAM。
二、时序上 URAM 更吃紧。URAM 是同步读写、固定两周期延迟,BRAM 可以配成读写同周期。把 URAM 放在关键路径上,时序收敛会明显变难。实测下来,URAM 输出后至少要加一级寄存器再进后续逻辑,否则 250MHz 以上的设计很难收敛;BRAM 则可以省掉这一级。
三、注意读写冲突规则。URAM 不支持同一地址同周期读写,写冲突时读回的是旧数据还是新数据取决于配置,数据手册里写得很绕。我的做法是把读写地址错开一个周期,或者在控制逻辑里显式插入气泡,避免依赖默认行为。
四、仿真与实测对不上时,先查初始化。URAM 上电后内容是未定义的,仿真里默认是 0;如果设计依赖上电初值,仿真跑得好好的,上板第一帧就错。解决办法是复位后先写一遍清零,或者在状态机里显式标记“未初始化”状态。
最后留一个问题:你们在片上缓存不够用的时候,是优先换大器件,还是先在算法层面砍缓存?比如把帧缓存改成行缓存加片外 DDR,时序和带宽的取舍是怎么算的?

