ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FPGA多路MIPI视频聚合实战:架构设计、DDR缓存与输出驱动

FPGA多路MIPI视频聚合实战:架构设计、DDR缓存与输出驱动 1. 项目缘起与整体设计思路1.1 为什么需要多路MIPI视频聚合做FPGA视频处理的同行大概都有这样的体会单路MIPI摄像头接入本身不算太难真正让人头疼的是当项目要求同时接入两路、四路甚至更多MIPI摄像头并且要把它们的数据汇聚到同一个显示终端或者同一路输出接口上。这个需求在嵌入式工业设备、机器视觉前端、多目拼接显示、车载环视等场景里非常普遍。我最初接触这类需求是在一个多路摄像头采集的项目里客户要求四路MIPI摄像头同时工作每路1080p30最终通过一路MIPI DSI输出到屏幕同时还要支持画面切换和画中画。当时第一反应是找现成的SoC方案但评估下来发现几个问题一是SoC的MIPI输入通道数有限二是多路同时工作时的带宽和延迟不可控三是灵活性差客户后续想改分辨率或者帧率就得换芯片。最后还是回到了FPGA方案上。FPGA做多路MIPI聚合的核心优势在于通道数可以按需扩展只要FPGA的MIPI硬核或者软核资源够用想接几路就接几路数据流完全可控每一路的时序、缓存、仲裁策略都可以自己定义输出格式灵活可以拼接、可以叠加、可以切换完全看后端需求。1.2 整体架构怎么搭一个典型的多路MIPI视频聚合方案从输入到输出可以拆成四个大块MIPI接收层、数据缓存层、聚合处理层、输出驱动层。MIPI接收层负责把每路摄像头的MIPI D-PHY信号解出来还原成像素数据流。这一层的关键是D-PHY的物理层接收和CSI-2协议解析。如果FPGA厂商提供了MIPI硬核比如Xilinx的MIPI D-PHY、紫光同创的MIPI硬核那这部分工作会轻松很多如果没有硬核就得用SelectIO或者LVDS接收器来搭这时候眼图、均衡、去偏斜这些事就得自己操心。数据缓存层是多路聚合的枢纽。每路视频流进来之后不能直接往聚合模块送因为不同摄像头的像素时钟可能有偏差帧同步也不一定对齐。通常的做法是每路先写进一个独立的FIFO或者DDR缓冲区然后用一个统一的仲裁器按行或者按帧从各个缓冲区里取数据。这里就涉及到基于FPGA的多端口DDR读写程序设计后面会详细展开。聚合处理层做的是真正的“聚合”动作。最简单的聚合是画面拼接比如四路1080p拼成一个4K画面复杂一点的有画中画叠加、Alpha混合、帧率归一化等。这一层的实现方式取决于具体需求但核心思路都是把多路数据流在时间或者空间上合并成一路。输出驱动层把聚合后的数据按照目标接口的时序送出去。如果输出也是MIPI那就需要MIPI DSI或者CSI-2的发送端如果是HDMI或者LVDS那就换成对应的发送IP。输出层的时序要求通常比输入层更严格因为显示设备对时序偏差的容忍度很低。1.3 方案选型中的几个关键取舍在实际项目中有几个决策点会直接影响方案的复杂度和最终效果。第一用硬核还是软核。如果FPGA自带MIPI D-PHY硬核优先用硬核。硬核的功耗、面积、信号完整性都优于软核实现而且厂商通常会提供配套的CSI-2控制器IP。软核方案虽然灵活但在高速率下比如每lane超过1Gbps对PCB布线和时序收敛的要求非常高调试周期会拉长很多。第二缓存用FIFO还是DDR。如果只是两路1080p30每路的数据率大约是1920×1080×30×2字节≈124MB/s两路加起来不到250MB/s用片内BRAM做行缓存甚至帧缓存都勉强够用。但如果是四路1080p60总数据率接近1GB/s片内BRAM就不够了必须上DDR。DDR方案的好处是容量大、成本低缺点是控制逻辑复杂多端口仲裁需要仔细设计。第三聚合策略是行级还是帧级。行级聚合的延迟低适合实时性要求高的场景但对各路视频的时序对齐要求高帧级聚合延迟大但实现简单适合对延迟不敏感的应用。我个人的经验是如果各路摄像头的像素时钟同源优先考虑行级聚合如果不同源帧级聚合更稳妥。2. MIPI接收层核心细节与实操要点2.1 MIPI D-PHY接收的关键参数MIPI D-PHY的接收端有几个参数必须搞清楚否则后面调试会非常痛苦。Lane速率决定了你需要的时钟频率和PCB走线要求。以1080p30、RAW10格式为例每帧像素数是1920×10802073600每个像素10bit加上消隐区大概20%的 overhead总数据量约2073600×10×1.2≈24.9Mbit。如果摄像头用2 lane输出每lane速率大约是24.9Mbit×30/2≈373Mbps。这个速率下D-PHY的HS模式完全能胜任PCB走线只要控制好差分阻抗和等长即可。去偏斜校准是多lane接收时必须做的步骤。由于PCB走线长度不可能完全一致各lane之间的信号到达时间会有偏差。D-PHY协议里定义了去偏斜校准序列接收端需要检测这个序列并调整各lane的采样相位。如果FPGA硬核支持自动去偏斜那这部分不用操心如果是软核实现就需要自己写状态机来检测同步码和调整延迟。S参数是评估信号完整性的重要指标。在高速率下比如每lane超过1GbpsPCB的插入损耗和回波损耗会直接影响眼图质量。我一般会在设计初期就用仿真工具看一下通道的S参数确保在Nyquist频率处的插入损耗不超过-6dB。如果超标就得考虑换板材或者缩短走线。2.2 CSI-2协议解析的实操细节CSI-2协议层的工作是把D-PHY送过来的字节流解析成像素数据。这里面有几个容易踩坑的地方。包格式解析。CSI-2的数据包有短包和长包两种。短包用于帧同步和行同步长包用于传输像素数据。每个长包有一个包头包含数据标识和字长。解析的时候要先判断包类型再根据字长读取有效数据。我见过不少人在这一步出错把包头也当成像素数据写进了缓存结果画面出现规律性的错位。数据类型匹配。摄像头的输出格式可能是RAW8、RAW10、RAW12、YUV422、RGB888等FPGA端的解析逻辑必须和摄像头配置一致。如果摄像头输出RAW10但FPGA按RAW8解析画面就会花屏。RAW10的打包方式比较特殊每4个像素占5个字节解析的时候需要做位拼接。虚拟通道处理。如果多路摄像头共用一组MIPI lane通过虚拟通道ID来区分那接收端需要根据VC ID把数据分发到不同的缓存区。这种方案可以节省FPGA的MIPI接口数量但对CSI-2控制器的要求更高。2.3 常见接收端问题与排查问题一MIPI屏调试没信号。这种情况首先要确认摄像头的初始化配置是否正确。很多MIPI摄像头需要先通过I2C写入一系列寄存器才能开始输出如果I2C配置没成功摄像头根本不会发数据。其次要检查D-PHY的HS模式是否正常进入用示波器看差分线上的共模电压和摆幅是否符合协议要求。问题二画面横向花屏。这通常是行同步或者字长解析出了问题。重点检查CSI-2长包的字长字段是否和实际像素数匹配以及行缓存是否溢出。如果花屏是周期性的大概率是某个包的解析错了如果花屏是随机的可能是时序约束没做好导致数据在跨时钟域时丢失。问题三多路同时工作时某一路丢帧。这往往是仲裁器的带宽分配不合理。如果仲裁器采用固定优先级低优先级的那一路在带宽紧张时就会丢帧。解决办法是改用轮询仲裁或者加权轮询保证每路都能分到足够的带宽。实操心得在调试MIPI接收时我习惯先用一个简单的测试图案比如彩条来验证链路是否通畅确认无误后再接入真实摄像头。这样可以排除摄像头配置的干扰快速定位问题是在物理层还是协议层。3. 多路视频缓存与DDR读写设计3.1 基于FPGA的多端口DDR读写架构当多路视频流的总带宽超过片内BRAM的承载能力时DDR就成了必选项。FPGA访问DDR通常通过MIG或者厂商提供的DDR控制器IP用户侧是一个AXI或者Native接口。多路视频流要共享这个接口就需要一个多端口仲裁器。我常用的架构是每路视频流对应一个写通道聚合模块对应一个读通道。写通道把每路的数据按帧或者按行写入DDR的不同区域读通道按照聚合策略从各个区域读取数据。仲裁器负责在多个写通道和一个读通道之间分配DDR的带宽。这里的关键是带宽计算。以四路1080p60、RAW10为例每路的数据率是1920×1080×60×10/8≈155MB/s四路合计约620MB/s。DDR3-1600的理論带宽是1600×812.8GB/s实际可用带宽大概60%到70%也就是7.7GB/s到9GB/s。看起来余量很大但要注意DDR的读写切换会有额外的开销如果读写比例接近1:1实际有效带宽会下降不少。所以设计时至少要留50%的余量。3.2 帧缓存地址管理与同步机制多路视频聚合时每路视频在DDR里需要独立的帧缓存区域。地址管理有两种常见方式固定分区和动态分配。固定分区就是给每路分配一块固定的地址范围比如路0用0x00000000到0x01000000路1用0x01000000到0x02000000以此类推。这种方式实现简单但灵活性差如果某路的分辨率变了地址映射就得改。动态分配是用一个链表或者环形缓冲区来管理地址每帧数据写完后更新写指针读端根据读指针来取数据。这种方式灵活但需要额外的逻辑来维护指针和防止读写冲突。同步机制方面如果各路摄像头的帧同步信号是独立的那就需要在DDR缓存里做帧对齐。常见的做法是给每路维护一个帧计数器聚合模块等到所有路的帧计数器都达到某个值时才开始读取这一组帧。如果某一路的帧率和其他路不一致还需要做帧率归一化比如重复或者丢弃某些帧。3.3 DDR读写时序优化技巧DDR的读写效率对多路视频聚合的成败至关重要。以下几个技巧是我在实际项目中验证有效的。批量传输。DDR的读写命令有固定的开销如果每次只读写几个字节效率会非常低。视频数据是连续的大块数据应该尽量用长突发比如AXI的burst length设为64或者128来传输。我一般会把每行的像素数据攒够一定长度再发起DDR读写而不是一个像素一个像素地操作。读写分离。如果DDR控制器支持读写分离的调度策略尽量开启。这样DDR可以在读请求和写请求之间做更高效的切换减少总线翻转的开销。Bank交错。DDR的物理地址会映射到不同的Bank如果连续访问的地址落在同一个Bank就会产生Bank冲突降低效率。在分配帧缓存地址时可以让相邻的帧或者相邻的行落在不同的Bank上减少冲突概率。预取和缓存。如果聚合模块需要反复读取同一帧数据比如做多帧叠加可以在片内做一个行缓存减少对DDR的重复访问。注意事项DDR的时序约束非常严格尤其是在高频下。如果时序报告里有setup或者hold的violation不要抱有侥幸心理一定要修掉。我见过太多因为DDR时序没收敛导致画面随机花屏的案例排查起来非常耗时。4. 聚合处理与输出驱动实现4.1 画面拼接与叠加的实现方式多路视频聚合最常见的形态是画面拼接。四路1080p拼成一个4K画面每路占一个象限。实现上聚合模块需要根据当前输出的像素坐标判断应该从哪一路的缓存里取数据。具体来说假设输出分辨率是3840×2160四路输入各是1920×1080。对于输出坐标(x, y)如果x1920且y1080就从路0取数据如果x≥1920且y1080就从路1取数据以此类推。这个判断逻辑可以用简单的比较器实现但要注意坐标的边界处理避免出现一行像素跨两路的情况。画中画叠加稍微复杂一点。需要先确定主画面和子画面的区域然后在子画面区域内用Alpha混合公式做像素混合。Alpha混合的公式是输出 前景×Alpha 背景×(1-Alpha)。Alpha值可以固定也可以从寄存器配置。4.2 MIPI DSI输出驱动的关键配置如果输出是MIPI DSI屏幕那输出驱动层需要配置DSI控制器的几个关键参数。视频模式 vs 命令模式。DSI有两种工作模式视频模式像传统的RGB接口一样持续输出像素流命令模式则是通过命令包来更新屏幕内容。对于视频聚合应用通常用视频模式因为延迟低、实现简单。时序参数。DSI的时序包括HSYNC、HVSYNC、HBP、HFP、VBP、VFP等这些参数必须和屏幕的规格书一致。如果参数不对屏幕可能不亮或者显示异常。我一般会先用一个低分辨率、低刷新率的配置把屏幕点亮确认链路通畅后再逐步提高到目标参数。Lane数和速率。DSI的lane数和每lane速率决定了总带宽。以4K30为例总数据率约3840×2160×30×24/8≈746MB/s如果DSI用4 lane每lane速率约1.5Gbps。这个速率下D-PHY的发送端需要做预加重和去偏斜校准确保信号质量。4.3 输出时序约束与调试输出层的时序约束是保证画面稳定的关键。在FPGA里输出像素时钟通常是由MMCM或者PLL生成的需要确保时钟的抖动和相位满足DSI控制器的要求。调试的时候我习惯先用示波器看DSI的差分信号确认HS模式进入和退出正常然后再用逻辑分析仪抓CSI-2或者DSI的包看数据内容是否正确。如果屏幕显示异常先检查时序参数再检查数据格式最后检查物理层信号质量。实操心得MIPI DSI屏幕的初始化序列通常比较长而且不同厂家的屏幕初始化序列差异很大。我一般会把初始化序列做成一个ROM表上电后由状态机逐条发送。这样更换屏幕时只需要改ROM内容不用改逻辑。5. 常见问题与排查技巧实录5.1 多路聚合典型问题速查表问题现象可能原因排查方向解决方法某一路无画面摄像头I2C配置失败读摄像头ID寄存器检查I2C时序和上拉电阻画面横向花屏CSI-2字长解析错误抓包看长包字长字段修正解析逻辑多路同时工作时丢帧DDR带宽不足计算总带宽和DDR有效带宽优化仲裁策略或降低分辨率画面撕裂帧同步未对齐检查各路帧计数器增加帧对齐逻辑输出屏幕不亮DSI时序参数错误对比屏幕规格书修正时序参数随机花屏时序约束未收敛看时序报告修setup/hold violation颜色异常像素格式不匹配检查RAW/YUV/RGB配置统一摄像头和FPGA的格式5.2 独家避坑技巧技巧一先降速再提速。新项目调试时不要一上来就跑最高速率。先把MIPI速率降到最低确认链路通畅后再逐步提高。这样可以把物理层问题和协议层问题分开排查。技巧二用ILA抓关键信号。Xilinx的ILA或者紫光同创的在线逻辑分析仪是调试MIPI聚合的利器。我一般会在CSI-2解析器的输入输出、DDR仲裁器的请求和应答、聚合模块的坐标判断这几个地方埋ILA出问题时一眼就能看出是哪一级出了问题。技巧三DDR带宽留足余量。计算DDR带宽时不要只看理论值要按实际有效带宽的50%来规划。比如DDR3-1600理论12.8GB/s实际按6GB/s来算。这样即使仲裁效率不理想也不会丢帧。技巧四帧缓存地址对齐。DDR的突发传输对地址对齐有要求如果帧缓存的起始地址没有对齐到突发长度的边界第一次传输的效率会很低。我一般会把每帧的起始地址对齐到4KB边界。技巧五输出时序用标准分辨率验证。调试DSI输出时先用720p或者1080p的标准时序把屏幕点亮确认无误后再切到目标分辨率。这样可以排除自定义时序带来的干扰。5.3 工具选型与IP配置建议FPGA平台的选择对MIPI聚合方案的实现难度影响很大。Xilinx Zynq-7000或者Zynq UltraScale系列有成熟的MIPI D-PHY硬核和CSI-2/DSI控制器IP开发效率高但成本也高。紫光同创、安路等国产FPGA近年来在MIPI硬核方面也有不少进展性价比更好适合成本敏感的项目。IP配置方面CSI-2接收控制器一般需要配置lane数、数据类型、虚拟通道数等参数。DSI发送控制器需要配置视频模式、时序参数、lane速率等。这些配置通常通过AXI-Lite接口在运行时写入所以FPGA逻辑里需要有一个配置状态机。DDR控制器IP的配置重点是数据位宽、突发长度、时序参数。数据位宽一般选32位或者64位突发长度选8或者16。时序参数要根据DDR颗粒的规格书来填不能随便抄。6. 实际项目中的经验体会我在多个项目中实现过两路到四路的MIPI视频聚合踩过的坑主要集中在三个方面DDR带宽估算不足、帧同步处理不当、输出时序约束遗漏。DDR带宽这块我现在的习惯是先用一个简单的带宽计算表格把所有路的数据率加起来然后乘以1.5的安全系数再和DDR的实际有效带宽对比。如果余量不到30%我就会考虑降低分辨率或者帧率或者换更快的DDR颗粒。帧同步方面如果各路摄像头的时钟不同源我一般会在DDR缓存里做两级缓冲第一级是每路自己的帧缓存第二级是聚合模块的输入缓存。聚合模块等到所有路的第二级缓存都有一帧完整数据时才开始读取。这样可以避免因为某一路的帧到达时间偏差导致画面撕裂。输出时序约束这块我的经验是不要相信综合工具自动推断的时序约束。DSI的输出时钟、数据线、控制线都需要手动写约束尤其是跨时钟域的信号一定要加set_false_path或者set_max_delay。我见过太多因为约束没写全导致画面随机闪烁的案例。最后分享一个小技巧如果项目允许尽量在FPGA里加一个测试图案生成器。当摄像头或者DDR出问题时可以切换到测试图案快速判断问题是在输入侧还是输出侧。这个功能在调试阶段能省下大量时间。
返回列表