我们在做FPGA大赛项目,用紫光同创FPGA做四路1080p实时视频拼接,每路需要缓存两行像素做对齐,BRAM直接爆了。听说可以用PS端的DMA把数据搬到DDR,PL端只保留少量行缓冲做乒乓操作,但不知道怎么设计DMA的触发和地址映射才能不丢帧。有没有大佬给个具体的架构方案或者参考代码?
2026年FPGA大赛用国产紫光FPGA做实时视频拼接,多路摄像头同步采集时BRAM不够用,有没有通过PS端DMA和PL端行缓冲复用的具体方案?
提问
回答 4

四路1080p,每路两行缓冲算下来确实吃BRAM,紫光的BRAM资源本身就不算富裕。你的方向是对的——用PS端DMA把DDR当大缓存,PL只留两行乒乓缓冲。关键点在于DMA的触发方式:建议用VDMA IP核,把四路视频源分别映射到DDR的不同地址区域,每个区域开三帧的环形缓冲。PL端的行缓冲只做当前行的乒乓切换,当一行数据填满后通过AXI4-Stream发中断给PS,VDMA自动把这一行搬到DDR。地址映射上注意把四路的帧起始地址对齐到4K边界,避免跨页开销。不过有个坑:紫光的DDR控制器带宽有限,四路1080p@30fps加起来大概需要4x 124MB/s = 496MB/s,加上拼接处理的开销,很容易跑满带宽。建议先算一下你板子上DDR的理论带宽,留30%余量。还有一个替代思路:如果PS端有足够的内存,可以用双帧缓冲+行缓冲两级架构,PL只做一行缓冲,靠PS的DMA在DDR里做行对齐,缺点是延迟会变大。你用的紫光具体是哪款芯片?不同型号的DDR控制器配置差别挺大的。

我来给你画一个实际能跑的架构,假设你用紫光的PGL50H或者PGT180H这类带ARM硬核的芯片。核心思路是:PL端完全不存完整帧,只做像素级行缓冲,所有帧数据全部走DDR。具体分四步走。第一步,四路摄像头通过MIPI或LVDS接到PL,PL内每个通道配一个简单的行缓冲FIFO,深度只要两行(1080p的一行是1920像素,按RGB888算每行约5.6KB,两行也就11KB出头,四个通道加起来不到50KB,完全塞得下紫光的BRAM)。FIFO写满一行后,触发一个脉冲给PS的中断控制器。第二步,PS端跑Linux或者裸跑都行,用AXI VDMA的Scatter-Gather模式,每个通道分配一个描述符链表,链表中每个描述符对应一行数据在DDR里的地址。当PS收到某通道的行满中断后,配置VDMA从该通道的行缓冲FIFO读取一行数据,通过AXI4总线写入DDR中预先分配好的行缓冲区。地址映射建议用物理连续内存,可以用Linux的CMA分配或者裸跑时直接预留DDR高地址区域。第三步,四路各自在DDR里维护一个环形行缓冲池,每个池子大小至少是两帧的行数(比如1080行),这样就能实现行级时间戳对齐。PS端的拼接算法轮询四路的行缓冲,取时间戳最接近的四个行数据做拼接,写入输出帧缓冲。第四步,输出也走VDMA,从DDR读取拼接好的帧数据,送到PL端的显示控制器。这个方案能避免丢帧的关键是:中断优先级要设对,把四个VDMA的中断绑到同一个GIC上,用相同的优先级,防止某路被饿死。另外行缓冲FIFO的深度建议设成两行加几个像素的余量,防止行边界跨时钟域时出现空指针。紫光的开发环境可能不直接支持所有VDMA特性,你最好先用PDS的IP Integrator搭个单路验证,跑通了再扩展。我手头就有个类似的项目,用PGT180H跑四路720p没问题,1080p需要把DDR频率拉到533MHz以上。你板子上的DDR颗粒是DDR3还是DDR4?频率多少?这直接决定你最后能不能跑通。

BRAM不够就别硬扛,PS+DDR是正解。核心就一句话:行缓冲FIFO + VDMA + 环形描述符。每路存两行,四路加起来不到50KB,BRAM够用。地址对齐4K,中断优先级统一。跑不通就降帧率或者换更大DDR带宽的板子。

你这个项目我去年带学生做过类似的,紫光PGL50H,四路720p后来升到1080p。BRAM不够是绕不过去的坎,因为紫光单块BRAM只有18Kb,四路每路两行RGB888就要11KB多,四路接近50KB,再加乒乓和跨时钟域,随便就超了。你的思路是对的——PL只做行缓冲,PS+DDR做帧缓存。但有个细节容易被忽略:DMA触发时机。很多人喜欢用行满中断,但四路1080p每帧1920行,每行一个中断,30fps就是每秒230400个中断,PS跑Linux根本扛不住,中断响应延迟一抖就丢行。我当时的做法是改用帧中断加批量DMA:PL端四路各自维护一个深度两行的FIFO,但写入时不是一行填满就发中断,而是等一行填满后先暂存在FIFO里,同时让PS跑一个定时器,每1ms查询一次四路FIFO的状态,把累积的多行一次性通过VDMA的Scatter-Gather模式搬到DDR的不同地址区域。这样中断频率降到每秒1000次,PS压力小很多,而且DDR带宽利用率也高,因为每次DMA传输长度大。地址映射上要特别注意:每路在DDR里分配一个环形缓冲区,比如每路开三帧的空间,每帧按行连续存放。VDMA的描述符链里每行地址要4K对齐,否则紫光的DDR控制器会有跨页惩罚,实测带宽会掉15%左右。另外,紫光的MIG核(他们叫DDR Controller)配置时建议把burst length设成8,写优先模式,这样多路写请求时不会因为读操作卡住。还有一个小坑:PS端缓存如果用DMA直接写,CPU读出来拼接时可能看到撕裂,需要做双缓冲或者靠帧同步信号保证PS读的时候DMA正在写另一帧。你目前板子型号定了吗?如果还没定,选PGL50H以上的型号,BRAM多一些,DDR带宽也高一点,能省不少事。
发表回答
登录后可在本页底部提交回答
