资讯动态

基于FPGA的CameraLink转SFP光口传输设计

发布时间:2026/9/9 10:24:59 来源:尧图企业网站定制
做了这么多年FPGA图像接口CameraLink算是工业相机里最常打交道的接口之一但它有个天生短板传输距离实在有限。普通CameraLink线缆在Base配置下5米以外信号就开始提心吊胆更别说几十米、上百米的场景。这时候最实用的思路就是加一道转换把CameraLink相机信号接入FPGA在FPGA里完成数据打包和高速收发最终通过SFP光口送出去。这样既保留了CameraLink相机的现有投资又能把传输距离一下子拉到几百米甚至几公里。这篇文章就是围绕一个典型的“FPGA实现CameraLink转SFP光口”项目展开的。工程核心是基于Xilinx 7系列FPGA的GT Transceivers Wizard加Aurora 8B10B编解码架构最终形成4套可参考复现的工程源码。我把自己从头到尾的设计思路、IP配置、容易栽的坑、调试方法都整理出来适合正在做图像远传、机器视觉接口转换、或者想上手Aurora协议但不知道怎么跟具体图像格式对接的工程师参考。如果你是想评估方案可行性这篇也能帮你把技术链路里每一处关键决策都弄明白。1. 整体架构与方案选型为什么偏偏是Aurora 8B10B在动手写代码之前最难的部分其实是架构决策。摄像头端是CameraLink远端是SFP光口FPGA夹在中间做翻译。翻译这件事听起来简单但选择哪种高速串行协议直接决定了工程量、延迟、通用性和后续维护成本。1.1 CameraLink的传输瓶颈到底卡在哪先理解一下CameraLink本身。它在物理层用的是Channel Link技术Base配置下就是一组5对LVDS差分线其中1对时钟、4对数据。并行侧是28位数据位加4位同步信号接收芯片比如DS90CR288A把它解串成TTL并行信号给FPGA。像素时钟越高LVDS线速率也越高比如85MHz像素时钟下每对LVDS大约跑595Mbps。问题在于LVDS在普通线缆上的高频衰减很厉害。工业上常用CameraLink线缆做到5到10米已经算不错如果环境有电机、变频器干扰距离还要打折。而很多产线场景相机和控制室之间隔着几十米或者相机装在高架机器人上、处理主机在地面柜子里这时候把CameraLink变成光口是比换GigE相机更省事的选择——相机不用换镜头视角、触发方式、帧率特性全部不变变的只是中间的物理传输层。1.2 为什么用Aurora而不是UDP、PCIe或者SRIO很多朋友一听到“图像远传”第一个想到的是万兆以太网加UDP。但实际上在这个项目里需求是“点对点透明传输CameraLink时序”不是“把图像打包成标准网络包发给任意PC”。如果用UDP需要处理MAC、ARP、IP、UDP校验还要在远端解析重组且每一个环节都对端到端延迟有额外贡献。CPU/ARM参与还得考虑协议栈调度问题。Aurora 8B10B是Xilinx提供的免费点对点链路层协议直接在GT高速收发器上跑。它解决的正是“我不管上面传什么我只负责把一堆字节可靠地从A送到B”这个问题。它的开销非常小8B10B编码自带DC平衡和游程长度控制物理上适合光模块传输而且Xilinx IP核把链路初始化、通道对齐、错误检测都做好了用户接口就是一个带流控的简单总线。你要做的只是把CameraLink的图像数据按时序塞进这个总线另一端再取出来重建时序。在这个场景下SRIO和PCIe也不是不能用但它们的协议更重面向的是多设备寻址、DMA、多通道交换这些复杂特性。点对点传图像属于杀鸡用牛刀而且调试难度和耗时明显更高。1.3 四套工程源码各自解决什么阶段的问题项目标题里写了“提供4套工程源码”这也符合我自己的交付习惯。正常情况下我不会只给一套写完的工程因为一套工程无法覆盖从验证到量产的所有场景。这4套的分工大致是这样第一套用于硬件回环测试不接相机先在FPGA内部产生测试数据发给GT自收自发确认光口物理层、GT配置、SFP模块没有问题。第二套是最小化的CameraLink Base转SFP单向传输工程去掉一切花哨功能透明搬运图像数据和同步信号适合作为方案验证和二次开发的基座。第三套在第二套基础上把图像打包格式做成可配置兼容不同像素位宽、行场同步极性和分辨率方便接不同型号的CameraLink相机。第四套是面向“远端需要一个标准CameraLink Source输出”的完整收发工程把光口接收的数据重新还原成CameraLink并行时序给后端的采集卡或者显示设备使用。这四套是递进关系也是排错隔离的关系。真到了现场出问题先用第一套确认链路再用第二套确认图像最后才去查第三、四套里的配置兼容性问题能省下大量瞎猜的时间。2. CameraLink信号进入FPGA之后数据流设计才是重头戏硬件方案定了IP选型定了很多人会觉得剩下的事情就是把数据从A口搬到B口。但图像数据远传最忌讳的就是把它当成普通字节流直接扔出去。CameraLink不只是像素数据它还有FVAL、LVAL、DVAL三根同步信号。远端要把图像还原成相机时序必须知道每一行从哪里开始、每一帧从哪里开始、像素什么时候有效。2.1 接收芯片后面的并行时序怎么理解以最常见的Base配置为例FPGA从DS90CR288A这类芯片拿到的是pDATA[27:0]、FVAL、LVAL、DVAL、像素时钟。这些信号本质上和相机内部的时序一致。FVAL拉高表示一帧有效LVAL拉高表示一行有效DVAL则根据配置表示数据是否有效有些相机不用DVAL直接用LVAL对齐数据。这里有个细节CameraLink的像素数据不是简单按字节排的。8位、10位、12位、16位像素在pDATA上的位宽映射不一样多tap相机的排列规则更复杂。如果FPGA端尝试“理解”像素排列比如去做Bayer插值、RGB转换就必须处理一堆厂商差异。所以在这个转光口设计里我的原则是不解析语义只搬运时序。FPGA不知道图像是黑白还是彩色也不管像素是10位还是12位它只确保一件事件远端恢复出来的pDATA每一位、每一拍的相对关系和发送端进来的完全一致。2.2 打包格式怎么设计才能做到透明既然要透明就得设计一种打包格式。简单粗暴地把pDATA连续存入FIFO然后让Aurora读走是可以跑的但一旦中间丢了一个字节或者链路重同步远端永远不知道哪里是行头、哪里是帧头图像会彻底花掉且无法自动恢复。我的做法是“行打包”。每当检测到LVAL上升沿开始把这一行有效的像素数据存起来LVAL拉低代表这一行结束之后把这一行数据加上自定义的行头组成一个Aurora帧发送出去。行头里包含帧计数、行计数、该行有效数据长度、以及原始同步信号的极性标志。FVAL本身不需要单独打包行计数为0的那一行就代表新的一帧开始。这样传输链路只关心“帧”不关心“行内数据到底长什么样”目的端的恢复模块根据行头重建FVAL和LVAL即可。8B10B编码本身并不能保证帧边界Aurora协议层能保证字节流可靠传输但不会自己划分“这一坨是一行图像”。所以自定义行头是必须的这也是整个工程里最有价值的设计之一。帧计数和行计数主要用来在远端做连续性校验一旦发现帧号断裂说明链路出现瞬时错误把输出同步信号复位重来避免一直带着错位图像跑下去。2.3 异步FIFO的深度与反压处理CameraLink侧的像素时钟来自接收芯片可能正好是某颗晶振分频出来的而Aurora侧的发送时钟来自于GT的用户时钟两者频率不可能天然一致。所以发送端必须先做异步FIFO隔离输入侧用像素时钟写输出侧用Aurora用户时钟读。FIFO深度要按“峰值积压量”来算。最坏情况是连续几行数据在短时间内涌入但Aurora侧因为链路流控暂时不能读。实际工程里我一般深度做到4096到16384之间宽度做到32位或64位满足Full HD分辨率下的多行缓冲。不推荐把FIFO做到上百KB因为如果出现这种积压说明带宽预算或者反压逻辑根本不合格堆再深也只是掩耳盗铃。反压是另一个容易翻车的地方。Aurora用户接口的发送端有ready信号如果对端还没来得及接收本端就不能继续送数据。但CameraLink是连续时钟不会等FPGA准备好所以FIFO读使能必须由Aurora发送状态机来控制。一旦ready为低立刻停止读FIFO但输入侧还在继续写此时如果FIFO满了就必须丢弃新的像素并拉高一个溢出标志。这个标志一定要引出到LED或者调试寄存器不能悄悄吞掉。3. GT Transceivers Wizard与Aurora IP配置要点工程里用到Xilinx 7系列FPGA就绕不开GT Transceivers Wizard和Aurora 8B10B这两个IP。很多人以为自己只是“调个IP”但这两个IP其实是整个系统里最需要理解物理含义的部分。配置错一个参考时钟频率或者排错GT位置上板后链路死活拉不起来。3.1 线速率和参考时钟怎么选才合适线速率的选取取决于有效数据带宽。CameraLink Base在85MHz像素时钟下并行侧理论带宽大约是85M × 28bit ≈ 2.38Gbps但这是把所有信号位都算进去了。实际图像有效数据率取决于分辨率、帧率、消隐时间。比如1280×102460fps灰度8bit有效像素率大约78.6M pixels/s有效带宽约0.63Gbps加上同步打包、8B10B编码25%开销也要留一定裕量。实际工程里我习惯直接选2.5Gbps或者3.125Gbps。2.5G是很多SFP光模块的舒适区3.125G则对应常见的156.25MHz参考时钟。Aurora 8B10B会在用户接口产生一个用户时钟线速率和用户时钟的关系取决于IP核内部选择的总线宽度常见的是线速率/16或者线速率/32。对应下来2.5G线速率配125MHz参考时钟得到约156.25MHz的用户时钟3.125G线速率配156.25MHz参考时钟得到约195.3125MHz的用户时钟。需要说明的是以上是常见搭配具体数值以IP配置界面实际生成的时钟约束为准。参考时钟必须是GT专用引脚引入不能随意接到普通IO上。很多开发板板载125MHz或者156.25MHz的MGT参考时钟选型时先看原理图确定SFP光模块的GT所在的Bank用了哪一路参考时钟再回过来在GT Wizard和Aurora IP里填对应频率。别想当然地认为开发板上那个SFP一定能用任意参考时钟我在一个板子上见过SFP的GT参考时钟被设计成只能从某个特定Bank输入结果那个Bank被其它接口占用最后只能改板子或者换工程。3.2 Aurora IP核内部选项的坑Aurora 8B10B有两个大方向Streaming接口和Frame接口。Streaming模式下用户侧是一个连续数据流没有帧边界适合纯字节流传输。Frame接口则会识别SOF和EOF对应我们打包模块里的帧起始和帧结束。图像传输我建议选Frame接口虽然多一个TLAST信号需要处理但语义更清晰远端也能明确知道一帧从哪开始。另一个容易忽略的是“Little Endian”和“Flow Control”选项。Aurora协议本身可以配置数据位宽和字节序如果你的发送侧是64位数据总线、接收侧是32位这种不对称设计会让IP核配置复杂很多。我的做法是两端工程保持一致64位就都是64位32位就都是32位宁可多个bit拼接逻辑也不做端到端位宽转换。Flow Control我一般直接关掉。Aurora的流控用于告诉对端“我暂时收不了”但图像传输要求实时性一旦打开了流控并且对端FIFO将满它会插入空闲周期表面看数据不丢实际上延迟发生抖动远端恢复出来的CameraLink时序就会不稳定。正确做法是在应用层配置足够的缓冲确保任何情况下不会因为瞬时带宽抖动丢数据。3.3 复位与初始化时序到底应该怎么处理GT和Aurora初始化有自己的时序要求。7系列GT上电后需要给gt_rxreset、gt_txreset一个适当的脉冲等待pll_lock、txresetdone、rxresetdone拉高。Aurora IP核内部管理了一部分复位但用户侧的reset通常要跟gt_reset_done信号配合。如果直接在Vivado里把reset引脚接到固定高电平或者用一个很短的脉冲硬件回环可能正常但接上光模块后可能一小时都不出一次问题。正确做法是做一个上电复位延时模块在配置完成后延时50到100ms再释放Aurora复位确保SFP光模块的电源稳定。Aurora初始化完成以channel_up信号拉高为准只有channel_up为高之后才能让图像数据进入发送端状态机。在channel_up拉低期间发送端的FIFO最好保持在复位状态避免数据已经读出但并没能送出去导致远端图像缺行。这部分的调试经验是把channel_up、lane_up、gt_pll_lock这些状态信号全部引到ILA或者板上LED。不要只盯着最终的图像链路状态是排错的第一级入口。4. 核心模块怎么拆发送状态机与接收恢复逻辑4套工程源码的代码组织我采用清晰的模块划分方便直接复用。顶层之下CameraLink接收与打包逻辑、Aurora收发Wrapper、远端恢复逻辑、寄存器配置接口各自独立。每个模块之间的接口如果定义得足够干净后续更换FPGA型号或者调整分辨率就是改参数的事。4.1 发送端状态机与自定义行头结构发送端的状态机大概是这样的等待FVAL和LVAL同时有效开始把pDATA写入行缓冲FIFOLVAL拉低后停止写入然后检测Aurora用户接口是否可发送可发送则先发送一个行头再连续发送该行数据。行头的位宽与数据总线对齐例如在64位总线下我会用两个周期发送一个128位的行头。行头里的字段可以划分为帧计数、行计数、数据有效字长、同步极性标志、校验字段。如果用户总线和像素位宽不是整数倍关系还需要在行尾做bit对齐由打包模块完成右填充或左对齐。这里要注意的是LVAL拉低不等于下一行数据不会立刻到来。有些相机的行消隐非常短只有几个像素时钟周期发送状态机必须能在几拍之内完成从“上一行收尾”到“下一行行头开始”的切换。所以我自己不倾向用复杂的AXI DMA搬移方式而是简单的乒乓FIFO一行写入FIFO A的同时状态机正在发送上一行FIFO B里的内容两个FIFO在LVAL边界处互换角色。这样有效避开了“同一块FIFO还在读又不能写”的死锁问题也保证了突发连续性。4.2 接收端如何重建CameraLink时序光口远端拿到的是打包后的数据第一步从Aurora Frame接口恢复出数据帧解析行头验证帧计数和行计数连续然后进入行缓存恢复模块。恢复模块按行头里记录的该行长度把有效数据依次写入输出FIFO。输出侧的同步信号生成逻辑需要产生一个模拟的像素时钟或者直接使用一个相对稳定的本地时钟然后按照行头参数生成LVAL、FVAL。这一段的难点在于“行头里没有绝对时间信息”只有行长度。如果远端本地时钟和发送端像素时钟有微小频差时间一长FIFO会溢出或者读空。实际工程我在恢复侧使用一个可动态调整的FIFO读使能机制当FIFO水位超过半满说明本地时钟慢了下一行的LVAL宽度可以稍微调整一两个时钟周期当FIFO水位低于某个阈值说明本地时钟快了下一行可以插入一个等待周期。这种做法本质上是时钟速率适配严格来说会让恢复的LVAL在极少数时候比原始行长度多或少几个周期但对于普通采集卡和显示器来说完全无感。如果要做到严格精确的时序恢复需要远端用CDR恢复出来的时钟作为像素时钟。这要求相机侧发送的不是纯异步数据而是跟GT参考时钟有一定相位关联。可惜绝大多数CameraLink相机并不同步于FPGA的GT时钟所以实际工程里最稳妥的仍然是“异步FIFO加水位自适应”方案。4.3 回环测试工程怎么测才算有效第一套源码是回环测试工程。它做了两件事内部生成PRBS或者固定递增数据送给Aurora发送数据从光口出去之后再接一根光纤跳线回到同一个SFP模块的接收端Aurora收到的数据送还给校验模块实时比对数据是否一致。这套工程的价值在于把GT物理层、SFP模块、光纤、Aurora链路这些问题先隔离掉。如果回环测试计数一直增长不上来大概率是硬件链路或者IP配置的问题跟图像逻辑无关。实际测试不要只测几分钟最好连续跑12小时以上并让误码计数器清零后不再增长才算稳定。回环测试也可以用光衰减器串在链路中间测试灵敏度这能提前发现SFP模块质量差或者在临界光功率下工作的问题。5. 上板调试实录链路、图像、长时间运行的坑流程走到这里理论上该出图了。但实际调试过程中我几乎没有遇到过“一把过”的情况。这里把最常见的几类问题和排查思路整理出来遇到同样问题的朋友可以直接按顺序查。5.1 channel_up一直拉不高的排查路线如果检查了光模块插紧、光纤跳线正常、电源正常channel_up仍然为低先不要怀疑Aurora IP应该从GT层开始查。第一看gt_pll_lock是否为高如果为低说明GT参考时钟没有进来或者频率配置不对第二看tx_resetdone和rx_resetdone是否拉高如果没拉高多半是GT复位时序不对第三看光模块的RX_LOS信号如果这个信号为高说明接收光功率太低检查光纤是否接反、对端是否有光发出。一个很常见的坑是SFP模块选型。很多千兆SFP模块只支持1.25Gbps你在GT Wizard里配了2.5Gbps模块内部电路并不能工作在这个速率上。有朋友把支持10G的SFP模块插到只提供3.3V电源的普通SFP座子上也可能无法正常工作。选模块前务必查清楚规格书能否支持你选的线速率是不是需要特殊驱动电流。还有一次我遇到的问题非常隐蔽光纤跳线是单模的而SFP模块是多模850nm的单模跳线内芯更细多模模块虽然能发光但接收端无法稳定耦合到多模光纤的纤芯模式导致channel_up反复掉线。换一根多模跳线后问题立刻消失。5.2 图像错位、偏色、边缘有杂色的排查如果channel_up正常但远端采集到的图像左右错位、上下滚动、颜色不对问题最可能在打包或恢复的时序处理上。先说错位。逐行扫描时行头里记录的长度如果和实际像素长度不一致远端恢复就会把行起始位置搞错。排查方法是在相机前放一个明显非对称的测试图比如左边纯白右边纯黑看看图像里黑白的边界是否在预期位置。如果有固定偏移说明行头长度或LVAL边沿识别逻辑有问题如果错位是逐行累加的说明恢复侧丢行或者重复行检查发送状态机的帧计数和行计数。偏色问题一般有两种原因一是发送端的并行数据位序与远端采集端的像素位宽映射不一致比如12位像素时高4位和低8位的排列顺序错了二是同步信号极性配置不正确导致采集端把无效数据当有效数据。排查偏色我通常用ColorBar测试图哪种颜色错乱可以反推出具体是哪个bit翻转。比如绿色通道掉了多半是某根数据位虚焊或者代码位宽拼接错了。5.3 长时间运行后偶发丢帧、花屏的根治办法前面两个问题都算能稳定复现的问题真正难查的是“跑两小时后突然花一帧然后自己恢复”。这种问题大概率出在异步FIFO边界或者误码没有有效纠正上。异步FIFO的读写指针跨时钟域如果处理不好偶尔会出现读到一个尚未写入的无效数据。8B10B编码能检测到线路误码但Aurora协议对于误码的处理如果配置不当可能会让错误数据直接上行。解决思路是在自定义行头里加上CRC或者简单的校验和接收端一旦发现校验错误就丢弃整行并标记帧计数异常由输出恢复状态机在下一帧重新同步。这样偶发的单bit误码不会导致长时间的花屏。链路长时间运行的另一个隐患是GT温度漂移。如果FPGA散热不好GT的RX抖动性能会下降误码率逐步上升。我碰到过一个项目回环测试只测了两个小时没问题上到产线跑八小时后开始冒错。后来加了一个风扇强制风冷并把GT的RX均衡参数从默认值调高一档问题解决。不要忽视FPGA芯片上GT附近的散热设计光模块本身也是发热大户FPGA和SFP紧挨着布局时更要仔细评估热区。6. 四套源码怎么选、怎么快速跑出第一张图帮别人评估这类“FPGA实现CameraLink转SFP”方案时我经常被问到这几套源码我该先看哪个其实答案很简单按顺序来。6.1 四套工程的适用场景和选择建议第一套回环测试工程是最先应该上板的。它和相机无关和图像格式无关只验证FPGA到光模块到光纤到光模块到FPGA这条物理链路。这套工程跑通了后续问题就可以缩小到图像侧逻辑。第二套最小化单向传输工程适合第一次接触这块方案的人它把打包和恢复逻辑做到最简单能帮你建立“图像数据是这样从一侧到另一侧”的完整认知。第三套可配置工程适合要对齐多种相机、多种分辨率的生产环境我会在里面实现了寄存器接口用来配置行长度、行头模式、同步极性、数据位宽拼接方式。第四套完整收发工程则是面向最终产品形态的远端需要重建标准CameraLink Source并行时序时用它加入了输出时钟管理与自适应FIFO逻辑。在实际项目里我的推进路线一定是从第一套开始确认硬件链路后在第二套基础上改到需要的分辨率和帧率然后切到第三套做参数配置最终固化到第四套作为交付。不要一上来就抱着第四套工程调试代码层次越多问题越难定位。6.2 上板后的快速验证步骤拿到源码后我建议的验证步骤是第一步Vivado里检查工程用的FPGA型号和板卡是否一致不一致先改器件并重新完成综合布局布线别急着上板第二步核对引脚约束文件里的GT位置、参考时钟引脚、CameraLink并行接口引脚尤其是差分信号正负极性不能反第三步烧录第一套回环工程打开串口或者ILA观察误码计数是否一直为零第四步回环通过后烧录第二套工程接上CameraLink相机先确认近端侧能正确解析到FVAL和LVAL再插光纤看远端能否出图第五步长稳测试至少跑4小时以上同时人为拔插光纤几次观察恢复机制是否能自动重新拉高链路和恢复图像流。光模块的线缆也很关键。SFP插座有的带锁扣有的不带插拔光纤时不要拉线身要捏住接头拔出。光纤端面脏污是工业现场最常见的隐性故障如果遇到衰耗大、偶发误码先用光纤清洁笔擦一下再试。6.3 想要继续扩展可以在哪里动刀这套架构最大的扩展价值在于图像数据到达FPGA之后天然可以做各种处理。目前工程源码里如果只做“转光口”其实浪费了FPGA算力。你可以很自然地在CameraLink接收之后、Aurora发送之前插入一行处理流水线比如Bayer转RGB、自动白平衡、ROI裁剪、帧率降低、图像压缩等。因为我前面自定义行头是数据不透明传输一旦在FPGA内部修改了像素内容或行长度只需要同步修改行头里的长度字段即可。如果后端需要的是GigE Vision或者UDP数据包也可以把Aurora发送替换成Xilinx 1G/2.5G Ethernet MAC加UDP/IP封装SFP光口物理层仍然复用GT。这个扩展方向在需要把相机直接接入PC网络时很有用只是工程量和复杂度比Aurora方案高一个量级建议在Aurora方案稳定跑通之后再做。从个人实操角度讲这类接口转换项目成败的关键不在于哪个IP配得高深而在于你把链路分层、把时序边界、把异常恢复机制理解到什么程度。我自己最深的体会是先做一套回环工程再谈图像传输这句话能帮你省掉至少一周的无效调试。另一个小建议是在行头里多放几个调试计数器比如总行数、总帧数、误码行数这些留在远端采集端非常有用比事后接ILA看波形高效得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价