做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直接转 | FPGA+CameraLink接口芯片+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到85MHz;28位并行输出的映射关系必须查数据手册,因为它不是简单地把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.38Gbps,Aurora 8B10B编码有25%开销,所以GT线速率至少要大于2.38/0.8=2.975Gbps。标准线速率选型里3.125Gbps是最合适的,既满足带宽需求,又在GTX的最佳工作区间内。如果选2.5Gbps线速率,有效带宽只有2.0Gbps,跑60fps 2048x2048的8位图像时大概率会丢帧,这个是最容易踩的坑。
参考时钟的选择要和线速率匹配。对于GTX,3.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.5Gbps,32位用户接口对应的用户时钟就是2.5G/32=78.125MHz。你后续做FIFO读写位宽匹配时,要严格按照这个78.125MHz来规划,不能想当然用80MHz或者75MHz,否则长期运行后会偶发溢出或者读空。
3. 四套工程源码的分工与设计思路
3.1 四套工程的整体规划
拿到一个FPGA高速接口项目,我最忌讳的就是一上来直接写完整逻辑,然后一次上板调通。GTX和Aurora本身就要分阶段调试,CameraLink数据帧格式也需要逐步验证,所以我把整个项目拆成了4套工程,从简到繁,每套工程都是前一套的增量迭代。我建议你也按这个思路来管理自己的项目,真的能省掉大量联调时间。
| 工程编号 | 工程内容 | 核心验证目标 |
|---|---|---|
| 工程1 | CameraLink接收 + Aurora光口发送 | 验证CameraLink解串、数据打包、GTX发送链路 |
| 工程2 | 光口回环自测 + 误码统计 | 验证GTX物理层可靠性和Aurora链路稳定性 |
| 工程3 | 增加BMP图片抓帧与PC端显示 | 验证图像数据格式正确性、上位机对接 |
| 工程4 | 增加DDR3缓存 + 多帧连续传输 | 验证突发带宽、跨时钟域大缓存和长时间稳定性 |
3.2 工程1:CameraLink接收 + 光口发送
工程1是整个方案的骨架,只做一件事:把CameraLink相机进来的数据送到光口发出去。
模块划分上包括顶层的camlink_to_sfp_top,下面挂了cam_link_rx(DS90CR288A数据采集)、frame_pack(把28位并行数据转成32位对齐的传输格式)、async_fifo_32x1024(跨时钟域)、aurora_8b10b_0(Xilinx 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.125MHz;
- Interface模式:选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.125MHz(Aurora用户时钟)。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参考时钟或者复位时序问题。
第三步是用IBERT(Integrated Bit Error Ratio Tester)独立验证GTX物理层。IBERT是Vivado自带的一个调试工具,可以生成误码率测试的bit文件,在硬核里产生伪随机序列并通过环回方式统计误码。我习惯在任何Aurora项目里都先把IBERT跑一遍,20分钟能解决的物理层问题,比在复杂逻辑里排查一整天强得多。
我实测的这套方案,CameraLink输入用Basler的2048x2048@60fps相机,像素时钟85MHz,SFP用千兆多模模块加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链路通但数据乱码的处理
Q:channel_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自动找到最佳采样点,能彻底解决这个问题。
Q:SFP光模块不发光或者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 UltraScale+,IP配置虽然要跟着调整,但模块架构和代码风格基本可以平移。
最后再说个实际体会。我踩过最大的坑是在工程2阶段,当时Aurora光口环回一切都正常,一接上真实相机就开始偶发丢帧。查了很久发现是FPGA内部一个跨时钟域的握手信号没有做同步处理,导致帧计数器偶尔跳变。这种问题纯靠看代码很难发现,最好在SignalTap里同时观察FIFO水位和帧计数,异常时立刻能看出来。FPGA高速传输项目,链路层只要按官方文档做基本都稳,真正容易出问题的往往是你自己的用户逻辑和跨时钟域处理,所以每一层都要留足验证手段,不要指望一次全部调通。