我们队伍今年FPGA大赛选了高云FPGA做双路1080p视频拼接,HDMI采集两路进来,在FPGA里做缩放和融合再输出。现在BRAM爆了,两路行缓冲加缩放系数表就把BRAM吃光了,DDR3带宽也紧张。导师说可以用行缓冲乒乓加DDR3分时复用,但我不知道怎么分配读写带宽才能不丢帧。有没有做过类似项目的朋友?求具体架构和资源分配方案,比如行缓冲深度设多少、DDR3读写调度怎么设计,BRAM和DDR3的带宽怎么平衡?
2026年了,FPGA大赛用国产高云FPGA做实时视频拼接,HDMI输入两路1080p,BRAM不够用,怎么用行缓冲乒乓和DDR3分时复用硬挤?求具体架构
3 个回答

先别急着上乒乓,把缩放系数表挪到分布式RAM或者干脆用乘法器现算,能省一大半BRAM。行缓冲的话,两路1080p同时处理确实吃紧,但你可以把两路输入错开一拍,共用同一块行缓冲,读的时候按行号分时取,这样单路乒乓就够了。DDR3那边,写带宽留30%余量是常识,但实际调度建议用简单的轮询加优先级:写请求优先级高于读,因为读可以靠行缓冲兜底延迟。行缓冲深度设成两行就够了,不用四行,多了也是浪费。先跑通再优化,别一上来就追求完美。你们现在用的高云具体是哪个型号?不同系列的BRAM块大小差挺多的。

说下我当年做类似项目的思路吧,核心矛盾其实不是BRAM容量,而是你让BRAM干了太多它不该干的活。行缓冲是流式数据,本质上是延迟线,DDR3是随机访问存储,两者职责要分开。我的做法是:两路HDMI进来后,各配一个两行的行缓冲,深度就设成1920x2x3字节,RGB888的话大概11KB,两块加起来22KB,这在高云的中端芯片上完全能接受。真正的BRAM杀手是缩放系数表——如果你用双线性插值,每行都要查系数,两路加一起就是1920x2x4字节的系数表,这玩意千万别用BRAM,直接LUT分布式RAM,高云的分布式RAM容量虽然小,但系数表是只读的,可以用查找表实现,省下的BRAM留给输出端的融合缓存。DDR3分时复用这块,我的调度器是这么设计的:DDR3接口跑在800MHz,数据位宽32bit,理论带宽3.2GB/s,两路1080p60输入加一路1080p60输出,总带宽需求大概2.4GB/s,留30%余量确实够。但关键在调度粒度,我建议用128字节为最小传输单位,写请求每攒够128字节就发一次,读请求按行预取,一次读一整行到行缓冲里。仲裁用简单的时间片轮询,写占60%时间片,读占40%,但写内部再分两路各占30%。这样就不会出现一路把另一路饿死的情况。还有个坑是DDR3的bank冲突,你两路写如果落在同一bank的不同row,效率会掉一半,所以地址映射要交错,把两路的起始地址错开一个bank。最后提醒一句,高云的DDR3控制器IP默认是支持AXI4接口的,但多端口AXI Interconnect在高云上可能没有现成IP,你得自己写个简单的arbiter,别指望官方库。你们现在卡在哪个环节了?是仿真过不了还是上板掉帧?

其实导师说的乒乓加DDR3分时复用,说白了就是拿时间换空间,但很多人忽略了一个前提:你的缩放比是多少?如果两路都是等比缩小到一半再拼接,那行缓冲压力会小很多,因为你可以先隔行抽点再进行缓冲,相当于把有效数据量减半。如果是一路放大一路缩小,那放大那路的行缓冲深度就得按放大后的行宽算,这时候两路乒乓就没意义了,因为两路的行宽不一样,你没法共用同一块缓冲。我的建议是先把需求拆清楚:两路是同时缩放还是先拼接再缩放?如果先缩放再拼接,那每路只需一个两行缓冲就够了,BRAM占用直接砍半,剩下的空间给输出端的融合缓存。DDR3那边,我个人觉得分时复用不如直接改成行交替存储——两路写DDR3时,按行号交替写入不同地址段,读的时候按行号交替读,这样仲裁器可以做成固定模式,不需要动态优先级,时序更好收敛。不过这样有个风险,就是如果两路帧率不同步,会出现某一行读不到数据的情况,所以最好在输入端加个FIFO做帧同步,深度设成一行就行。你们比赛时间紧的话,我建议先按这个简化方案做,能出效果就行,别追求极致带宽利用率。对了,高云的工具链对DDR3 IP的例化方式和其他家不太一样,你们是用的官方例程还是自己写的控制器?如果是自己写的,记得看下读写时序余量够不够。
发表回答
登录后可在本页底部提交回答