☰
FPGA GT IP调试实录:Aurora 64B/66B高速链路从调通到0误码
2026/10/3 7:57:54 网站建设 项目流程

每次想在搜索引擎里敲“GT IP”这几个字,我都得做好心理准备——结果里一半是三菱GT Works3的触摸屏教程,另一半在教你怎么配网络IP地址。我说的GT,是Xilinx FPGA里的高速串行收发器(Gigabit Transceiver);这里的IP,也是Xilinx官方IP核,不是IP地址。最近在一块UltraScale+平台上用GTH把Aurora 64B/66B协议调通了,从最开始的channel_up死活拉不起来,到后来长时间大数据量跑下来误码为0,整个过程挺有代表性。这篇就把调试思路、参数计算和踩过的坑都记录下来,给正在跟高速串行接口较劲的朋友一个参考。

1. 先弄清楚这次调的到底是什么

1.1 GT、IP核、Aurora协议三者的定位

很多刚接触FPGA高速接口的人会把这三样东西混在一起,我简单分一下工。GT是FPGA芯片内部的硬核收发器,负责物理层的串并转换、时钟恢复、编码解码,它决定了你的板子最高能跑多快的线速率。Aurora是Xilinx定义的一套轻量级链路层协议,专门用来在FPGA之间或者FPGA和其他芯片之间搭高速通道。IP核则是官方把GT的配置和Aurora协议栈封装成的一个黑盒子,你在Vivado里例化它,填一堆参数,生成bitstream就能用。

拿公路类比的话,GT是路基和收费站的硬件设施,Aurora是这套公路上的交通规则,IP核则是替你把这套规则落地的施工单位。你真正要做的事,就是选择正确的“通车标准”——也就是编码方式——然后保证路基(时钟、电源、PCB走线)没有质量问题。

1.2 64B/66B编码和8B/10B有什么本质区别

这次调试的主角是64B/66B编码。之前很多场合用的是8B/10B,比如Aurora 8B/10B、PCIe 1.0/2.0、千兆以太网。8B/10B的本质是把每8bit数据扩展成10bit发送,好处是自带直流平衡和足够多的跳变沿,接收端容易恢复时钟和数据,坏处是带宽浪费了整整20%。

64B/66B则是每64bit数据加上2bit同步头,一共66bit发送。同步头“01”表示数据块,“10”表示控制块,接收端靠它快速找到块边界。

[table]

编码方式带宽开销特点典型应用
8B/10B25%(10bit传8bit)直流平衡好,实现简单,有K码控制字符Aurora 8B/10B、PCIe、ETH
64B/66B约3.125%(66bit传64bit)开销低,需加扰保证跳变密度,无K码Aurora 64B/66B、10G/25G以太网
[/table]

64B/66B的问题在于,它不像8B/10B靠编码表天然保证直流平衡,而是靠一个多项式加扰器来打散数据,起保证游程长度的作用。所以它确实更省带宽,但对物理链路质量、参考时钟抖动的要求更高,调起来也比8B/10B麻烦一些。这次调试的目标就是在最终跑出这个高效编码下的稳定链路。

2. 方案选型:为什么选了Aurora 64B/66B而不是别的

2.1 需求场景与备选方案对比

这次做的事是板间大数据量实时传输,源头是一块采集板的ADC数据,需要以极高的速率送到另一块处理板。这类场景有几个特点:数据量大、实时性要求高、不想引入太重的协议栈。备选方案有这么几个,我大致比了一圈。

PCIe的问题在于协议太完整了,枚举、配置空间、中断、DMA一个都躲不掉,光是把PCIE IP配好就要花不少时间,而且在FPGA与FPGA之间通信时并不划断算。以太网倒是通用,但MAC、IP、TCP全套上来以后,线速率一大半被协议头占掉,加上驱动和协议栈的CPU开销,实时性也打折扣。JESD204B主要给高速ADC/DAC用,只能做点对点,一般也就单向,灵活性差一些。

