拓冰建站拓冰建站
首页 / 资讯中心 / 正文

FPGA图像传输:CameraLink转SFP光口基于Aurora 8B10B的完整工程实践

做FPGA图像传输的同行估计都遇到过CameraLink转光口这种需求。相机端是CameraLink接口但传输距离一超过三五米CameraLink线缆就开始拖后腿要么信号衰减要么被工业现场的电磁干扰搞得出图花屏。换光纤是最省心的方案但光口这边怎么跟FPGA对接很多刚从摄像头一头扎进来的朋友会纠结是用GT Transceivers Wizard把SerDes裸调出来还是直接用Xilinx现成的Aurora 8B10B协议栈我跟你们说如果你是做项目交付而不是写论文直接上Aurora这是把GTX/GTH收发器用得最稳、最快、最不折腾人的路径。这篇文章基于我最近整理的一套CameraLink转SFP光口完整工程来写硬件平台覆盖Kintex-7和Artix-7提供4套不同侧重的源码工程全部基于Xilinx GT Transceivers Wizard Aurora 8B10B架构。写出来主要是给两类人看一类是从未碰过高速串行接口、对GTX和Aurora一头雾水的FPGA新手另一类是已经调过SDI或者PCIe、但第一次做相机接口转光纤这种具体场景的老手。看完至少能明白架构怎么搭、IP怎么配、上板后出现光口不通时先查哪里少走我当年走过的弯路。1. 整体架构与方案选型思路1.1 CameraLink转光口本质上在解决什么问题CameraLink接口在机器视觉领域用得非常多它的特点是协议简单、实时性强但有个天然短板传输距离短。标准CameraLink线缆推荐长度在3米以内用好的线缆加放大器也很难超过10米。工业现场一需要长距离传输光纤就成了最合理的替代方案——光纤本身传输几公里都没问题而且不受电磁干扰。所以这套系统的任务可以拆成三句话把CameraLink接口芯片送进来的并行图像数据接进FPGAFPGA把它们打包成适合高速串行链路传输的格式再通过SFP光模块发出去接收端反过来做解包恢复出和发送端一模一样的图像时序。为完成这个闭环板上链路是相机 → CameraLink线缆 → 接口芯片DS90CR288A等→ FPGA并行侧GTX高速侧→ SFP光模块 → 光纤 → 对端FPGA系统。FPGA在中间扮演的角色就像一个同时精通并行慢速协议和高速串行协议的双语翻译官。CameraLink侧是随路时钟并行数据SFP侧是高速差分串行信号两边速度、时序模型完全不同FPGA的任务就是把两边桥接起来。1.2 时钟架构与数据流设计整套系统里最容易被忽略、但最决定成败的是时钟架构。CameraLink接口芯片输出的像素时钟是跟随图像数据一起过来的这个时钟必须作为FPGA内部并行数据采集的参考。而GTX高速收发器侧需要一对独立的参考时钟通常由板上的可编程晶振或者固定频率晶振提供。我在这套工程里的做法是CameraLink像素时钟经IBUFDS原语转换成单端时钟作为图像采集模块的工作时钟GTX参考时钟用板上专用差分参考时钟经过IBUFDS_GTE2原语接到GT Transceivers Wizard的参考时钟输入。两边时钟域之间用异步FIFO做缓冲隔离。数据流则是并行图像数据 → 行列有效信号解析 → 数据同步与打包 → 异步FIFO → Aurora发送接口 → GTX → SFP光模块。接收路径完全对称。这个架构没有用DDR缓存不需要帧存所以端到端延迟只取决于异步FIFO深度和Aurora链路自身的延迟实测在几十微秒量级完全满足工业实时传输的需求。1.3 为什么不用GT Transceivers Wizard裸调非要加一层Aurora这是我在网上被问得最多的一个问题很多朋友觉得Aurora IP是多余的直接用GT Transceivers Wizard把GTX配置成自定义协议不就行了理论上确实可以但实际工程中你会立刻遇到几个麻烦要自己处理8B/10B编解码、要自己设计通道对齐机制、要自己实现时钟补偿、还要自己写错误重传逻辑。这些工作不是不能做但每一块都是大坑全部踩完没有个把月出不来。Aurora 8B10B协议是Xilinx免费提供的轻量级高速串行链路协议它在GTX/GTH之上帮你把链路初始化、通道绑定、时钟补偿、错误检测这些脏活全干了。对图像传输这种期望无损、低延迟、不丢帧的场景来说Aurora的streaming接口封装得很干净你只管往接口里塞数据对端按顺序收数据不用关心底层是怎么对齐的。我见过太多人在自研高速串行协议上耗了大半年最后性能还不如Aurora稳定这时间砸进去真不划算。选Aurora还有一个重要原因——图像传输讲究确定性。Aurora链路上没有以太网的冲突重传也没有PCIe的分包仲裁稳定建立链接之后就是纯数据管道。这跟CameraLink本身的传输特性是吻合的两边都是流式数据不需要复杂事务层协议所以Aurora几乎是这个场景的最优解。2. GT Transceivers Wizard与Aurora 8B10B核的配置要点2.1 GTX与GTH怎么选7系列FPGA的高速收发器分为GTP、GTX、GTH、GTZ等几档。Artix-7上的叫GTPKintex-7和Virtex-7上是GTXVirtex-7还有GTH。这里有个常见的坑很多人在Artix-7上按照Kintex-7的配置去跑高速率结果发现跑不上去。做CameraLink转光口速率需求通常在2.5Gbps到5Gbps之间。这个区间内GTP和GTX都能胜任但GTP最高线速率只有3.75Gbps而GTX能跑到12.5Gbps。所以方案选型时如果你打算用3.125Gbps或更高线速率老老实实用Kintex-7或Virtex-7Artix-7只有在2.5Gbps及以下时才稳。我这套4个工程里专门做了一个Artix-7平台的低速率版本就是考虑很多低成本项目用Artix-7搭配2.5Gbps速率性价比最高。2.2 GT Transceivers Wizard关键参数配置GT Transceivers Wizard是Xilinx提供的图形化配置工具本质上是帮你生成GTX/GTH收发器的例化代码和约束。打开IP核配置界面一眼看去全是选项关键的就那么几个线速率Line Rate。这个参数决定了SFP光口跑多快不是随便填的。要倒推CameraLink Base配置最大像素时钟85MHz数据位宽16bit两个8bit像素峰值带宽约1.36Gbps加上8B/10B编码的20%开销理论最低线速率约为1.7Gbps。所以2.5Gbps标称速率扣掉开销后有效带宽2.0Gbps余量足够。如果将来想扩展更多的数据位宽或灰度等级用3.125Gbps更宽裕。我给的4套工程里分别用了2.5Gbps和3.125Gbps两种配置方便你对号入座。参考时钟REFCLK。GTX的参考时钟频率必须跟线速率匹配常见组合是2.5Gbps配125MHz3.125Gbps配156.25MHz或125MHz。这个不是你想配多少就配多少的取决于GTX内部的PLL分频比。如果板上晶振频率跟你想要的不一致必须改线速率或者换晶振否则PLL永远锁不住。我踩过的最大坑就在这以前板子上放了一个200MHz的晶振结果想要的线速率一时对不上最后不得不调整线速率去迁就晶振。协议模板Protocol Template。GT Wizard里面自带一个Aurora 8B10B的模板选择后会自动帮你把编解码、极性控制等参数配好。强烈建议选这个模板而不是从头自己配因为Aurora核与GTX核之间有大量共享信号的连接要求一旦某个信号接口名对不上综合报错能让你排查到怀疑人生。时钟架构Clock Architecture。图像传输场景建议选独立参考时钟模式也就是TX和RX共用同一个参考时钟。因为CameraLink转光口是单向视频流为主不需要支持环回时钟这种花活共用参考时钟可以让链路初始化逻辑更简单调试时少一层变量。2.3 Aurora 8B10B核配置Aurora IP核配置界面比GT Wizard简单得多但它有几个选项直接决定工程成败。首先是链路配置有1条lane到多条lane可选。CameraLink Base模式下数据量不大1条lane足够。CameraLink Full或Deca模式80bit数据就得考虑2条或4条lane并行传输。注意Aurora多lane通道绑定依赖GTX的通道对齐机制lane数越多对布线等长要求越高我这套工程里Full配置的板子对差分线做了严格的长度匹配如果你自己画板这一点一定要跟PCB工程师强调。其次是接口模式有Framing和Streaming两种。Framing模式带帧头帧尾信号适合传输有明确帧结构的数据比如把一整幅图像当作一个帧Streaming模式是纯数据流没有帧概念。做图像传输我的习惯是选Streaming为什么因为CameraLink本身已经有行有效和帧有效信号了帧的边界自己心里有数不需要Aurora再包一层帧格式白白增加开销。但如果你希望接收端完全不关心图像格式、只从数据流里恢复时序也可以选Framing各有利弊。第三是流控Flow Control。Aurora核提供了用户流控和原生流控选项。图像传输端到端是固定码率数据量相对稳定理论上不需要流控但考虑到异步FIFO可能溢出我强烈建议开启原生流控Native Flow Control。万一接收端FIFO快满了对端可以通过链路层的流控帧反向通知发送端暂停这样就不会丢数据。2.4 工程源码的组织结构这套资源一共4套工程全部基于Xilinx Vivado开发每套都是独立的、可直接综合上板的完整工程。它们分别是第一套标准Base配置工程目标芯片Kintex-7线速率3.125Gbps单laneCameraLink Base模式带完整的图像采集、数据打包、Aurora收发、接收端图像时序恢复模块。这套是主力工程适用于绝大多数单相机远距离传输项目。第二套Artix-7低成本工程目标芯片Artix-7线速率2.5Gbps单laneCameraLink Base模式。这套工程逻辑设计跟第一套基本一致但针对A7的资源做了精简去掉了部分调试逻辑节约LE和BRAM资源。适合预算敏感、对图像分辨率要求不是极高的项目。第三套Full配置工程目标芯片Kintex-7线速率5.0Gbps双laneCameraLink Full模式对应80bit图像数据。这套是给高分辨率、高帧率相机用的比如2048×2048100fps以上的场景单lane带宽扛不住必须双lane甚至四lane并行。第四套验证与测试工程带有伪随机图案发生器和CRC校验模块可以脱离CameraLink相机独立运行。上电后FPGA自己生成测试图像通过光口发送再环回校验用于验证光模块、光纤、GTX链路是否正常。这个工程在调试时价值极大强烈建议你先跑通这套再上相机。每套工程都包含Vivado工程文件、源码和约束文件。源码部分拆分为CameraLink采集模块、数据转换/打包模块、Aurora收发模块、接收端时序恢复模块模块间接口对齐方便你在自己的板子上移植。3. 核心链路实现从CameraLink到Aurora的完整数据通路3.1 CameraLink接口芯片侧的数据采集CameraLink物理层由4对Base配置或8对Full配置LVDS数据线加一对LVDS时钟线组成。FPGA一般不直接接收LVDS信号而是通过接口芯片如DS90CR288A把LVDS差分信号转换成28bit并行TTL数据加一个像素时钟。数据采集模块的输入信号通常是pixel_clk像素时钟data[27:0]28bit并行图像数据其中包含4bit图像数据使能信号FVAL、LVAL、DVAL、SPARE和24bit图像数据FVAL是帧有效、LVAL是行有效在实际代码里用像素时钟打拍采样即可需要留意的是CameraLink的时序是随路时钟同步的理论上不存在跨时钟域问题但为了抗干扰最好做一次双寄存器同步再进逻辑。我在这套工程里用了一个简单的打拍模块第一拍pixel_clk上升沿采样外部输入第二拍做同步后的数据供内部逻辑使用。 数据采集完成之后把FVAL与LVAL作为控制信号把24bit图像数据拆成两个16bit像素流输入后端FIFO。这里有个细节值得说很多相机的CameraLink输出支持2tap甚至4tap模式也就是一个像素时钟同时输出2个或4个像素。我在工程里把这种多tap情况考虑了进来通过参数配置可以选择1tap或2tap模式默认按1tap传输接口留了扩展位。这么做是给分辨率升级留了余地换相机时不用改架构。3.2 图像数据打包与异步FIFO缓冲从CameraLink侧过来的图像数据是像素时钟域的数据而Aurora侧工作在用户时钟域通常等于线速率除以整数因子两个时钟频率和相位没有任何关系所以中间必须通过异步FIFO做跨时钟域缓冲。数据宽度设计上我在发送端把24bit RGB图像数据转成16bit灰度或24bit RGB透传两种模式用参数配置。灰度模式节省带宽可以把线速率降一级RGB模式保真度高但带宽需求翻倍。异步FIFO的读写端宽度都统一为32bit每次写入打包好的数据字其中高16bit是图像数据低16bit是控制信息包括行号、帧号、数据有效标志。为什么要把控制信息一起打包进FIFO因为接收端恢复时序时不能只靠FVAL和LVAL信号重建时序还要知道当前是哪一行、哪一帧。如果两端行号不同步光口传输过程中一旦丢过数据接收端画面会整体偏移。打包时可以顺带计算每一行的CRC校验值接收端逐行校验一旦发现校验错误就能立刻报警或者请求重传这对要求可靠传输的工业场景非常实用。这个32bit打包格式在双lane模式下会扩展为64bit两个lane各占32bit。多lane数据分配方式是把同一行的像素按奇偶序号分到两个lane里接收端再按序号合并回原始顺序。这个方案在实现上远比按行分配简单因为不需要在接收端缓存完整一行再做行拼接。3.3 Aurora接口的握手机制与数据注入Aurora 8B10B核的Streaming接口发送侧只有三个关键信号s_axi_tx_tdata、s_axi_tx_tvalid、s_axi_tx_tready。tvalid拉高且tready为高时tdata上的数据才算真正被发送出去。接收侧对应是m_axi_rx_tdata、m_axi_rx_tvalid。实际操作中最容易出错的是tvalid和tready的握手逻辑。很多初学Aurora的朋友直接把FIFO读出的数据往tdata上一扔然后tvalid一直拉高结果数据丢得莫名其妙。正确做法是FIFO空时tvalid拉低FIFO非空时tvalid拉高同时要检测tready只有tvalid和tready同时为高时才从FIFO里读走下一个数据。这是一个标准的AXI4-Stream握手机制不能把它当成简单的使能信号。链路初始化时序也要注意。Aurora核在复位释放后需要一段时间完成通道对齐和初始化通常会拉低channel_up信号。在channel_up拉高之前绝不能向Aurora接口写任何数据否则这些数据会直接丢失而且不报错。工程里的发送状态机逻辑是等待channel_up拉高然后拉高FIFO读使能开始把缓存的数据打到链路上。注意这里有个隐含设计因为初始化完成后FIFO里可能已经积压了几行图像数据为了保证实时性我做了先到先发的透传策略没有等整帧对齐再发所以端到端延迟保持得很低。3.4 接收端图像时序恢复光口对端接收不止是把Aurora数据读出来还要把图像时序完整地重建出来。接收端拿到FIFO数据后解析出控制信息里的帧号、行号和数据然后通过状态机产生新的FVAL、LVAL、DVALID信号和标准的CameraLink输出时序对齐再送给后端的显示、采集或者存储模块。时序恢复的关键在于行同步。CameraLink的行时序不是等间隔的行消隐期长度可能随相机不同而变化。如果接收端只是简单按像素计数来产生LVAL必然会出现行长度漂移。所以我用行号作为同步基准每收到新的一行数据就用该行的行号刷新内部行计数器同时用帧号刷新帧计数器然后严格按行号对应的LVAL区间来拉高LVAL信号。实测下来这种方案无论在连续采集还是启停模式下都能保持输出时序稳定。接收端还要处理一个状况就是上电时发送端已经开始发数据了接收端从任意时刻接入链路可能拿到半行数据。我做的处理是接收端必须以帧号变化为起点开始输出完整帧半行数据主动丢弃等下一帧从帧头开始输出。这样的做法牺牲了一帧首帧的显示但保证了后续输出绝对完整直播类应用可以接受。4. 工程调试经验我从这套板子上踩过的坑4.1 光模块不发光的问题排查上电调试第一步不是看逻辑波形而是先用光功率计或者直接看光模块的发光指示灯确认SFP光模块有没有光出来。如果发现没光先查硬件光模块的TX_DISABLE引脚有没有被拉高很多光模块的TX_DISABLE是默认拉高禁用的FPGA侧需要主动拉低才能让激光器发光。这个细节害过我一次。当时固件加载正常、FPGA配置成功、GTX复位完成但链路就是起不来折腾了一下午最后拿万用表一量发现板子上光模块的TX_DISABLE被一个上拉电阻拉高了而FPGA的配置管脚没有覆写这个信号。把对应的FPGA引脚配置为输出低电平后光模块立刻有光了链路也起来了。4.2 GTX PLL锁不住反省时钟另一个高频问题是GTX的TX/RX PLL的locked信号一直不拉高。这通常不是逻辑问题而是参考时钟频率不对或者质量不行。用vivado里的IBERT工具可以快速验证GTX能不能正常环回如果IBERT也锁不住那就是硬件层面的问题。我之前遇到过一块批次的板子GTX参考时钟的差分走线过孔打得不好导致信号质量差PLL偶尔能锁偶尔锁不住表现出来就是链路时好时坏、上电成功率和温度强相关。最后在PCB上做了微调换了一版板子才彻底解决。所以如果链路不稳定且有规律性建议优先怀疑参考时钟的信号完整性用示波器看参考时钟的眼图一看就明白。4.3 Aurora通道初始化超时Aurora核的channel_up信号迟迟不拉高也是常见问题。这里有两种情况发送端和接收端的线速率不一致或者两端参数配置不一致。Aurora协议在初始化时会对lane进行速率协商和通道绑定如果两端的GT配置不同它们会一直收不到相互的对齐序列表现为channel_up永远为低。我遇到过一种更隐蔽的情况发送端和接收端用的Aurora核版本不同比如Vivado 2018.3和2021.1生成的IP核8B/10B编码本身是兼容的但初始化状态机的时序细节有差异导致偶尔能握手偶尔不能。遇到这种问题最稳妥的办法是统一Vivado版本重新生成两端的Aurora核不要混用。4.4 图像出现行偏移或者撕裂如果链路通了、图像也能看到但有行偏移或者画面撕裂基本可以确定是接收端的行同步逻辑和数据缓存策略出了问题。我建议优先检查异步FIFO的读指针和写指针是否对齐。图像传输场景里异步FIFO的深度至少应该能容纳2行以上的数据否则在行消隐期间来不及排空就容易出现数据覆盖。有一种典型情况是CameraLink的LVAL在高分辨率模式下消隐期特别长而Aurora链路跑得很快FIFO在消隐期内被读空下一行数据还没到接收端就拉低LVAL造成行延迟不一致。解决办法是把FIFO深度加大到4行甚至8行同时在接收端增加一个FIFO水位检测水位低于阈值时主动延长当前行的LVAL等数据够了再继续输出下一行。这个弹性行设计能让接收端在数据不均匀到达时也不会撕裂画面。4.5 调试时必备的ILA抓信号顺序用Vivado的ILA调试这套系统抓信号的顺序很重要。我的习惯是从发送端开始先看GTX的tx_reset_done有没有拉高然后看Aurora的channel_up再看发送侧FIFO的empty信号和读使能最后看s_axi_tx_tvalid和s_axi_tx_tready的握手。如果握手频次正常说明发送端没问题。然后把ILA挪到接收端按同样顺序从后往前查。这种从发送端到接收端、从物理层到协议层再到应用层的排查思路比随机抓波形高效得多。建议调试时先在仿真环境跑通Aurora回环测试再上板调光口。仿真时可以人为注入错误数据、拉高错误标志验证错误处理逻辑上板跑真实的图像数据后再逐步加入CRC校验和错误统计模块实时监控链路质量。5. 总结与经验补充做这套工程的过程中我最深的一个体会是CameraLink转光口这类项目技术难度其实不在于某个模块有多复杂而在于你能否把并行域的时序逻辑和高速串行域协议栈在同一个工程里协调好。很多时候问题不是不出的功能而是常常被忽略的细节——参考时钟频率匹配、光模块控制脚、复位时序、FIFO深度——这些点任何一个没处理好都会让你在调试阶段耗费大量时间。给新手朋友的直接建议上手这套工程时请严格按照以下顺序操作先跑通第四套测试工程确认光链路质量再把第四套工程换成发送端应用接上CameraLink信号测试数据采集是否正确最后搭接收端验证时序恢复。每走一步都把这一级的ILA波形留下存档这样一旦后面出问题能迅速定位是哪一级引入了错误。工程源码的资源包里我也放了一份调试截图和实际波形是我在做验证板时留下的包含了GTX复位时序、Aurora channel_up建立过程、图像数据通过FIFO握手传输的完整波形以及接收端恢复出图像行场信号的实测截图。这些一手资料比纯粹的文字说明直观得多参考价值很高。做FPGA这行多一个能稳定跑的工程模板就少一个通宵调板的夜晚。希望这套基于Aurora 8B10B的CameraLink转光口设计真能帮你把项目周期压缩下来把时间花在更有价值的事情上。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门