资讯动态

FPGA CameraLink转SFP光口传输方案:基于GTX与Aurora 8B10B的完整实现

发布时间:2026/9/8 7:03:40 来源:尧图企业网站定制
做FPGA图像传输的兄弟应该都被CameraLink这种接口折磨过。线又粗、距离又短、接线麻烦到了现场动不动就要拉几十米铜缆方案根本扛不住。我前阵子刚好给客户落地了一个需求把CameraLink相机的图像通过SFP光口长距离传输到后端平台。整个项目基于Xilinx FPGA的GT Transceivers Wizard和Aurora 8B10B架构来做配套做了4套递进式工程源码本文把这套方案从选型、架构、代码模块到调试踩坑完整梳理一遍给正在做FPGA光口收发、CameraLink图像采集、或者准备接触GTX高速串行接口的工程师一个可以直接参考的落地样本。这个项目能解决的问题很明确CameraLink接口相机在医疗、工业检测、安防监控里非常常见但CameraLink线缆一般只能跑5米以内超过这个距离信号质量直线下降而SFP光口加光纤可以轻松跑到几百米甚至几十公里同时天然隔离地环路抗干扰能力强很多。内容适合三类读者一是刚接触GT Transceivers、Aurora协议的新手可以把它当成一份完整的学习案例二是正在做图像传输类FPGA项目的工程师可以直接复用工程的模块划分和IP配置参数三是项目选型阶段的技术负责人可以参考文中的方案对比数据判断“CameraLink转SFP”到底该怎么转。1. 为什么做CameraLink转光口场景痛点与方案选型对比1.1 CameraLink接口的定位与局限CameraLink是AIIA制定的工业相机标准接口本质上是基于Channel Link技术的LVDS串行传输。常见的Base配置用4对LVDS数据线加1对时钟线把28位并行数据24位图像数据加4位控制信号串行化传输像素时钟最高85MHz时链路总数据率约为2.38Gbps。这个带宽在几年前够用现在高分辨率高帧率的相机越来越多带宽压力就显出来了。比带宽更头疼的是传输距离。CameraLink标准线缆在85MHz像素时钟下一般只能保证5米以内可靠传输就算用高质量的线超过10米后LVDS信号衰减、抖动、串扰问题都会暴露出来。很多工业现场相机和采集卡之间隔着一堵墙甚至一条产线根本没法用CameraLink直接拉。换CameraLink的线缆中继器那是纯模拟放大对噪声和抖动的改善非常有限而且中继器本身也是成本。还有一点容易被人忽略CameraLink接口芯片的差分信号对PCB布局要求很高尤其在FPGA板卡上如果LVDS走线没有做等长、没有控制阻抗波形质量会很难看。我自己就见过一块板子因为CameraLink走线差导致图像间歇性花屏查了三天最后发现是走线stub太长。所以对这个接口来说物理层可靠性本身就是个坎。1.2 三种主流转换方案的横向对比CameraLink转光口市面上的做法大致有三种我做个表格对比大家选型时可以直接参考。方案核心器件带宽能力延迟开发成本灵活性专用转换器现成CameraLink转光纤盒子取决于盒子规格通常支持Base/Medium中等最低即插即用极低只能做固定格式透传CameraLink采集卡FPGA板PCIe采集卡加独立光口模块高但需要上位机参与转发较高高涉及PC和驱动中等FPGA直接转FPGACameraLink接口芯片SFP光模块高可扩展到多路低纯硬件链路中等偏高最高协议、格式全可控第一种专用转换器适合快速交付、不差钱的场景但有个致命问题它是封闭的转换后的光纤数据格式往往是私有协议后端如果想直接接到另一个FPGA或者定制的图像处理板基本无法对接。第二种适合已有PC采集链路的老项目改造但延迟高实时性要求高的场合不合适。我最终选择第三种用FPGA做CameraLink到SFP光口的直接转换核心原因有两个一是延迟可以压到微秒级整个链路不需要操作系统参与二是数据格式完全透明光口出去的数据可以直接被其他Aurora设备接收后续想加图像处理、加DDR缓存、扩展多路采集都是顺理成章的事情。1.3 为什么最终选择GT Transceivers Aurora8B10B确定了用FPGA之后下一个问题是高速串行接口怎么实现。SFP光模块的数据接口是高速差分对FPGA内部必须用高速收发器Xilinx叫GT Transceiver包括GTP、GTX、GTH这几代去驱动这个没得选。但在GT之上跑什么协议有几种路线自己写8B10B编解码、用Xilinx的Aurora IP、甚至直接怼10G Ethernet MAC。自己写8B10B编解码是最劝退的选项。8B10B编码要做字节对齐、K码检测、跑偏纠正、时钟补偿还要考虑上电后的链路初始化握手代码量大且容易出边界问题。我见过有人用Verilog硬写了一个简化的8B10B链路单板测试能通但两台设备互联时偶尔会莫名丢字节排查起来非常痛苦。GT Transceivers Wizard加上Aurora 8B10B IP的组合相当于是把物理层和链路层都给你封装好了你只需要关注用户数据接口。Aurora协议是Xilinx提供的轻量级透明传输协议没有MAC层没有TCP/IP那套繁重头延迟很低非常适合图像这种“大批量、流式、点对点”的传输场景。选Aurora 8B10B而不是Aurora 64B66B是因为CameraLink Base模式2.38Gbps的链路速率在8B10B的带宽范围内同时8B10B版本IP更成熟、对GTX/GTH支持更稳定时钟方案也简单。64B66B适合更高带宽但对应的用户时钟和参考时钟规划会复杂一些对这个项目来说是杀鸡用牛刀。2. 链路架构拆解从CameraLink入到SFP出2.1 整条数据链路怎么走先看整条链路的宏观数据流我按信号走向列一下CameraLink相机通过MDR 26针接口输出LVDS差分对板上的CameraLink接口芯片比如DS90CR288A完成LVDS解串输出28位并行数据和像素时钟PCLK到FPGA引脚FPGA内部把28位数据按自定义帧格式打包通过异步FIFO跨越像素时钟域和Aurora用户时钟域GT Transceivers Wizard实例化GTX/GTH收发器将并行数据编码成高速串行差分对差分对连接到SFP光模块的TX/RX引脚光模块完成电光转换光纤把信号送出去。这里要注意一个关键点CameraLink接口芯片输出的PCLK和Aurora IP的用户时钟是两个完全独立的时钟域不能直接相连。PCLK由相机决定Aurora用户时钟由GT参考时钟和线速率决定两者的频率和相位没有关系。跨时钟域处理必须用异步FIFO而且FIFO深度要按照带宽余量来算这个我后面实操章节会详细展开。2.2 CameraLink接口芯片怎么选、怎么接CameraLink物理层解串芯片最常见的是TI的DS90CR288A/DS90CR288B输入4对LVDS数据加1对LVDS时钟输出28位并行数据和1个像素时钟。还有个配套的发送端芯片DS90CR287如果你的链路还包括“接收光口数据然后转回CameraLink给显示器”这种反向业务那就要加上它。这个项目主要做单向图像采集上传所以FPGA这边只用了接收端288A。芯片选型上要注意的点DS90CR288A供电有3.3V版本LVDS输入需要100欧终端电阻匹配PCB上电阻要尽量靠近芯片引脚PCLK输出频率等于相机的像素时钟常见的是25MHz到85MHz28位并行输出的映射关系必须查数据手册因为它不是简单地把4路LVDS逐位展开而是有固定的bit排列顺序接错线会导致图像颜色通道互换或者像素错位。另外DS90CR288A的LVDS输入共模电压范围有限CameraLink线缆长度不能过长。我建议板卡设计时在芯片输入端预留交流耦合位置如果现场条件差可以直接改耦合方式多一手准备总没坏处。2.3 SFP光模块侧设计与GTX关键配置SFP光模块的电气接口比较简单电源3.3V数据接口就是一对TX差分和一对RX差分另外有TX_FAULT、LOS、TX_DISABLE、MOD_DEF0/1/2等管理引脚。GTX/GTH收发器的TXP/TXN差分对直接连到SFP的TD/TD-RXP/RXN连到RD/RD-即可。GT Transceivers Wizard配置时最核心的两项是线速率和参考时钟。针对CameraLink Base模式我上面算过链路总数据率是2.38GbpsAurora 8B10B编码有25%开销所以GT线速率至少要大于2.38/0.82.975Gbps。标准线速率选型里3.125Gbps是最合适的既满足带宽需求又在GTX的最佳工作区间内。如果选2.5Gbps线速率有效带宽只有2.0Gbps跑60fps 2048x2048的8位图像时大概率会丢帧这个是最容易踩的坑。参考时钟的选择要和线速率匹配。对于GTX3.125Gbps的线速率建议用125MHz参考时钟QPLL倍频后生成串行时钟如果参考时钟不是整数倍关系Vivado会直接报配置错误。另外GT参考时钟所在的bank要和实际PCB走线一致不能例化IP时随便选一个否则上板后GTX完全锁定不了。2.4 Aurora 8B10B IP在链路里的角色Aurora 8B10B IP在Xilinx FPGA里的定位是一个免费提供的串行链路层协议IP内部自动例化GT Transceivers Wizard生成的收发器对外提供用户接口通常是AXI4-Stream和链路状态接口。它负责的事情包括上电后自动完成GTX初始化、时钟对齐、通道绑定发送端把用户数据字节流转换成Aurora帧格式加上适当的K码用于对齐接收端完成字节同步、通道对齐、数据恢复把有效数据解出来送给用户逻辑链路出错时上报Hard Error、Soft Error状态支持错误恢复。Aurora 8B10B有两种接口模式Streaming和Framing。Streaming模式最简单把数据连续推给IP就行IP内部自动打包适合这种图像流传输Framing模式需要自己定义帧头帧尾适合需要按帧边界传递控制信息的场景。这个项目里图像本身就是连续的像素流用Streaming模式就够了省掉了一堆帧管理逻辑。有一个细节要提醒Aurora IP的用户接口位宽是配置时确定的常见32位。线速率3.125Gbps、8B10B有效带宽2.5Gbps32位用户接口对应的用户时钟就是2.5G/3278.125MHz。你后续做FIFO读写位宽匹配时要严格按照这个78.125MHz来规划不能想当然用80MHz或者75MHz否则长期运行后会偶发溢出或者读空。3. 四套工程源码的分工与设计思路3.1 四套工程的整体规划拿到一个FPGA高速接口项目我最忌讳的就是一上来直接写完整逻辑然后一次上板调通。GTX和Aurora本身就要分阶段调试CameraLink数据帧格式也需要逐步验证所以我把整个项目拆成了4套工程从简到繁每套工程都是前一套的增量迭代。我建议你也按这个思路来管理自己的项目真的能省掉大量联调时间。工程编号工程内容核心验证目标工程1CameraLink接收 Aurora光口发送验证CameraLink解串、数据打包、GTX发送链路工程2光口回环自测 误码统计验证GTX物理层可靠性和Aurora链路稳定性工程3增加BMP图片抓帧与PC端显示验证图像数据格式正确性、上位机对接工程4增加DDR3缓存 多帧连续传输验证突发带宽、跨时钟域大缓存和长时间稳定性3.2 工程1CameraLink接收 光口发送工程1是整个方案的骨架只做一件事把CameraLink相机进来的数据送到光口发出去。模块划分上包括顶层的camlink_to_sfp_top下面挂了cam_link_rxDS90CR288A数据采集、frame_pack把28位并行数据转成32位对齐的传输格式、async_fifo_32x1024跨时钟域、aurora_8b10b_0Xilinx IP、以及一个最简的sfp_ctrl模块用于控制SFP的TX_DISABLE和读取LOS状态。frame_pack这段逻辑看起来简单但很容易出错。CameraLink输出的28位是24位图像数据加4位控制信号图像数据如果是8位RGB那么三个颜色通道必须按固定顺序排成一个32位字否则后面PC端显示图像时颜色是乱的。我当时在设计时把FVAL和LVAL也打包进帧头里这样后端可以准确恢复图像的行场同步信息比自己猜测像素尺寸靠谱得多。工程1上板验证的标准就是用SignalTap抓Aurora的axi_tx_tready和FIFO的wr_usedw确认数据确实在持续发送。这阶段不求图像完全正确只要链路上有稳定数据流就算成功。3.3 工程2到工程4回环自测、BMP抓帧、DDR缓存实时传输工程2做的是把Aurora接收端解出来的数据再环回发送端同时用伪随机序列做误码统计。这里要区分两种回环一种是在FPGA内部把RX数据直接接到TX数据接口验证的是Aurora逻辑链路另一种是通过GTX内部的PMA回环或者PCS回环验证的是物理层和编解码层。实际调试时有个经验先跑GTX的PMA回环这时数据不经过SFP光模块可以判断FPGA端GTX是否正常然后跑外部光纤回环就是把SFP的TX用光纤跳线直接连到RX验证光模块和光纤链路。外部回环通过后再接入真实的CameraLink相机这时候如果出问题排查范围已经缩小到相机和CameraLink接口芯片那一侧了。工程3加了BMP抓帧功能。FPGA端维护一个帧计数器每收到一帧完整的CameraLink图像就通过Aurora帧头发送一帧数据PC端用简单的QT或者Python程序从接收端读取数据并存储为BMP。这个工程的核心价值是验证图像数据格式而不是传输链路所以我在FPGA端把图像尺寸和帧格式做成了参数可配方便适配不同分辨率的相机。工程4是目前最接近产品形态的版本增加了DDR3缓存。为什么要加DDR因为CameraLink进的是连续像素流带宽是恒定的而后端图像处理平台可能是突发式读取数据的加了DDR缓存后可以做到“输入连续收输出按需发”。同时DDR也解决了多路相机不同步时需要临时缓存整帧数据的问题。工程4在FPGA里例化了DDR3控制器、写通道仲裁、读通道调度和一组图像帧FIFO逻辑复杂度比前三个工程上了一个台阶但功能和稳定性也最接近实际交付状态。4. 实操过程Vivado里搭建工程的完整步骤4.1 工程创建与GT Transceivers Wizard配置我用Vivado 2019.1版本做的这个项目器件是Kintex-7系列。新建工程后第一步是添加Aurora 8B10B IP这里我建议不要单独去创建GT Transceivers Wizard直接通过Aurora IP的配置界面来间接生成GT实例因为Aurora和GTX之间的参数匹配非常微妙手动配置GT很容易漏掉某个约束位。Aurora 8B10B IP的配置界面里要关注几项Lane Rate填3.125Gbps这个要和参考时钟、GTX的QPLL参数联动参考时钟填125MHz注意要和板子实际接到GTX参考时钟引脚的频率一致数据位宽选32位对应用户时钟78.125MHzInterface模式选Streaming数据流方向选Duplex同时支持发送和接收共享逻辑选择Include Shared Logic in Core把复位和时钟模块放到IP内部减少顶层连接复杂度。Aurora IP会自动生成一个GT Transceivers Wizard实例生成的名字带gt_*前缀。此时打开Generated IP的例化模板可以看到gt_rxp_in、gt_rxn_in、gt_txp_out、gt_txn_out这些引脚把它们直接连到SFP的差分引脚即可。4.2 Aurora IP接口对接与时钟复位处理Aurora 8B10B IP对外接口主要有几组用户发送接口、用户接收接口、链路状态接口、复位接口和时钟接口。顶层对接时最容易出事的是复位逻辑。Aurora IP的reset引脚支持异步复位但要求复位释放后至少保持若干个用户时钟周期如果复位释放得太快GTX可能没完成初始化和校准导致链路一直起不来。我的做法是做一个专用的复位延时模块上电后立即拉低Aurora的复位延时100ms后再释放。这100ms足够GTX完成PLL锁定和模拟校准也避免了FPGA全局复位对GTX的干扰。实测中这个延时非常关键很多人的Aurora链路不稳定问题就出在复位时序上。用户接口对接方面Streaming模式下发送端是s_axi_tx_tdata、s_axi_tx_tvalid、s_axi_tx_tready这套AXI4-Stream握手信号。FIFO读出的32位数据只要tvalid拉高且tready为高就表示数据被Aurora接收了。接收端同理m_axi_rx_tdata和m_axi_rx_tvalid配合使用。这个握手规则不复杂但我见过不少新人把tvalid一直拉高完全不看tready这在高带宽时会丢数据。链路状态接口里最重要的三个信号是channel_up、lane_up、hard_err和soft_err。调试时加一个LED点亮channel_up一眼就能看出链路状态。soft_err出现时不要慌8B10B链路在外部干扰下偶尔报一次soft error是正常的但如果连续报错就要查信号完整性或者光模块质量了。4.3 CameraLink时序约束与跨时钟处理从CameraLink接口芯片DS90CR288A输出的PCLK是一个由相机决定的输入时钟频率范围25MHz到85MHz。如果你在FPGA里用了MMCM/PLL来倍频或相位调整那必须给这个输入时钟创建约束否则Vivado会为了满足所有可能的时钟场景而过度约束导致时序收敛困难。最简的约束写法是create_clock -name cam_pclk -period 11.764 [get_ports cam_pclk]这里的period 11.764ns对应85MHz。如果相机像素时钟是别的频率根据实际值修改即可。需要注意的是如果PCLK进入了MMCM/PLL约束只需要加在输入端口上Vivado会自动推导出MMCM输出时钟的约束。跨时钟域处理上我用的是Xilinx的异步FIFO IP写时钟是PCLK读时钟是78.125MHzAurora用户时钟。FIFO深度取1024或者2048就够不要盲目做很深因为FIFO深了会增加延迟。深度计算逻辑很简单写入速率最大2.38Gbps读出速率固定2.5Gbps读比写快只要FIFO防亚稳态的同步逻辑正常工作理论上不会溢出。如果跑到极限像素时钟85MHz写入速率逼近读出速率FIFO深度可以适当加大到4096但带宽余量已经够了。FIFO两端的数据位宽匹配也要注意。CameraLink的28位并行数据经过打包后是32位异步FIFO我设置的也是32位输入输出这样从FIFO读出的数据和Aurora的用户接口位宽严格对齐不需要额外的位宽转换逻辑。4.4 板级调试与实测结果板级调试的第一步是上电看电流GTX和SFP部分如果电流异常先查电源不要急着加载bitstream。第二步是烧录工程1用SignalTap看Aurora的channel_up信号是否拉高如果拉不高等2秒后拉低大概率是GT参考时钟或者复位时序问题。第三步是用IBERTIntegrated Bit Error Ratio Tester独立验证GTX物理层。IBERT是Vivado自带的一个调试工具可以生成误码率测试的bit文件在硬核里产生伪随机序列并通过环回方式统计误码。我习惯在任何Aurora项目里都先把IBERT跑一遍20分钟能解决的物理层问题比在复杂逻辑里排查一整天强得多。我实测的这套方案CameraLink输入用Basler的2048x204860fps相机像素时钟85MHzSFP用千兆多模模块加50米OM3光纤光口端用另一块FPGA板接收并恢复图像。连续跑8小时没有出现链路中断误码统计为0图像无花屏无丢行。如果换成单模模块加20公里光纤链路依然稳定这主要得益于Aurora协议本身设计得好以及GTX物理层的可靠性足够高。4套工程的综合资源占用情况大概是GTX一对约占用一个bank的相关资源Aurora IP逻辑大概两千多个LUT加三千多个FF整个工程加上CameraLink接收和FIFO逻辑7K325T这种片子资源占用不到10%留有充分空间给后续的图像算法处理。5. 常见问题与排查技巧实录5.1 GTX失锁与参考时钟问题Q上电后Aurora的channel_up一直不拉高gt_pll_lock信号反复跳变。A这是GTX参考时钟问题可能性按概率排序为参考时钟根本没有真正送到GTX专用引脚检查PCB走线有没有接入MGTREFCLK参考时钟频率和IP配置不一致用示波器实测频率对一下GTX模拟电源纹波过大或者电源上电时序不对复位释放过快GTX还没完成PLL锁定。排查顺序我建议是示波器测参考时钟频率和幅度确认电源纹波GTX的VCCO和MGTAVCC纹波要控制在30mV以内再加长复位延时。GTX的PLL锁定是整个Aurora链路正常工作的前提如果gt_pll_lock不稳定优先找硬件问题不要把时间浪费在改逻辑上。5.2 Aurora链路通但数据乱码的处理Qchannel_up稳定拉高但接收端数据偶尔错位图像出现周期性花屏。A这种情况基本是字节对齐或者通道绑定问题但也有可能是CameraLink帧格式相关问题。先用IBERT的环回测试排除GT物理层如果IBERT无误码问题大概率出在Aurora帧结构对上位机解析的影响上。我遇到过一次很隐蔽的问题Aurora IP在Streaming模式下会周期性插入K码用于时钟补偿接收端解出来的数据流中这些K码已经被IP去掉了但PC端软件在解析时如果以固定字节数分帧就会因为K码间隙导致帧错位。解决办法是在FPGA发送端自己维护帧头标志每帧开始前发送一个多字节同步头PC端同步头搜索后再解析就不会受K码插入影响了。5.3 CameraLink接口芯片相关的坑Q图像有规律性噪点或者颜色通道错乱。A先查DS90CR288A的输出映射。CameraLink 28位并行数据和LVDS通道的对应关系不是线性的手上没有数据手册必然踩坑。我把基址映射表打印出来贴在工作台前确认FPGA侧引脚分配和芯片手册一一对应。另一个容易忽略的是时序DS90CR288A输出的PCLK和有效数据之间有一个小的窗口FPGA接收时最好用IDELAY或PLL移相来保证采样点落在数据稳定区域。85MHz下不做什么也能跑通但温度一高或者芯片批次一变就开始偶发花屏。增加一个动态移相逻辑让FPGA自动找到最佳采样点能彻底解决这个问题。QSFP光模块不发光或者LOS一直拉高。A先检查TX_DISABLE引脚。很多SFP模块默认TX_DISABLE是高电平有效如果FPGA上电后这个引脚被FPGA内部的默认上拉或者下拉拉到了无效状态光模块就直接被禁用了。我在sfp_ctrl模块里做了显式控制上电后延时100ms再拉低TX_DISABLE确保光模块正常上电初始化。其次检查SFP插座的接触可靠性这问题看起来低级但在实际项目里真的发生过好几次。5.4 高速链路信号完整性的经验SFP和GTX之间的高速差分走线在PCB设计阶段就要控制好。具体来说差分阻抗100欧有些SFP方案要求90欧看芯片手册TX和RX差分对内等长控制在5mil以内和参考时钟差分对之间保持足够的间距。SFP的金属外壳和屏蔽罩要直接和地平面良好接触否则电磁干扰可能会让你的误码率在长时间运行后缓慢上升。我调试时还发现过一个问题SFP模块的TD和TD-接反导致数据完全不通。如果遇到channel_up一直起不来把TX和RX极性互换或者用GTX的极性翻转功能试试这比重新改板快得多。6. 这个方案后续还能怎么扩展整个CameraLink转SFP的框架搭好之后扩展方向其实很多。最直接的一种是改成Aurora 64B66B协议加更高的线速率比如用10G SFP模块带宽一下提到10Gbps级别CameraLink Full甚至双路Full相机都能同时传输。另外可以在光口对端接一块同样的FPGA板实现“光口进、CameraLink出”的双向转换这样整套系统就是一套透明的CameraLink延长器后端显示器看到的图像和直接用短CameraLink线缆没有区别。如果你需要做视频流处理这个架构也可以无缝叠加。CameraLink进来的图像先经过FPGA里的ISP或者图像算法模块再进Aurora发送等于把预处理功能也搬到了采集端后端平台的负载会小很多。我自己已经在工程4的基础上加了简单的图像缩放和ROI裁剪模块客户反馈效果不错。从团队开发的角度看这套4工程的划分思路也值得保留。新人上手时从工程1开始按顺序看到工程4对整个链路从物理层到应用层的理解会比较完整。后续如果换平台比如从Kintex-7换到Artix-7或者Zynq UltraScaleIP配置虽然要跟着调整但模块架构和代码风格基本可以平移。最后再说个实际体会。我踩过最大的坑是在工程2阶段当时Aurora光口环回一切都正常一接上真实相机就开始偶发丢帧。查了很久发现是FPGA内部一个跨时钟域的握手信号没有做同步处理导致帧计数器偶尔跳变。这种问题纯靠看代码很难发现最好在SignalTap里同时观察FIFO水位和帧计数异常时立刻能看出来。FPGA高速传输项目链路层只要按官方文档做基本都稳真正容易出问题的往往是你自己的用户逻辑和跨时钟域处理所以每一层都要留足验证手段不要指望一次全部调通。

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

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

免费获取报价