Aurora则刚好卡在中间。它只有数据链路层,没有复杂的网络层,协议头开销几乎可以忽略,配置成简单流式传输以后,FPGA把数据往TX接口一推,对端RX原样收出来,延迟也低。对于“一块FPGA往另一块FPGA灌数据”这种需求,它就是最合适的。

2.2 64B/66B相对8B/10B带来的实实在在的带宽收益

有人可能觉得,既然8B/10B调起来更省心,为什么要用64B/66B?一个最直接的理由是带宽。假设GT物理层都是10Gbps线速率,跑8B/10B时有效数据率只有8Gbps,跑64B/66B则约9.7Gbps。如果算上Aurora头(其实很小),差距就更明显。对大数据量传输的场景,这1.7Gbps的提升是实打实的。

另一个原因是对更高线速率的支撑。8B/10B因为跳变过多,到10G以上时对收发器时钟恢复压力很大,业界基本没有25Gbps的8B/10B方案。而64B/66B因为加扰后跳变均匀,配合GTH/GTY这类高速GT,做到10G、25G都是常规操作。也就是说,选64B/66B这个编码方式,也是在为后续系统升级留余量。

2.3 平台和工具层面的考虑

Aurora 64B/66B这个IP需要在合适的器件上跑。我这次用的是UltraScale+系列的GTH,Vivado 2021.2版本,Aurora 64B/66B核是随Vivado一起发布的版本。这里要注意,7系列FPGA上是没有Aurora 64B/66B核的,7系列只有Aurora 8B/10B,想跑64B/66B得用UltraScale或者UltraScale+往后的平台。这个限制我在最开始没注意到,差点用老平台硬干,后来查手册才发现,白白耽误了半天。

另外提醒一句,有些国产FPGA在兼容Xilinx生态时也提供了类似Aurora的IP,但命名、时序、配置方式都可能不同,直接拿这篇的方法套不一定能跑通。遇到具体情况还是以对应厂商的手册为准。

3. IP核例化与关键参数配置

3.1 打开配置界面后要关心的选项

Vivado里例化Aurora 64B/66B的时候,配置界面会有一堆参数,第一次看容易懵。我按优先级整理一下,先关心这几个:

线速率(Line Rate)是第一个要定的。它直接决定你的GT物理层跑多快,一般根据实际吞吐量需求来定。我做的是10.3125Gbps,因为板上的光模块和参考时钟都是按这个速率设计的,如果换速率,光模块不一定能撑住。

第二个是参考时钟频率(Reference Clock Frequency)。GT需要一个干净的参考时钟来驱动内部PLL,频率必须和线速率匹配。我在这次配置里用的是156.25MHz,正好满足156.25MHz × 66 = 10.3125GHz的关系。

第三个是数据流模式。Aurora 64B/66B支持流式(Streaming)和帧式(Framing)两种模式。流式简单直接,适合像我这样只要源源不断传输数据的场景;帧式可以携带通道号、字节序等额外控制信息,适合有较多控制需求的场景。我选了流式,因为采集数据是连续不断的,不需要复杂的帧结构。

用户接口数据位宽也得关心,常见的有64bit、128bit、256bit。位宽越大,用户时钟越低,时序越容易收敛,但跨时钟域的处理也越麻烦。我在这次用了64bit位宽,对应内部时钟156.25MHz,这个时钟频率在时序上很宽松。

3.2 时钟树和复位时序的设计

调Aurora的人十有八九要栽在时钟和复位上,我也没例外。先说时钟。Aurora核需要一个用户时钟(user_clk),这个时钟必须从GT的恢复时钟(rxoutclk)派生,不能随便用一个系统时钟顶替。因为我是在链路建立起来之后才读写数据,用户时钟必须跟着接收端的恢复时钟走,才能保证基元里的FIFO不出现溢出或读空。

用户时钟频率的计算公式是:线速率 × (64/66) / 用户数据位宽。以我的配置为例:10.3125G × (64/66) / 64 ≈ 156.25MHz。这个数很好记,因为10.3125G的“有效数据率”恰好约等于9.7Gbps,再除以64bit位宽,正好156.25MHz。

