今年FPGA大赛我选了高云FPGA做实时视频去雾,暗通道先验算法里导向滤波和透射率计算占用了大量BRAM,分时复用已经用了但还是爆资源。除了分时复用,有没有更硬核的优化技巧?比如用行缓冲代替整帧存储、流水线重排减少中间变量,或者用移位寄存器替代部分BRAM?求具体实现步骤和资源对比,最好能给出代码框架参考。
2026年FPGA大赛用高云FPGA做实时视频去雾,暗通道先验算法BRAM不够,除了分时复用还有哪些硬核优化技巧?
4 个回答

行缓冲加流水线重排这招在高云上特别值得试。暗通道先验的导向滤波核心是局部均值计算,你完全不用存整帧,用两到三行缓冲加滑动窗口,把均值滤波拆成行累加和列累加两个流水级,BRAM消耗能从几十K降到几K。具体做法:先对输入像素做行方向的累加,存到FIFO里,再在列方向做二次累加,中间用寄存器打拍对齐时序。透射率计算里的最小值滤波也能用类似思路,把3×3或5×5窗口的排序换成比较器树,只缓存几行数据。高云的LUT资源相对充裕,用查找表代替小规模乘法器也能省BRAM。你当前用的是什么分辨率?如果是1080p,行缓冲深度设1920就够了,试试看能不能压到目标BRAM的一半以下。

分时复用只是治标,真正的硬核优化要从算法结构和数据流两个方向下手。先讲数据复用和重计算——导向滤波里协方差计算需要大量乘法,你不需要每个像素都重新算一遍窗口内的和,可以用前一窗口的部分结果做增量更新。具体来说,滑动窗口每移动一列,只需要减去离开列的数据、加上新进入列的数据,这样乘法器数量减半,中间结果的存储也只需要几个寄存器加一个移位寄存器链。高云的LUT可以实现小型移位寄存器,比BRAM更灵活,适合这种窗口尺寸固定的场景。再讲流水线重排:透射率计算和去雾输出本来是两个串行阶段,你可以把透射率的粗计算提前到输入级,同时用行缓冲保留原始像素,等透射率算完再直接做大气光去除。这样中间变量只存一行数据,而不是存整帧透射率图。最后提一下动态部分重配置(DPR),但高云的部分器件不支持,你最好先查器件手册。如果支持,可以把暗通道估计和导向滤波分成两个bitstream,运行时切换,BRAM复用。不过DPR开发周期长,大赛时间紧的话不建议赌这条路。更实操的方案是:先分析综合报告里哪个模块占BRAM最多,大概率是导向滤波的窗口缓存,针对它单独用LUT+寄存器重写,其他模块保持原样。你有没有试过用高云的IP Generator生成FIFO,把宽度设成最小位宽来省BRAM?有时候默认配置会浪费一半资源。

我补充一个容易被忽略的点:查表替代乘法器在暗通道先验里特别管用,但要注意查表的位宽取舍。透射率计算里的除法或乘法,输入范围一般是0到255,你可以预先算好所有可能结果存到LUT里,高云LUT4或LUT5可以组合成小ROM,占用几十个LUT,省下几个乘法器对应的DSP和BRAM。代价是精度损失——如果输入是8位,查表输出也截成8位,去雾效果肉眼几乎看不出差别。另一个思路是重计算:有些中间结果其实可以重复利用,比如暗通道图里的最小值,你求完一次后存到寄存器堆里,后续导向滤波的均值计算直接读,不用再从原始帧重新提取。这样帧缓存只保留一行原始像素,BRAM开销直接降一个数量级。但要注意,重计算会增加组合逻辑路径,时序可能变差,高云内部走线延迟偏大,你最好在关键路径上插寄存器打一拍。个人感觉,对于大赛来说,行缓冲加查表是最稳妥的,代码量可控,效果立竿见影。你现在的分时复用是时分到几个模块?如果已经压到极限,查表+重计算还能再挤出一半资源。方便的话说说你用的具体器件型号和BRAM总量,我可以帮你估一下各方案的上限。

看到你说暗通道先验BRAM爆了,我猜你大概率是直接把整帧透射率图和导向滤波的中间结果都存了下来。其实换个思路,把算法拆成滑动窗口的流水线,很多中间变量根本不需要落地。比如导向滤波里的均值计算,你完全可以用两个行FIFO加一个列累加器,每次只处理三行数据,窗口滑过去就丢弃旧行。高云的BRAM通常支持真双口,你还可以把一个BRAM拆成两个小FIFO来用,代价是读写时序要错开一拍。透射率计算里的最小值滤波,别用排序网络,用比较器树加行缓冲,窗口3×3只需要缓存两行加当前行,BRAM开销直接降到原来的十分之一以下。不过要注意,这种流水线重排会增加组合逻辑级数,高云内部走线延迟偏大,你最好在每级累加器输出插一级寄存器,时序会干净很多。另外,大气光值A的估计也别用全局统计,改成每帧只对暗通道图采样几个固定位置的像素,省掉整帧的统计RAM。你当前用的是什么分辨率?如果是720p以下,行缓冲深度设1280就够了,试试看能不能把BRAM压到4个以内。
发表回答
登录后可在本页底部提交回答