1. 项目背景与方案选型思路
1.1 为什么需要 CameraLink 转光口
做机器视觉和工业检测的工程师,对 CameraLink 接口一定不陌生。这套接口标准在工业相机领域用了很多年,特点是带宽高、稳定、确定性延迟好。以 Base 配置为例,3 对 Channel Link 数据通道加上 1 对时钟通道,工作在 85MHz 时理论带宽能达到 2.04Gbps,Medium 和 Full 配置则能跑到 5.44Gbps 甚至更高。但实际工程里总会遇到一个尴尬问题——CameraLink 线缆传输距离太短。
标准 CameraLink 线缆通常建议 3 米以内,虽然加装中继器(如 Basler 的 Camera Link Repeater)能推到 10 多米,但成本上来了,而且线缆又粗又硬,在运动平台、机械手臂这种场合走线极其痛苦。更麻烦的是,有些产线工位之间距离几十米甚至上百米,总不能把相机搬过去吧。
这时候把 CameraLink 转成光口就非常有价值了。光纤传输距离动辄几百米到几公里,信号衰减几乎可以忽略,而且光纤线径细、重量轻、抗电磁干扰能力强。在医疗影像、交通抓拍、军工电子、平板检测这类场景里,CameraLink 转光纤几乎是刚需。
1.2 为什么选 Aurora 8B10B 协议
做 CameraLink 转光口,实现方案其实不止一种。完全自定义的 SerDes 协议、RapidIO、SRIO、Aurora 各有优劣,但我最终选择 Aurora 8B10B,主要看重它这几个特性。
首先是协议开销低。Aurora 8B10B 属于轻量级链路层协议,只负责数据拆分、链路初始化、通道绑定和错误检测,不像 TCP/IP 协议栈那样有沉重的封装开销。对于 CameraLink 这种实时视频流来说,延迟越低越好,Aurora 正好满足。
其次是 Xilinx 官方维护,生态好、参考设计多。在 Vivado 里通过 GT Transceivers Wizard 生成高速收发器底层,再用 Aurora 8B10B IP 核把链路控制逻辑打包好,工程师不需要自己写 PCS 层的字节对齐、8B10B 编解码、时钟补偿这些复杂逻辑,工作量能省不少。
第三是兼容性强。Aurora 8B10B 在 Xilinx 官方文档 PG046 里有详细规范,链路初始化状态机是开放的,只要对端也按规范实现,跨厂商跨芯片互通是可行的。而且 Aurora 8B10B 支持 1~16 条通道绑定(Channel Bonding),这对于 CameraLink Full 配置这种大带宽需求来说,扩展空间很充裕。
还有一点很关键,8B10B 编解码自带 DC 平衡和游程长度限制,对光模块这种交流耦合链路非常友好。不像 64B66B 那样对时钟恢复要求更苛刻,也不像纯 NRZ 编码那样容易出现连续长 0 或长 1 导致 CDR 锁定异常。工业环境里,稳定比什么都重要。
1.3 整体架构图与数据流规划
这套系统的顶层架构,核心是一条流水线:CameraLink 接口接收图像数据 → FPGA 逻辑将并行数据整理成用户数据流 → 经过 Aurora 发送端 FIFO 送入 GT Transceiver → SFP 光模块发出去。接收方向则刚好相反。
下面我用文字把这幅数据流图描述清楚,方便你对整体有个认识:
CameraLink 相机输出 → CameraLink 连接器/线缆 → 板卡上的 DS90CR288A/DS90UB914A(CameraLink 解串器)→ FPGA 的 IO 引脚接收 28bit 并行数据 + 4 个 LVDS 时钟 → FPGA 内做数据对齐与格式转换 → 写入异步 FIFO → Aurora 8B10B IP 核用户逻辑接口 → GT Transceivers Wizard 生成的收发器通道 → SFP 光模块 → 光纤 → 远端接收板。
接收方向就是反向流程,光信号进来后经过 SFP 光模块转成电信号,GT 完成时钟恢复和串并转换,Aurora 核做字节对齐和链路管理,最后恢复出的数据在 FPGA 内重新映射成 CameraLink 并行时序,通过 DS90CR287 驱动器输出给后端采集卡或显示器。
这套架构的关键在于两端 FPGA 的程序要按同一套 Aurora 参数配置,链路速率、通道数、数据接口位宽必须严格一致。否则链路初始化就会失败,表现在现象上就是接收端 User Interface 的 RX 数据一直无效,或者 LINK_UP 信号拉不起来。
2. CameraLink 接口采集与预处理核心细节
2.1 CameraLink 接口配置深度解析
CameraLink 协议在物理层其实就是 Channel Link 技术的扩展。标准的 Channel Link 是 4 对数据 LVDS + 1 对时钟 LVDS,而 CameraLink 在此基础上分成了 Base、Medium、Full 三种配置。
Base 配置使用一个 Channel Link 连接,也就是 4 对数据加 1 对时钟,此时数据位宽是 28bit,其中 24bit 用于图像数据,4bit 用于相机控制信号(CC1-CC4)。在 85MHz 像素时钟下,Base 模式有效带宽 2.04Gbps,传 8bit 灰度图可以跑到 85MHz×24bit/8bit=255MB/s,够用但不算宽裕。
Medium 配置在 Base 基础上增加了第二个 Channel Link,只用来传输图像数据,这样数据位宽变成 56bit,带宽翻倍。Full 配置则是在 Base 基础上增加两组通道,数据位宽达到 84bit,带宽是 Base 的三倍。
做工程选型时,首先要确认你的相机是哪种配置。工业相机厂商如 Basler、DALSA、Vieworks 的 CameraLink 相机,通常在规格书上明确标注支持 Base、Medium 还是 Full。比如 DALSA 的 Genie Nano 系列,很多支持 Base 配置,而 Vieworks 的高分辨率面阵相机通常需要 Full 配置才能满足满帧率输出。
还有一个小细节容易踩坑,就是像素时钟。CameraLink 标准支持 20MHz~85MHz 的像素时钟范围,但实际很多工业相机的像素时钟是可以软件配置的。比如同样的相机,在低分辨率模式可能用 40MHz,在高分辨率全幅面输出时跑到 75MHz。FPGA 端要做的是无论像素时钟怎么变,都能正确接收并转发,因此采集模块需要具备一定的自适应能力。
2.2 FPGA 端 CameraLink 数据接收实战
CameraLink 的物理层是 LVDS 差分信号,但 FPGA 一般不会直接接收这种信号,而是通过解串器芯片先把串行 LVDS 数据转成并行 CMOS/TTL 信号。主流方案是 DS90CR288A(TI 公司,Base 配置)或 DS90CR288A + DS90CR286A 组合(Medium/Full 配置)。
我用的是 DS90CR288A 这块经典芯片,它把 4 对 LVDS 数据线和 1 对 LVDS 时钟线转换成 28bit 并行数据 + 1 个像素时钟。需要注意,DS90CR288A 输出的是 28bit 数据,这 28bit 里,前 24bit 是图像数据,后 4bit 是相机控制信号。具体排列规则是:
D0~D7:图像数据通道 1(对应 Channel Link 的 Tx0 输出) D8~D15:图像数据通道 2 D16~D23:图像数据通道 3 D24~D27:相机控制信号 CC1~CC4
在 FPGA 里写采集模块时,要把这 28bit 信号和像素时钟同步采样。这里有一个常见的坑:DS90CR288A 输出的数据是在时钟上升沿变化,还是下降沿变化,不同批次的芯片可能有细微差异。稳妥的做法是写一个 IO 延迟自动校准逻辑,通过抓取 FVAL(帧有效)、LVAL(行有效)信号的变化沿,自动调整数据采样时钟相位。
2.3 图像数据预处理与时序同步策略
CameraLink 接收进来的图像数据格式,FVAL(Frame Valid)、LVAL(Line Valid)、DVAL(Data Valid)这三个信号是关键。当 FVAL 拉高期间表示当前处于有效帧,LVAL 拉高期间表示当前处于有效行,DVAL 配合像素数据同步输出。
这些信号在转换成 Aurora 用户数据流时,最简单的做法是直接透传打包,把 FVAL、LVAL、DVAL 当作数据的伴随通道一起打包发送。接收端解包后直接还原成这三个有效信号,配合像素数据和行场同步信息,就能完整恢复出图像时序。
但这里有个问题需要权衡:如果把 FVAL/LVAL/DVAL 信号和像素数据完全一一对应打包,数据链路利用率不高。例如 Base 配置 24bit 像素数据,至少需要封装成 32bit(4 字节)才能对齐到 Aurora 用户接口的常用位宽,这会导致 25% 的带宽浪费。
我的做法是在发送端做一个小模块,把 24bit 像素数据和 FVAL/LVAL/DVAL 状态位封装成 32bit 数据帧。低 24bit 放像素数据,第 24~26bit 放 FVAL、LVAL、DVAL,第 27~31bit 预留。这样刚好凑满 32bit 对齐,一个时钟周期传一个像素,带宽利用率最大化。
接收端解包时,从 32bit 中高位提取出 FVAL/LVAL/DVAL 状态,低 24bit 提取像素数据,再按 CameraLink 时序输出。这个方案在工程上很成熟,我测试过在 85MHz 像素时钟下没有任何带宽瓶颈。
3. GT Transceivers Wizard 与 Aurora 8B10B 核心配置实操
3.1 GT 收发器的线速率计算与选择
Aurora 8B10B 核底层依赖 Xilinx GT 收发器,在 7 系列 FPGA 上就是 GTX(Kintex-7、Artix-7 高速版本)或 GTH(Virtex-7 高端型号),在 UltraScale 系列上是 GTH/GTY。GT 收发器的物理层实现已经比较成熟,我们需要关心的是线速率(Line Rate)怎么定。
线速率计算是第一步,也是最容易出错的地方。公式是:Line Rate = 有效数据带宽 × 编码开销系数 / 通道数。
以 Base 配置 CameraLink,像素时钟 85MHz,24bit 像素数据为例:
有效数据率 = 85MHz × 24bit = 2.04Gbps
Aurora 8B10B 编码是每 8bit 数据编码成 10bit 在链路上传输,所以物理层开销是数据量的 1.25 倍:
物理层数据率 = 2.04Gbps × 1.25 = 2.55Gbps
如果使用 1 条 GT 通道,线速率需要 ≥ 2.55Gbps。但 GT 收发器的线速率档位不是任意选的,GTX 在 7 系列上典型范围是 480Mbps~12.5Gbps(不同速度等级略有差异),而且需要满足 QPLL/CPLL 的可配置性。经查 Vivado 的 GT Wizard,2.55Gbps 这个速率在很多器件上是可以精确生成的,但我更倾向于选一个留有裕量的档位,比如 3.125Gbps。
为什么选 3.125Gbps 而不是刚好卡在 2.55Gbps?因为 Aurora 协议本身还有链路开销(初始化序列、用户 K 码等),而且线速率接近临界值会让时钟恢复压力增大。3.125Gbps 是 GTX 收发器非常成熟的档位,大量 1G/10G 以太网设计都在用这个速率附近,参考设计和调试经验都丰富。带宽利用率 = 2.55/3.125 = 81.6%,符合 Aurora 轻量协议的开销比例,完全够用。
如果是 Full 配置的 CameraLink,像素时钟还是 85MHz,但数据位宽变成 84bit:
有效数据率 = 85MHz × 84bit = 7.14Gbps
物理层数据率 = 7.14 × 1.25 = 8.925Gbps
这时单条 GT 通道就比较吃力了,工程上通常用 2 条 GT 通道绑定,每条通道线速率 = 8.925 / 2 = 4.4625Gbps,取 5Gbps 档位就有余量了。Aurora 核会做多通道绑定,把两条通道的字节交错分发,实现逻辑上的双倍带宽。
3.2 GT Transceivers Wizard 配置要点详解
在 Vivado 里创建 GT Transceivers Wizard IP 核(Xilinx 官方 IP,PG182),需要关注的配置项有好几处,任何一个设错都可能导致链路起不来。
第一步是选参考时钟(REFCLK)。在 7 系列 FPGA 上,GTX 的参考时钟一般从专用参考时钟引脚(如 MGTREFCLK)输入,频率通常选择 125MHz 或 100MHz。GT Wizard 会根据你设定的线速率和参考时钟频率自动算出分频比。我习惯用 125MHz 参考时钟,因为 3.125Gbps 线速率下刚好可以整数分频,3.125Gbps / 125MHz = 25 倍频,正好在 GTX 的 PLL 锁定范围内。这是纯经验值,你换成 100MHz 参考时钟也能算,只是分频系数不是整数,测试下来也能锁,但稳定性略差。
第二步是设置 TX/RX 数据位宽。Aurora 8B10B 核建议 GT 的内部数据位宽设为 2 字节(16bit)或 4 字节(32bit),这和 Aurora 用户接口的位宽配置有关。我通常把 GT Wizard 的 Internal Data Width 设为 4 字节(32bit),这样在 3.125Gbps 线速率下,内部用户时钟 = 3.125Gbps / 32bit = 97.65625MHz。这个频率高于 CameraLink 的 85MHz 像素时钟,满足数据流从慢速时钟域到快速时钟域的跨时钟处理要求。
第三步是开启 RX CDR(时钟数据恢复)相关选项。GT Wizard 里有一个 RX Equalization 选项,默认是 LPM(低功耗模式),但遇到长走线和光模块信号质量下降时,改成 DFE(决策反馈均衡)模式会更稳妥。代价是功耗略高,但对光链路这种长距离传输场景,DFE 的抗码间干扰能力更可靠。如果你的光模块质量一般,或者光纤链路长,建议改成 DFE。
第四步是注意 CPLL 和 QPLL 的选择。单通道低速率用 CPLL 够用,多通道绑定(比如 4 通道 Aurora)就必须用 QPLL,因为 QPLL 可以同时给多个 GT 通道提供时钟,保证通道间的相位一致性。
3.3 Aurora 8B10B IP 核搭建方法与参数关联
GT Wizard 配置好之后,再创建 Aurora 8B10B IP 核(Xilinx 官方 IP,PG046)。这个 IP 核会把链路初始化、通道绑定、错误检测这些逻辑封装好,用户只需要处理 User Interface。
Aurora 核的配置界面里有几个关键参数必须和 GT Wizard 保持一致:
Line Rate:必须等于 GT Wizard 里的线速率(例如 3.125Gbps) 参考时钟频率:必须等于 GT Wizard 的参考时钟频率(例如 125MHz) 通道数(Lanes):必须小于等于 GT Wizard 创建的 GT 通道数 用户接口数据位宽:Aurora 8B10B 核的 Streaming 接口,每通道推荐设为 32bit,对应 4 字节
这些参数不匹配时,Aurora 核在生成 Bitstream 时会报错误。但更隐蔽的问题是,即使能生成 Bitstream,链路初始化也可能异常。我在调试一款 Artix-7 板卡时,GT 通道数建了 2 个,Aurora 核却只配了 1 个通道,结果第二条 GT 通道完全没有输出,数据一直发送失败。排查了整整半天,最后查原理图发现 GT 通道引脚的物理连接有问题。
Aurora 核还提供两种数据接口模式:Framing 和 Streaming。做视频流传输,Streaming 模式更合适,因为它不需要定义帧边界,直接传送连续数据流。Framing 模式需要用户自己定义帧头和帧尾,适合数据包格式的应用场景。我做 CameraLink 转光口时,Streaming 模式开箱即用,省去不少工作量。
3.4 时钟架构与跨时钟域处理的关键方案
时钟设计是这套系统的生命线,我把时钟树梳理清楚,你心里就有底了。
CameraLink 像素时钟(PIXCLK)是来自 DS90CR288A 的输出时钟,频率等于相机的像素时钟。这个时钟进入 FPGA 的普通 IO 引脚后,进入采集模块,完成 CameraLink 数据的同步采集。
Aurora 用户时钟(USER_CLK)来自 GT Wizard 的输出时钟,频率 = 线速率 /(用户接口位宽 / 8 / 通道数)。配置为 32bit 单通道、3.125Gbps 时,USER_CLK = 3.125×10^9 / 4 = 781.25MHz?不对,这里需要注意,GT Wizard 内部数据位宽可能是 16bit 或 32bit,而 Aurora 核的用户接口位宽再经过一个转换层。实际工程中,Aurora 核输出的 USER_CLK 频率一般是你配置的 GT 内部时钟的一半或四分之一。
举个具体例子,GT Wizard 内部数据位宽设 32bit,线速率 3.125Gbps,则 GT 内部并行时钟 = 3.125Gbps / 32bit = 97.65625MHz。Aurora 核如果配成双通道,用户接口变成 64bit,那么 USER_CLK = 97.65625MHz 不变;如果配单通道 32bit,USER_CLK 也是 97.65625MHz。这个时钟给到应用层,就是跨时钟域处理的终点。
跨时钟域方面,CameraLink 像素时钟域(85MHz)到 Aurora USER_CLK 域(97.6MHz)之间必须加异步 FIFO。在 Vivado 里直接用 Xilinx FIFO Generator IP 核,配置成异步时钟、标准读取模式,数据宽度 32bit,深度建议 2048。为什么需要这么深?因为缓存太浅的话,遇到像素时钟抖动或 Aurora 链路暂时性反压,FIFO 会溢出丢数,帧就花了。
3.5 光模块选型与 SFP 接口电路注意事项
SFP 光模块这边,我踩过不少坑。最重要的一点是:Aurora 8B10B 编码后输出的是标准的串行数据流,光模块本质上只负责电光转换和光电转换,不解析协议。所以任何支持对应速率的 SFP 模块都能用于 Aurora 链路,只要你选的模块速率范围覆盖你的线速率。
具体选型上,3.125Gbps 线速率优先选 2.5G/3.125G 速率的 SFP 模块,这类模块常见的是 850nm 多模,配 OM3 光纤能传 300m,配单模光纤能传更远。如果你的链路距离在 2km 以上,就得选 1310nm 单模模块,这类模块配单模光纤也能用到 10km,只是成本更高。
SFP 接口的电路设计方面,FPGA 的 GT 引脚直接连接到 SFP 连接器的差分信号引脚。需要注意信号完整性,SFP 座的焊盘和 GT 引脚之间的走线必须做阻抗控制,100Ω 差分阻抗是标准,走线长度尽量短,避免接插件和过孔导致的信号反射。如果 PCB 布局紧张,建议在 GT TX 端串联 0.1uF 电容做交流耦合(Xilinx 器件内部已集成 DC 耦合选项,但外部串联电容更保险),RX 端也串联同样的电容。
我遇到过一块板子 SFP 插上后链路一直不稳定,时好时坏。用示波器量 GT 引脚信号,发现眼图明显有塌陷,展开度不够。排查到最后,发现是 SFP 连接器的地引脚没有充分接地,回流路径太长导致的。后来换了 SFP 座,在 PCB 上增加过孔阵列,问题就解决了。这类信号完整性问题在高速设计里非常容易遇到,尤其在 DIY 或小批量板卡上。
4. 四套工程源码的功能划分与核心模块实现
4.1 四套工程源码分别解决什么场景
这套项目一共提供 4 套工程源码,目的很明确:不同工业相机接口配置、不同传输距离和带宽需求下能各取所需。我按场景把它们分成四档。
第一套:CameraLink Base 配置单通道 Aurora 方案。适用于绝大多数标准工业相机工程,例如 Basler acA2500-14um 这类 Base 接口的 500 万像素相机,帧率 14fps 到 30fps,像素时钟 85MHz 以内。这套方案是 4 套中最简单也最容易跑起来的,适合初学者做基础验证和二次开发。
第二套:CameraLink Medium 配置单通道/双通道 Aurora 方案。Medium 的 CameraLink 相机通常应用于分辨率更高、帧率要求更严的场景,比如线阵相机或高分辨率面阵相机。我有的 Medium 相机像素时钟到 60MHz,但有效带宽翻倍到 3.4Gbps,单纯单通道 Aurora 3.125Gbps 不够,需要跑在 5Gbps 线速率,或者双通道绑定。
第三套:CameraLink Full 配置多通道 Aurora 方案。Full 配置相机常见于高端面阵相机,例如大靶面 sCMOS,帧率不是很快但每帧数据量巨大。这种场景必须是双通道甚至四通道绑定,才能跑满带宽。这第三套工程是双通道 Aurora 绑定方案,线速率 5Gbps 两条通道,用户接口 64bit,USER_CLK 依然跑在 100MHz 上下,数据带宽达 10Gbps,余量充足。
第四套:CameraLink Base 配置双通道低延迟增强方案。这套工程解决的场景比较特殊,需要在传输视频流的同时,把相机控制信号(CC1-CC4)和串口数据也透传到远端。比如远程控制相机触发拍照、查询相机状态、修改相机参数,这些功能如果没有独立通道,就得在视频流里插入控制包,增加复杂度。这套工程里我单独划分出一条逻辑通道,用 Aurora 协议中的消息通道(Message Channel)或自定义 K 码实现控制信号的透明传输。
四套工程的 FPGA 逻辑框架是相通的,核心差异在 GT 通道数和 Aurora 核参数配置,以及 CameraLink 解串器芯片的数量。这套框架的复用性很强,你一次学会,后续改参数就能适配不同相机。
4.2 核心模块代码结构解析
拿第一套 Base 配置方案来拆解,FPGA 顶层模块的层次结构和关键代码模块如下。
- camlink_rx_top:CameraLink 接收顶层模块。负责把 DS90CR288A 输出的 28bit 数据 + 像素时钟同步进 FPGA,提取 FVAL/LVAL/DVAL 和像素数据,输出标准视频流接口。
- cl_fifo_wrapper:异步 FIFO 包装模块。封装 Xilinx FIFO IP 核,完成 CameraLink 像素时钟域到 Aurora USER_CLK 域的跨时钟域处理,同时处理写满、读空等状态计数的输出。
- aurora_pkg_top:Aurora 发送/接收顶层模块。实例化 Aurora 8B10B IP 核,把 FIFO 数据映射到 Aurora 的用户接口。发送方向把 32bit 数据写入 s_axi_tx_tdata,接收方向从 m_axi_rx_tdata 读取数据。
- camlink_tx_top:CameraLink 发送顶层模块。接收端从 Aurora 恢复出数据后,重新生成 28bit CameraLink 并行格式和像素时钟,驱动 DS90CR287 芯片输出。
看一下关键接口代码的实现片段,Aurora IP 核例化部分需要注意脱离 IP 核独立仿真的细节:
aurora_8b10b_0 aurora_core ( .s_axi_tx_tdata({data_hdr, pixel_data}), // 32bit 用户数据 .s_axi_tx_tvalid(fifo_dout_valid), .s_axi_tx_tready(fifo_rd_en), .m_axi_rx_tdata(recovered_data), .m_axi_rx_tvalid(rx_valid), .m_axi_rx_tlast(rx_last), .link_up(link_up), .user_clk(user_clk), .reset(reset_n), .gt_qpllclk_quad1(qpll_clk), .gt_qpllrefclk_quad1(qpll_refclk), .gt_rxp_in({1'b0, gt_rxp}), .gt_rxn_in({1'b0, gt_rxn}), .gt_txp_out(gt_txp), .gt_txn_out(gt_txn), .init_clk(init_clk) );这里有几个细节和初学者常掉的坑:s_axi_tx_tdata 接口的位宽要严格和 IP 核配置一致,32bit 就是 32bit,不能 16bit 混用。gt_rxp_in 和 gt_rxn_in 是一组差分信号,如果只用单个通道,高位通道必须接 1'b0(单通道场景),否则会出现链路检测异常。init_clk 一般接 50MHz 或 100MHz 的独立时钟,不能和 GT 参考时钟共用,ICAPE2 等比特流加载和复位逻辑依赖这个时钟。
4.3 发送链路数据封包与接收链路解包的实现逻辑
发送方向的数据封包逻辑,核心工作是把 CameraLink 采集模块输出的 FVAL/LVAL/DVAL 和像素数据封装成 32bit 的 Aurora 用户数据帧。
FVAL、LVAL、DVAL 这三个信号是伴随像素数据同步变化的,在像素时钟域采样。但把它们放进 Aurora 用户数据流时,存在一个时序对齐问题:像素数据和这三个有效信号之间可能有 1~2 个时钟周期的错位。你直接无缝拼接的话,接收端恢复图像时会出现行同步不齐的情况,画面出现撕裂或偏移。
我的处理方式是在采集模块里就把 FVAL/LVAL/DVAL 和像素数据流水线对齐,确保三者严格同步输出。具体做法是把像素数据打两拍缓存,把 FVAL/LVAL/DVAL 同步打拍,直到三者对齐为止。
接收方向的解包逻辑刚好反过来。Aurora 恢复出的 32bit 用户数据,高位提取 FVAL/LVAL/DVAL 状态,低位提取像素数据。注意接收方向也存在一个问题:Aurora 链路刚建立时,接收到的数据流起点是任意的,可能从奇数地址开始。Aurora 核本身会处理字节对齐和通道绑定,但对用户数据的帧起点,我得自己通过检测 FVAL/LVAL 的跳变沿来定位。
实现方式是写一个状态机,等 FVAL 从低到高跳变时,认为这是新一帧图像的起点,从这个位置开始拼接下来的像素数据,同时输出恢复的时序信号。这个方法的好处是即使链路中断后重新恢复,也能迅速重新定位图像帧起点,不会出现画面一直错位的情况。
4.4 双通道绑定与负载均衡的设计要点
第三套和第四套工程涉及双通道 Aurora,双通道绑定看起来只是把 GT 通道数从 1 改成 2,实际上里面有几个坑。
第一个坑是数据分配的粒度。Aurora 8B10B 核的通道绑定机制,处理的是字节级别的交错分发,用户不需要关心具体哪个字节走到哪条通道。但用户接口的位宽必须相应扩大一倍。单通道 32bit,双通道就是 64bit。也就是说,用户接口一个时钟周期要提供 64bit 数据,否则 Aurora 核会反压(backpressure),链路吞吐下来。
在数据源侧,64bit 数据的来源其实就是两个 32bit 的 FIFO 输出,或者一个 64bit 宽度的 FIFO。我用的是一个 64bit 深度 1024 的 FIFO,输入端从 CameraLink 采集模块以 32bit 写入,输出端以 64bit 读出。写满标志拉高时,采集模块暂停写入,防止溢出。Aurora 核的 tready 信号作为读使能,配合实现数据流的供需匹配。
第二个坑是两通道的时延差。每条 GT 通道在接收端的字节对齐延迟可能不同,导致两通道恢复出的数据在时间轴上存在偏差。Aurora 核内部有通道绑定逻辑(channel bonding)来自动补偿这种偏差,但前提是输入到核的 GT 通道配置必须一致,包括参考时钟、线速率、极性设置。
第三个坑是极性设置。如果你的 PCB 布线时 GT 差分对的 P/N 反了,需要在 GT Wizard 或 Aurora 核里配置 TX/RX 极性反转。每个通道可以独立配置极性,这是一个很容易被忽略的细节。双通道的一根线极性接反,最典型的故障现象就是只有一半数据恢复出来,图像只有奇偶行或左右半幅。
5. 系统调试、常见故障排查与工程化经验
5.1 上电初始化顺序与硬件检查清单
上电调试是所有环节里最考验耐心的。我总结了一套硬件检查清单,照着走能少走很多弯路。
先查电源。GT 收发器需要独立的模拟电源(MGTAVCC 和 MGTAVTT),这两个电压的值要严格按照 FPGA 器件手册设置。7 系列 GTX 是 1.0V(MGTAVCC)和 1.2V(MGTAVTT),UltraScale 的 GTH 是 0.9V 和 1.2V。电压差了 10% 以上,链路就可能不稳定。
再查时钟。用示波器量参考时钟引脚,确认频率、幅度、上升沿是否符合要求。参考时钟的焊接不良、串阻过大,会导致 GT PLL 锁不上。
接下来检查 CameraLink 解串器芯片。上电后先看 PIXCLK 有没有输出,如果 PIXCLK 有输出但数据线上全高或全低,大概率是芯片未正确配置或 LVDS 输入线序有问题。检查 DS90CR288A 的 PDB(Power Down)引脚是否拉高,如果悬空,芯片默认进入低功耗模式,数据输出全为高阻态。
SFP 模块方面,插上后看模块的 LOS(Loss of Signal)引脚电平。LOS 拉低表示检测到光信号,拉高表示没信号。如果 LOS 一直是高,先查光纤是否插好、对端是否在发送光信号;如果 LOS 正常但链路还是起不来,就得怀疑 GT 配置有问题了。
5.2 常见疑难问题与排查速查表
调试这套系统时,常见故障大概分成四类,我列了一个速查表,方便你在实验室里按图索骥。
表格如下:
| 故障现象 | 可能原因 | 排查方法与解决方案 |
|---|---|---|
| Aurora 链路 LINK_UP 一直拉低 | GT 线速率与对端不匹配 | 核对两端的线速率和 GT Wizard 配置,务必一致 |
| LINK_UP 偶尔拉高但数据错误 | 光模块型号不匹配或信号劣化 | 换一个 3.125G/5G 速率 SFP 模块,检查眼图 |
| 链路正常但接收图像花屏 | 数据字节顺序错乱或 FVAL/LVAL 对齐异常 | 检查 28bit 拼接顺序,调整数据通道映射关系 |
| 图像只有左半幅或右半幅 | 双通道绑定异常或极性接反 | 检查 GT 通道 polarity 设置,核对 PCB 差分走线 |
| 丢数但无明显规律 | FIFO 深度不够引起溢出 | 加大异步 FIFO 深度到 2048 或 4096,检查反压逻辑 |
| 高低温测试时链路不稳定 | 光模块电源噪声大 | 增加 SFP 供电滤波电容,电源用 LDO 隔离模块 |
第一类故障 LINK_UP 拉不起来,除了参数匹配问题,还有一个隐蔽原因:GT 的参考时钟没锁住。在 Vivado 里调试时加上 GT 的 drp 端口,或者直接用 Xilinx 的 debug 工具观测 QPLL/CPLL lock 状态,比盲猜配置高效得多。我习惯在工程里加一个简单的状态指示模块,把 QPLL lock、GT TX/RX reset done、Aurora link_up 这些信号引到 LED 上,一眼就能看出问题出在 PLL 还是链路层。
第二类故障中,光模块信号劣化是最难查的,因为示波器不一定能直接测量光信号质量。我的办法是用 Xilinx 内部集成的 IBERT 测试(Integrated Bit Error Ratio Tester),在 Vivado 里生成 IBERT 工程,把 GT 通道配成环回测试模式,看误码率和眼图打开程度。如果误码率高于 10^-12,说明链路质量不达标,优先排查光模块和 PCB 的走线。
第三类故障花屏问题,本质上是因为接收端的 28bit 数据和发送端没有对应上。CameraLink 的通道映射顺序在 DS90CR288A 和 DS90CR287 之间是有规范的,但如果相机厂家走的是非标线序,或者通过转接头连接,就可能导致数据位乱序。排查方法是发一个已知图像(比如彩色竖条纹测试图),通过对比发送端和接收端像素值的二进制关系,手工推算出映射关系,然后修改代码里的位映射表即可。
第四类故障双通道绑定问题,最直接的手段是把两个通道分别设置为独立单通道模式,先单独验证每条链路都能正常传输。再设置成绑定模式,如果绑定后数据错位,就检查接收端的通道绑定延迟补偿参数。Aurora 核里面有几个和绑定相关的寄存器,在 Xilinx 文档 PG046 里能找到详细说明,按推荐值配置一般都能解决。
5.3 板级调试经验与信号完整性心得
做这套系统的时间里,我最大的一条体会是:高速链路的问题,百分之八十出在硬件而非逻辑。
比如 GT 通道的 PCB 走线,正因如此,我把能想到的都提前优化了:差分 100Ω 阻抗、走线等长控制在 ±5mil 以内、过孔数量尽量少、信号回路面积不要留太大。这些做不好,再好的 FPGA 代码也白搭。
具体到板卡布局上,SFP 座子尽量靠近 FPGA 的 GT 引脚,减少走线长度和过孔数量。FPGA 到 DS90CR288A 的 LVDS 走线同样要控制阻抗,CameraLink 时钟信号和数据信号之间等长性也要保证。
另外一个细节是地平面的完整性。CameraLink 解串器、GT 收发器、SFP 模块这三个区域的参考地必须完整且连续。如果地平面被电源分割成孤岛,高速信号回流路径断裂,会产生严重的 EMI 和信号串扰。我见过一个案例,SFP 和 FPGA 中间隔了一排磁珠,地平面被切断,结果 3.125Gbps 信号眼图闭到打不开,去掉磁珠后一切正常。
散热也是被忽视的点。高速 GT 收发器发热量不小,SFP 光模块也是发热源,如果板卡放在密闭机箱里,温度一上来误码率显著上升。我推荐在 PCB 上预留散热焊盘,贴上导热垫连接到外壳散热。
5.4 二次开发建议与扩展方向
整套系统跑通之后,扩展空间其实很大。
如果你想接入更多相机,只需要按这套框架再加一路 CameraLink 采集模块和对应的 Aurora 通道,在发送端做个多路数据复用,接收端做解复用。需要注意 GT 通道总数要够用,Kintex-7 325T 这种中等规模芯片有 16 个 GTX 通道,做 4 路 Base 相机转光口也够了。
如果你跑的是 CameraLink 相机,但想支持 PoCL(Power over Camera Link),则需要额外处理供电问题。PoCL 是 CameraLink 标准里扩展的供电方式,利用同一根线缆给相机供电。如果相机是 PoCL 供电,那么系统的 CameraLink 连接器和板卡电源部分必须符合 PoCL 规范,否则插上相机后供电异常。
如果你想把这套系统升级成支持图像处理功能的方案,比如在 FPGA 里加白平衡、坏点校正、ROI 裁剪,再走 Aurora 发送,这个框架也完全兼容。像素数据经过预处理再拼接时序信号即可,地址映射和带宽规划在 CameraLink 像素时钟域内完成即可。
还有一点,是专家系统里经常被问到的一个问题:Aurora 8B10B 能不能对接非 Xilinx 器件?答案是可以,但前提是对端也实现了 Aurora 8B10B 协议的物理层和链路层。有些国产 FPGA 厂商提供了 Aurora 兼容 IP,我在调试中验证过,在速率和参数一致的前提下,跨厂商的 Aurora 链路可以正常建立。但需要注意,链路初始化时间可能比同厂商长一些,接收端的 byte alignment 逻辑需要仔细配置。
6. 写在后面的几点实操体会
在这套系统的调试过程里,我个人经验最深刻的几点,分享给你做参考。
第一,拿到这类项目,第一版不建议追求功能完整。先把单通道 Base 配置跑通,确认 CameraLink 采集和 Aurora 链路都没有问题,再加带宽、加功能。一上来就搞 Full 配置双通道绑定,万一故障出现,排查范围大,容易让人焦头烂额。
第二,仿真很重要,但仿真替代不了上板调试。Aurora 链路初始化时间、GT PLL 锁定时间、SFP 模块的上电时序,这些在行为级仿真里都非常理想化,但实际板上会有各种不确定因素。我的习惯是用逻辑分析仪(ILA)抓关键信号,比如 link_up、fifo_almost_full、gt_txresetdone,结合硬件现象逐步缩小范围。一开始抓一堆信号没有头绪,后来学会分优先级——先确认时钟锁住、链路建立,再看数据流是否正常。
第三,所有复位逻辑必须考虑 GT 收发器的特殊要求。GT 的复位时序在 Xilinx 手册里写得很清楚,复位释放后必须等待 TX Reset Done 和 RX Reset Done 拉高,之后才能开始链路初始化。如果复位逻辑写得太随意,比如在主复位还在拉低时就启动 Aurora 核,链路会一直处于初始化失败状态。
第四,如果你想把这套设计产品化,好版本管理和工程文档要跟上。FPGA 工程的工程文件、约束文件、 IP 核配置导出文件,还有各版本改动记录,全得留好。尤其 IP 核的升级不是简单替换,有时 GT Wizard 版本升级后默认参数变了,链路密钥就对不上了,这在团队协作开发时是很容易踩坑的。
最后再说一个比较冷门的小技巧:Aurora 核的初始化时序中,有一个需要注意的地方是若干个 cycle 的 INIT 时钟。如果 init_clk 频率太低(比如用的低速调试时钟),链路初始化时间会变长,甚至出现超时。建议 init_clk 用 50MHz 或更高,不要和低功耗模式同时使用。
这套系统从原理图设计到最终调到稳定,整体投入的时间比我预想的多一倍。但跑通那一刻,看着光纤链路上流畅输出的图像,前面踩过的坑都值了。希望这篇梳理对你的 CameraLink 转光口项目有实际帮助,有问题随时交流。