复位方面,Aurora核的复位信号要满足它的最小脉冲宽度,并且在参考时钟稳定之后才能释放。我刚开始图省事,直接把系统上电复位接到了核的reset引脚上,结果链路一直起不来。后来老老实实按手册要求,先把参考时钟锁定,再等几百微秒,然后拉低复位,链路就正常了。

3.3 接口信号与example_design的改造

Aurora 64B/66B核对外接口是AXI4-Stream风格。常用的几个信号,发送侧是s_axi_tx_tdata、s_axi_tx_tvalid、s_axi_tx_tready,接收侧是m_axi_rx_tdata、m_axi_rx_tvalid、m_axi_rx_tready。链路状态信号是channel_up和lane_up,这两个信号不拉高,后面一切免谈。

生成IP后,Vivado会给一个example_design工程,里面通常自带一个数据生成和校验模块。第一次上板建议直接跑example_design的loopback模式,让发送数据和接收数据在核内部或者板级回环,看误码是不是0,这样能先排除你自己的逻辑问题。我是在example_design跑通之后,再把自己的数据源和下级处理模块替换上去,这样每一步出问题都能很快定位。

4. 上板调试全流程记录

4.1 第一阶段:先用IBERT验证物理层

这是一个我吃了不少亏才学乖的步骤:先过物理层,再跑协议层。刚上手时我跳过IBERT直接调Aurora,结果channel_up起不来,我调了大半天都没搞清楚是协议问题还是硬件问题。后来查下来发现是一根射频线没接好,GT根本没收到信号。如果先用IBERT扫一遍,这个问题一分钟就能发现。

IBERT是Xilinx官方提供的一个物理层调试IP,你可以在Vivado里生成一个IBERT核,下载到板子上,然后在Hardware Manager里实时看到每个GT通道的误码率和眼图。实际操作中,我在IBERT里跑了10.3125Gbps的PRBS伪随机序列,发射端在上,接收端在下,观察到误码率低于1E-15,眼图张开度也不错。这一步确认了GT的TX和RX都是好的,才进入协议层调试。

4.2 第二阶段:核内部回环验证Aurora

物理层过了以后,下面就是让Aurora核自己跑起来。先在核配置里打开内部PMA回环(near-end PMA loopback),让发送数据不经过光模块,直接在GT内部回到接收端。这样即使没有任何外部线缆,链路也能建立起来,方便验证IP核自身是否正常。

上板后观察channel_up信号,正常几毫秒内就拉高了。这一步说明Aurora核的复位、时钟、编码同步都没问题。然后我使用example_design自带的测试模块,发送递增数据,接收端校验,跑了几分钟,错误计数一直是0。这时候可以断定Aurora核本身工作正常,问题只可能在外部物理链路和自己的用户逻辑里。

4.3 第三阶段:外部回环与板间点对点

核内部回环跑通之后,接下来是外部回环。我在板子上的SFP+笼子里插入了一个回环模块(或者用一根短DAC线缆把TX和RX连起来),这样数据会真正经过光模块和线缆往返,物理链路质量也能顺带验证。

这个阶段最容易发现的问题是通道极性。如果GT的TX正负端和RX正负端在PCB上交叉了,通道是起不来的。遇到这种情况,要么改PCB,要么在Vivado里把GT的极性取反配置打开。我这次就用到了极性取反,对应选项叫TX/RX Polarity Invert,在核配置里勾一下就能处理。

外部回环通了以后,就是最终的板间点对点。我把Aurora IP接到自己的用户逻辑上,发送侧按设计的数据格式组帧,接收侧解析并统计误码。整个过程中间还出了一次字节序问题,数据能通,但内容不对,排查过程放到下一章讲。

5. 踩过的坑和常见问题排查

5.1 channel_up拉不起来的几类原因

channel_up是Aurora链路建立的核心信号,它不拉高基本就不用继续调了。我总结了一下常见原因,按概率排序:

