我们小组正在备赛2026年FPGA大赛,选了基于Zynq的实时视频去雾加速器项目。现在用暗通道先验算法在PL侧实现,发现BRAM资源严重不足,已经用了80%多的BRAM,后面还有导向滤波模块没加。请问大家有什么优化策略?比如能不能把部分数据放到DDR里用AXI总线读取?或者有没有更省资源的算法变体?求有经验的大佬指点,最好能给出具体的资源分配方案。
2026年FPGA大赛备赛,用Zynq做实时视频去雾加速器,暗通道先验算法在PL侧实现时BRAM不够用怎么办?
提问
回答 3

暗通道先验在PL侧吃BRAM是经典坑,核心原因在于你为了求暗通道,得维护一个局部窗口(比如15×15)的像素最小值,如果每个像素都存全图或大块缓存,BRAM当然爆。常规做法是把图像切块处理,比如按行流水,只缓存当前窗口所需的若干行数据,而不是整个frame。具体来说,暗通道窗口15×15,你只需要缓存15行像素(如果是RGB,每行按宽度存),导向滤波的引导图如果也是同一分辨率,同样按行缓存窗口半径对应的行数。这样BRAM消耗就从O(widthheight)降到O(widthwindow_size),一般能省掉一半以上。
至于你说的把数据放DDR用AXI读,这其实是带宽换面积。如果帧率要求不高(比如30fps以下且分辨率不太大),确实可以把整帧放DDR,PL侧只保留小行缓冲,每算一个窗口就通过AXI_HP口突发读一批像素。代价是DDR带宽占用大,且需要处理好读写同步和缓存一致性。Zynq的HP口带宽足够,但要注意AXI burst长度和地址对齐,不然效率掉得厉害。常见做法是乒乓操作:PL侧两个小行缓冲,一个在算当前行,另一个通过DMA从DDR预取下一行。
算法变体方面,暗通道先验本身不是唯一解。如果BRAM实在紧张,可以试简化版:不用固定窗口,改用快速递推最小值(类似一维最小值滤波的列向+行向分离),这样只需缓存几列像素,BRAM更省。或者干脆换算法,比如用基于大气光散射模型但不需要导向滤波的简化版,比如直接用中值滤波代替导向滤波做透射率细化,精度稍降但资源友好。导向滤波本身也吃BRAM,如果非用不可,建议换成box滤波+均值滤波的组合变体,省掉乘法器。
你们现在80% BRAM已经很高了,后续导向滤波大概率加不上。建议先做资源预算:把暗通道、透射率计算、导向滤波、大气光估计每个模块所需的行缓冲和缓存深度列出来,然后按最大并行需求算总BRAM,再用AXI+行乒乓的方式切分。如果预算还是超,就得降窗口大小(比如从15×15降到11×11)或者降分辨率(先缩小再处理)。追问一句:你们用的Zynq具体是7010还是7020?不同型号BRAM块数差一倍,7020有140块,7010只有60块,如果用的是7010,那80%其实才48块左右,换7020直接多一倍空间。

BRAM不够最直接的解法不是硬挤,而是把暗通道求最小值的窗口从全并行改成行流水加列累加。具体说,不要为每个像素保留整个窗口的所有数据,而是算一行最小值时只存当前行的结果,下一行用递推更新。这样BRAM消耗从O(窗口面积)降到O(窗口宽度),导向滤波也能用类似思路拆成两次一维滤波。如果还超,就把大气光估计这种低频计算挪到PS侧用软件算,PL只做核心的透射率和去雾,能省一块缓存。另外确认下你们是不是用了双端口BRAM做帧缓存?改成单端口时序优化也能省块数,代价是调度复杂些。

窗口切成行流水,BRAM立马减半。再爆就上DDR做行缓冲,AXI_HP口开两路,一路读一路写乒乓。别硬塞导向滤波,试试快速双边滤波代替。
发表回答
登录后可在本页底部提交回答
