FPGA实现CameraLink转SFP光口:Aurora 8B10B与GTX高速收发器工程方案
发布时间:2026/9/7 2:05:47 作者:尧图编辑部 阅读量:1,286

FPGA接口转换项目里CameraLink转SFP光口一直是块硬骨头。CameraLink协议本身是并行的Base/Medium/Full配置数据率动辄几百MB甚至上GB级别而SFP光口走的是高速串行差分信号中间必须有FPGA做数据格式和物理层的双重转换。我这次做了一套完整的工程方案主控用Xilinx 7系列FPGA通过GT Transceivers Wizard例化高速收发器再用Aurora 8B10B协议完成串行编解码把CameraLink的图像数据包含像素数据、行场同步、像素时钟整体搬到光口上解决了长距离传输和电气隔离的问题。整个方案一共整理了4套不同配置的工程源码从单路Base模式到Full模式全覆盖到手直接改引脚约束就能跑。这项目适合三类人看一是正在做图像采集传输系统、被CameraLink线缆距离限制卡住的人二是想在FPGA上快速打通GTX/GTH高速收发器、但对Aurora协议还不熟悉的工程师三是准备做CameraLink接口相机采集板卡、需要参考整体架构设计的人。下面我把这套方案的架构思路、关键原理、模块拆解、工程源码使用方法和调试技巧一次性讲清楚。1. 整体设计方案与架构思路拆解1.1 为什么要用SFP光口替换CameraLink线缆CameraLink是工业相机领域很成熟的标准接口但它的物理层用的是MDR26或SDR26连接器信号是LVDS差分对线缆传输距离最多也就10米实际工程里超过5米就开始有明显衰减。如果相机装在运动平台上线缆跟着拖链来回弯折故障率更高。还有一个问题是CameraLink的并行数据线数量多Full模式单相机要占用3条链接布线麻烦。换成SFP光口后单根光纤轻松跑10公里抗电磁干扰能力强设备间还实现了电气隔离地环路问题直接消失。对图像传输系统来说这几乎是根治的方案。但CameraLink是并行接口SFP光口是串行接口怎么衔接FPGA就是中间的桥梁。CameraLink接收端用DS90CR288A这类LVDS解串器把串行LVDS转成28位并行数据送入FPGA。FPGA拿到并行数据和像素时钟后按Aurora 8B10B协议打包成帧送进GTX/GTH收发器的发送端转成高速差分串行信号驱动SFP光模块。接收端反过来做光信号转电信号后GTX恢复出并行数据Aurora解帧再通过DS90CR287串行器转成CameraLink的LVDS信号送给采集卡。整个链路就是“并行→串行→光纤→串行→并行”。1.2 Aurora 8B10B协议为什么适合这个场景Aurora是Xilinx推的免费轻量级高速串行链路协议专门给FPGA之间或者FPGA和ASIC之间做点到点数据传输。用8B10B编码方式数据和时钟一起编码进高速流里接收端不需要额外的时钟恢复链路。我选择Aurora 8B10B而不是Aurora 64B66B原因很实际CameraLink的图像数据带宽最高也就2.38GbpsFull模式85MHz像素时钟×24位数据8B10B编码后约2.97Gbps一片K7-325T的GTX就能轻松跑3.125Gbps线速率8B10B编码有内置的逗号字符字节对齐和通道绑定方便实现简单可靠GT Transceivers Wizard里直接集成Aurora 8B10B IP核模板不用自己撸编解码逻辑省掉大量调试时间帧结构简单没有Aurora 64B66B那种复杂的扰码和帧校验机制端到端延迟更低所以做CameraLink这个量级的图像传输8B10B是性价比最优解。1.3 4套工程源码的区分逻辑这4套工程不是随便凑的覆盖了CameraLink最常见的三种配置工程一单路Base模式像素时钟最高85MHz24位像素数据4位虚拟数据用GTX 1个通道线速率2.5Gbps这是最常见的工业相机配置工程二双路Base模式相当于Medium配置2个GTX通道每路单独轮换可以实现中高分辨率相机的双通道传输工程三Full模式3个GTX通道拼接像素数据位宽到64位其中24位为虚拟数据带宽最大工程四Base模式回环测试工程发送端内部产生测试图案不经过CameraLink接口直接Aurora发出、接收端解出并比对用来验证光口链路和GTX配置的正确性对于大多数项目工程一和工程四最实用工程四先验证链路工程一接真实相机。2. 硬件平台与关键器件选型2.1 FPGA选型的考量与资源评估这个方案对FPGA的资源需求分两大块逻辑资源和高速收发器资源。CameraLink Base模式解串后的并行数据是24位像素4位同步信号进FPGA后要用内部FIFO做跨时钟域处理再把数据组织成Aurora帧。因为Aurora协议的发送端是AXI4-Stream接口需要把并行数据流转换成连续的字节流。这部分逻辑量不大也就几百个Slice真正占用资源的是GTX收发器硬核和时钟管理单元。7系列里我推荐这三款Artix-7 75T适合单路Base模式1个GTX通道够用性价比高适合成本敏感的项目Kintex-7 325T适合Full模式或多路MediumGTX数量16个4路光口能同时跑逻辑资源也充裕是这个方案的主力Zynq-7030如果后续还要接ARM做图像处理算法选Zynq更合适PL端GTX架构和Kintex-7同源务必检查的一点是器件的速度等级和GTX的线速率支持范围。7系列Aritx-7的GTX最高支持6.6Gbps做2.5-3.125Gbps完全没问题但GTP和GTX的使用方式有细微差别约束写法也不一样最好统一用GTX。2.2 CameraLink接口芯片DS90CR288A/DS90CR287CameraLink物理层规范定义了三种芯片驱动器DS90CR287并转串、接收器DS90CR288A串转并、以及并转并的Channel Link芯片。这套工程里输入侧用DS90CR288A把相机输出的5对LVDS串行数据转成28位并行CMOS24位像素4位帧/行同步信号输出侧用DS90CR287把FPGA送出的28位并行数据转成LVDS串行送给采集卡。实际工程里常踩的坑DS90CR288A需要一个与像素时钟同步的LVDS输入时钟这个时钟同时作为输出并行数据的参考时钟FPGA内部锁相环要以它为基准生成GTX的参考时钟跨时钟域处理时务必对齐相位关系CameraLink的Channel Link信号里包含一个锁相环需要的PLL时钟部分相机输出的时钟占空比不是50%必须先经过IBUFDS差分缓冲再进PLL必要时用IDELAY做相位微调芯片的TXOUT引脚与FPGA I/O的电平标准要匹配DS90CR288A输出是LVCMOS 3.3VFPGA对应Bank的VCCO必须接3.3V2.3 SFP光模块与GTX收发器的对接SFP光模块的电接口是标准的LVPECL差分对和FPGA的GTX收发器直接相连时需要做AC耦合这是最稳妥的做法。FPGA的GTX发送端TX引脚到SFP模块的TD/-之间串接100nF电容接收端同理。关键的配置点是GTX的终端电阻SFP模块内部已经带了50欧姆端接到地FPGA侧GTX的RX端要用内部端接TX端一般用外部端接电阻或者依赖模块自带的信号调理。实际工程里我习惯在原理图上给SFP模块的TX/RX引脚都加上100nF耦合电容同时在FPGA的GTX RX端配置为“RX Equalization”自适应模式因为不同厂家光模块的S参数差异比较大固定均衡参数容易被长走线坑到。光模块选择建议850nm多模模块OM3光纤短距离板间传输成本低1310nm单模模块单模光纤长距离跨设备传输稳定光模块的速率等级要覆盖GTX设置的线速率比如2.5Gbps用2.125G-2.67G的光模块别买千兆光模块带宽不够3. 核心模块实现细节与实操要点3.1 GT Transceivers Wizard配置要点打开Vivado里的GT Transceivers Wizard选好FPGA型号后关键配置项逐一说清楚。首先是Protocol模板。不要选自定义直接选Aurora 8B10B模板向导会自动把TX/RX的数据位宽、编码方式、逗号检测等参数设置好。线速率这里填2.5GbpsBase模式或3.125GbpsFull模式参考时钟一般用100MHz或156.25MHz两者必须满足“线速率 参考时钟 × 分频系数”的关系具体在向导里用“Calculate”按钮看是否合法。然后是数据位宽。GTX的发送数据接口在8B10B编码前是16位或32位Aurora 8B10B IP核的AXI4-Stream接口是32位4字节所以GTX内部数据位宽选32位TXUSRCLK就是线速率除以40因为8B10B每字节10位32位数据需要4个UI8B10B后每个字节10位所以4字节即40位TXUSRCLK线速率/40。例如2.5Gbps时TXUSRCLK62.5MHz。3.2 Aurora 8B10B IP核的配置与接口Aurora 8B10B IP核配置时选单通道还是多通道通道数要和GTX的通道数量对应。Base模式单通道够用Medium模式选2通道Full模式选3通道。IP核接口上重点说明三个s_axi_tx_tdata发送数据总线32位Aurora会把每字节的低位优先发出s_axi_tx_tvalid/tready握手信号本方案中我直接用连续发送模式tvalid拉高直到所有数据发完m_axi_rx_tdata接收数据总线同样32位接收端要按字节顺序还原图像像素帧格式我是这么组织的图像的一行像素放在一个Aurora帧里帧头加一个32位的“图像头”包含第几行、行像素个数、图像分辨率宽度、像素格式编码。帧尾加32位CRC校验像素数据字节对齐后算CRC32。这样接收端解析时先收头部知道行宽和格式再收固定长度的像素数据最后校验过程干净利落。3.3 跨时钟域处理与FIFO设计CameraLink侧像素时钟PCLK和Aurora侧用户时钟USER_CLK是两个独立时钟域必然要做跨时钟域处理。图像数据这种连续高速流最佳方案就是异步FIFO。Base模式24位像素一个PCLK周期写入24位但Aurora发送接口是32位位宽FIFO写入位宽24位、读出位宽32位会遇到凑不够32位的情况。我的做法是把24位像素数据扩展成32位存储格式多出的8位存放行号低8位或者其他辅助信息。这样做的好处是FIFO读写位宽一致都是32位不用处理跨位宽的麻烦。FIFO深度选择按一行像素数算假设图像宽1280一行的数据量5120字节FIFO深度至少要能缓存2行防止Aurora链路上偶尔的背压导致溢出。实际用2048×32位8K深度对2K分辨率以下都够。FIFO的Prog_Full信号接到发送控制状态机FIFO快满时状态机不再向Aurora发送新帧同时向图像采集端发送反压信号。3.4 接收端数据恢复与CameraLink输出接收端的Aurora解帧后先按帧头信息解析行号和像素格式把32位数据流还原成24位像素写入接收FIFO。再从FIFO读出按行场同步要求通过DS90CR287发送出去。有个容易出问题的地方CameraLink采集卡要求接收端的LVDS时钟即DS90CR287的像素时钟必须和发送端相机的像素时钟一致或者非常接近。Aurora链路本身是异步的光口传输会引入缓冲延迟采集端如果按固定的PCLK采样可能会因为两端的时钟偏差累积丢行。解决办法是接收端用“从Aurora恢复的时钟”作为像素时钟输出也就是从接收数据流中恢复出来的频率和发送端晶振同源但经过CDR时钟数据恢复后可能有几ppm的偏差。这个偏差靠接收端FIFO的读写水位差动态调整帧头里带上“行号连续计数器”接收端发现计数跳变就适当调整FIFO上下水线实测能稳定跑72小时不掉帧。4. 工程源码结构与使用指南4.1 4套工程源码的目录架构四套工程我都放在统一的目录结构下拿到后按README操作即可。顶层结构如下├── cameraLink_sfp_top.v # 顶层模块例化GTWizard、Aurora、FIFO、状态机 ├── src/ │ ├── cameralink_rx.v # CameraLink接收端DS90CR288A数据采样 │ ├── frame_gen.v # Aurora发送帧组织帧头像素CRC │ ├── frame_parse.v # Aurora接收帧解析 │ ├── cameralink_tx.v # CameraLink输出端并转串接口 │ ├── async_fifo_32x2048.v # 跨时钟域FIFO │ └── crc32_d32.v # CRC32校验模块 ├── ip/ │ ├── gtwizard_0.xci # GT Transceivers Wizard IP核配置 │ └── aurora_8b10b_0.xci # Aurora 8B10B IP核配置 ├── constraint/ │ ├── pin.xdc # 引脚约束 │ ├── timing.xdc # 时钟和跨时钟域约束 │ └── xdc_gtwizard.xdc # GTX相关约束Vivado自动生成 └── sim/ ├── tb_cameralink_top.v # 仿真测试平台 └── test_pattern_gen.v # 测试图案生成器使用步骤如下先用Vivado打开对应工程每个工程目录下有完整xpr工程文件检查IP核的器件型号是否匹配你的FPGA如果是相同系列的器件直接Refresh IP即可把pin.xdc里的FPGA引脚改到你的板卡实际连接综合、实现、生成 bitstream工程四的回环测试可以先用仿真试用确认链路正常再上板4.2 约束文件的核心注意事项GTX相关的约束里最容易写错的是参考时钟和GTX的位置约束。Vivado的GT Transceivers Wizard会自动生成xdc_gtwizard.xdc里面包含GTXE2_CHANNEL的LOC约束。如果你修改了参考时钟引脚必须同步修改GTX参考时钟的bind约束。选参考时钟引脚时有一个细节7系列FPGA每个GTX bank有专用的参考时钟引脚如MGTREFCLK0/1要让GTX使用哪个参考时钟必须在XDC里用loc约束指明set_property LOC GTXE2_CHANNEL_X0Y8 [get_cells gtwizard_0_i/gtwizard_0_i/gtwizard_0_inst/gtxe2_i] set_property LOC MGTREFCLK_X0Y0 [get_cells gtwizard_0_i/gtwizard_0_i/gtwizard_0_inst/refclk]跨时钟域约束上异步FIFO的读写时钟之间用set_clock_groups -asynchronous声明避免Vivado对这两个时钟域做不合理的时序分析产生大量false path警告。4.3 仿真验证与上板调试流程先用仿真把逻辑跑通。架一个tb用PLL生成85MHz像素时钟test_pattern_gen模块产生图像数据通过cameralink_rx输入到顶层再经过Aurora发送和接收仿真里Aurora可以走内部环回模式不需要外部光模块最后从cameralink_tx输出用testbench比对输入输出数据完全一致即通过。仿真通过后上板第一个人为验证方法是用ILA集成逻辑分析仪抓Aurora的AXI4-Stream接口看tvalid/tready握手是否正常CRC校验是否报错。第二个验证方法是工程四的回环测试如果回环测试通过说明GTX和Aurora链路没问题可以接CameraLink。常见问题的排查顺序我后面专门讲这里提醒一句上板前务必检查SFP模块的电源和I2C地址很多光模块需要先供电并初始化否则GTX接收端完全没有信号。5. 常见问题与排查技巧实录5.1 问题速查表现象可能原因排查方法GTX复位不释放参考时钟未起振或频率不对ILA抓GTX的txresetdone/rxresetdone信号确认参考时钟频率Aurora链路无法对齐线速率与SFP模块速率不匹配或参考时钟抖动过大检查光模块速率等级确认GTX的TX/RX终端电阻配置正确图像花屏/绿屏数据错位或帧格式不对用工程四回环测链路抓Aurora帧头数据比对CRC校验偶尔丢帧FIFO深度不足或背压机制不完善增大FIFO深度检查Prog_Full信号和发送状态机的联动时序长时间运行后掉链眼图余量不足或热漂移导致误码用IBERT眼图扫描检查GTX的TX预加重和RX均衡参数CRC大量报错光纤接口接触不良或光模块质量差换光纤、换光模块检查SFP座子的焊点5.2 调试中用到的三个核心技巧第一个技巧是GTX眼图扫描。Vivado里有IBERT IP核可以扫描GTX通道的眼图和浴盆曲线快速定位物理层问题。调试这套系统时我上板后第一件事就是跑IBERT确认2.5Gbps下眼图睁开足够保证误码率低于1e-15再开始测Aurora协议层。很多时候花屏的根源就是物理层眼图不好BERT测试能帮你把问题分层。第二个技巧是抓同步信号。CameraLink图像的行场同步信号FVAL/LVAL在解串后是单独的引脚调试时先抓这几个信号确认相机输出正常再检查像素数据。如果在FPGA内部就能看到LVAL的脉冲宽度和行周期就能判断数据流方向是否对。第三个技巧是软件触发诊断模式。我在这套工程里写了一个简单的“测试模式”寄存器通过UART或者板卡上的拨码开关控制可以让发送端不接相机直接产生彩条测试图案通过Aurora发送、接收端还原。调试接收端时不用依赖真实相机大幅缩短调试周期。5.3 长期稳定性验证的注意事项CameraLink转光口项目最怕的就是短期测试通过、长期跑起来出问题。我实际验证过连续运行72小时以上主要关注三点GTX的通道温度变化FPGA温度升高后GTX的RX均衡参数可能有漂移需要在initial配置里留足够裕量光模块的发射光功率和接收光功率用模块的数字诊断接口DDM监控光功率接收光功率建议高于-15dBmFIFO水位的长期漂移记录接收端FIFO的读写指针差值长时间停车后如果不断上升说明两侧时钟偏差累积方向一致需要调整帧头里的消隐处理这些点都在工程源码里有对应配置比如FIFO水位软复位寄存器可以定期自动校准。6. 扩展方向与后续优化建议如果这套方案稳定跑通了有几个方向可以继续扩展。第一个是带宽升级。CameraLink Full模式的带宽已经接近2.38Gbps如果后续换成10G以太网接口或者更高分辨率的相机可以把Aurora 8B10B换成Aurora 64B66B线速率直接提到10.3125Gbps物理层换GTH/GTY逻辑层改动主要在编解码和帧格式上。第二个是接口扩展。SFP光口之后除了对接CameraLink采集卡也可以对接交换机的光口或者另一个FPGA开发板做成通用图像传输节点。只要把帧格式统一一下就能变成私有协议的图像传输接口。第三个是增加控制通道。目前这套方案是纯图像数据单向传输如果相机需要串口控制或者GPIO触发可以在Aurora帧里划分一个单独的控制通道字在空闲周期里双向传控制指令。Aurora协议本身支持这样的用户自定义通道。我个人在实际项目中的体会是CameraLink转光口这个项目最大的价值不是技术难度本身而是它把FPGA中最常用的模块全打通了一遍GTX高速收发器配置、Aurora IP核使用、跨时钟域FIFO设计、状态机控制、XDC约束编写、ILA调试可以说做通这个项目FPGA的高速接口开发能力基本就过关了。如果你正在做类似的项目先从工程四回环测试开始把物理层链路调扎实再上真实相机能少走很多弯路。