第一类是物理层问题,比如GT没收到参考时钟、光模块没插好、线缆损坏、差分极性接反。这类问题IBERT一测便知,IBERT都过不了就老老实实查硬件链路。

第二类是复位和时钟时序问题。复位拉得太短、参考时钟不够稳定就释放复位、或者用户时钟不在规定频率上,都会导致初始化失败。

第三类是参数配置不匹配。两端如果线速率、参考时钟、数据位宽不一致,链路压根不可能建立。前期核对配置表的时候,要仔细确认这些参数在两端完全一致。

5.2 数据字节序和位序问题的排查

链路建起来了不代表万事大吉,我第一次跑点对点,发现接收到的数据“看起来”是对的,但按字节解析出来的数值全都不符合预期。一开始以为是信号处理算法错了,排查了半天才想到可能是字节序问题。Aurora 64B/66B接口的数据在跨到用户逻辑时,存在大小端和对齐的问题。Aurora核的数据位宽是64bit,它把8个字节打包成一拍,接收端把这拍数推给你的时候,先到的字节到底放在低位还是高位,跟发送端怎么打包有关系。

排查办法很简单:发一个固定的递增字节序列,接收端解析出来看是正序还是反序,如果是反的,在发送侧做个字节重排就解决了。这个坑看着小,但特别容易和业务逻辑问题混淆,建议现在项目一开始就定好数据字节序规范,避免后期返工。

5.3 误码率忽然飙高怎么办

我的板间点对点调通之后,有一个现象让我头疼了一阵:短时间跑着没问题,跑上十几分钟偶尔会跳出几个误码。这种偶发误码相当难查,因为用ILA去抓,抓到的时候误码已经发生了,现场没了。

排查思路是先从物理层入手。我用IBERT开了长时间误码率测试,连续跑了一晚,发现GT本身的误码率其实很低,说明物理层问题不大。那问题就很可能在跨时钟域和数据校验逻辑上。我检查了Aurora核和用户逻辑之间的FIFO设计,发现FIFO的读写指针在某些边界情况下处理得不够严谨,修掉之后误码问题就没再出现。这里也要提醒一句,不要在用户逻辑里用异步信号直接采Aurora接口的同步信号,容易引入亚稳态,要用标准跨时钟域处理。

5.4 常见问题速查表

[table]

现象可能原因排查方向
channel_up不拉高GT物理链路问题、复位时序不对、参数不匹配先跑IBERT验证物理层,再检查复位与配置
lane_up拉高但channel_up不拉高多通道绑定失败、跨通道时钟偏差太大检查通道间偏斜,看是否需要内部补偿
数据能通但内容不对字节序位序问题、用户逻辑解析错误发送递增pattern,确认字节顺序后做重排
偶发误码物理链路质量差、跨时钟域处理不严谨长时间IBERT跑眼图,检查FIFO和CDC设计
GT时报PLL解锁参考时钟频率不匹配、时钟抖动过大用频谱仪或示波器检查参考时钟,核对倍频关系
[/table]

5.5 调高速接口的几个通用习惯

最后分享几个这次调试下来养成的习惯。一是在改动任何Aurora核配置或硬件接线之后,先用IBERT快速验证一遍物理层,不要直接赌协议层能通。二是给每个重要的信号留出ILA探针,比如channel_up、lane_up、tvalid、tready,链路一旦出问题首先抓波形,而不是拍脑袋猜。三是老生常谈但真的重要:检查板卡供电是否干净,GT通道附近的电源纹波影响很大,之前有一次误码率跟电源纹波强相关,换了个电源方案之后链路稳定多了。

回到开头说的,搜索“GT IP”能搜出一堆三菱触摸屏和网络IP文章,说明做这个方向的人相对少。但恰恰因为少,能跑通的经验才更有价值。Aurora 64B/66B这套链路一旦建立起来,后续加协议、加通道、提线速率都是水到渠成的事。这次调试记录到这儿,后面如果再碰到其他有意思的坑,我再单独写一篇分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询