ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FPGA高速串行通信:Aurora 64B/66B IP核从配置到调试完整指南

FPGA高速串行通信:Aurora 64B/66B IP核从配置到调试完整指南 做FPGA高速串行通信的同学几乎都绕不开Aurora这个协议。你项目文档里可能见过它也可能在别人工程里瞥过一眼那个叫aurora_64b66b的IP核但真轮到自己打开Vivado从零开始配一个64B/66B版本的Aurora才发现坑比想象中多得多。参数选项卡一大堆GT参考时钟要自己算example design仿真起来还不知道到底要跑多久才算通更别提上板之后channel_up拉不高、DRC时不时给你来一个RTSTAT-2真的会把人逼疯。这篇文章就按我实际调板子的经验把Vivado里配置Aurora 64B/66B IP核的完整过程捋一遍从协议思路、IP参数怎么选到example design仿真怎么看结果最后上板调试会遇到哪些经典问题一次讲清楚。适合刚接触高速串口通信、准备在两个FPGA之间或FPGA与光模块之间做高速数据传输的工程师。内容偏实操我会尽量把你可能踩的坑提前标出来。1. 为什么是Aurora 64B/66B协议基础与选型思路1.1 64B/66B到底比8B/10B强在哪很多做嵌入式或FPGA的同学对Aurora的第一印象可能还是老掉牙的8B/10B版本。8B/10B编码每一项8比特数据都有对应的10比特传输码型冗余比例是20%也就是说跑10Gbps的链路实际有效数据带宽只有8Gbps。而64B/66B把64比特数据打成66比特块只加2比特同步头冗余比例不到5%有效带宽接近97%。同样跑10Gbps64B/66B能比8B/10B多传差不多1.8Gbps的有效数据这个概念在白牌交换机、视频传输、数据采集这些高带宽场景里就是实打实的收益——要不怎么SATA、PCIe、10G以太网这些高速接口后来都往64B/66B或者更高级的编码方向走。Aurora 64B/66B在Xilinx FPGA里就是基于这个编码思路实现的串行协议它依赖GTX/GTH/GTY这种高速收发器来做物理层。你只需要关心用户侧数据怎么发、怎么收编解码、加扰解扰、通道对齐、时钟恢复这些事情IP核基本都帮你搞定了。1.2 IP核内部到底是怎么工作的虽然我们大多数时候只是配置和使用IP核但至少要大概知道它内部结构否则调起错来毫无头绪。Aurora 64B/66B IP核从底层往上大致分三层物理层就是GT收发器负责把并行数据转成高速差分串行信号同时完成时钟恢复链路层负责通道初始化和对齐把多个lane的数据绑在一起保证收发双方侧的数据分界完全一致用户接口层提供简单的AXI-Stream或者类FIFO接口供你的业务逻辑收发数据。在调试时你最需要关注的信号就是channel_up和lane_up。lane_up表示每条lane完成对齐channel_up表示整个Aurora通道建立成功。只有channel_up拉高之后用户数据才能正常传。这个信号一旦起不来问题基本集中在物理层连接、GT参考时钟、两端参数不匹配这几类原因上后面我详细说。1.3 选64B/66B之前想清楚这几点64B/66B虽然效率高但并不是无脑闭眼选。第一次做Aurora调试我建议你评估一下自己的场景如果是两个FPGA板卡之间高速互联且带宽需求超过5Gbps直接用64B/66B效率高很多。如果只是低速控制信号、几十Mbps级别的板间通信Aurora的配置和调试成本偏高不如SPI或者LVDS简单。如果链路要跨越很长距离或者要过连接器、背板优先考虑带均衡的GTAurora本身也支持TX预加重、RX均衡这类信号完整性补偿但物理设计的压力并不会因为协议简单而消失。一句话总结64B/66B适合“高带宽、板间/芯片间近距离、逻辑简单”的场景。至于具体该选Streaming还是Framing模式下一节跟着IP配置一起讲。2. Vivado中Aurora 64B/66B IP核的创建与参数配置2.1 从IP Catalog找到并创建IP打开Vivado工程在Flow Navigator左侧找到IP Catalog搜索“Aurora”会看到“Aurora 64B/66B”这个IP核。双击创建设置好组件名称比如aurora_64b66b_0然后进入自定义配置界面。这一步看起来简单但有一点要注意Aurora 64B/66B不是在每个器件型号上都有。如果你用的是老一些的7系列GTX资源就支持如果是UltraScale系列通常用GTH或GTY。你新建IP时如果发现某些线速率选项灰掉大概率是器件型号不支持换一个更高端的器件型号再看就好了。2.2 关键参数逐项拆解线速率、参考时钟、GT类型配置界面第一页主要是物理层参数重中之重是下面这几个Line Rate线速率线速率就是GT收发器串行链路上的比特率。常用值有5.0Gbps、6.6Gbps、10.0Gbps等具体要看你的板卡GT最高支持多少。7系列GTX通常到12.5GbpsUltraScale的GTH到16.3Gbps左右再往上要上GTY。我实际调试用的是一块搭载7系列GTX的板子最常用的一个组合是Line Rate 5.0Gbps、GT Refclk 125MHz、User Interface Streaming、Data Width 32bit后面所有示例都按这个组合来讲。GT RefclkGT参考时钟GT本身的PLL需要外部提供一个参考时钟最常用的是125MHz或156.25MHz。选多少取决于线速率能否用这个频率整数倍频得到。比如5Gbps线速率配合125MHz参考时钟内部PLL做40倍频就出来了10Gbps也可以用125MHz做80倍频但有些GT型号对倍频范围有限制就要换成156.25MHz做64倍频。具体选哪个板卡上哪个频率的晶振或时钟芯片接入了MGTREFCLK引脚就用哪个不是你想用多少就多少。注意Aurora 64B/66B IP配置界面里会让你选GT参考时钟来源是MGTREFCLK0还是MGTREFCLK1对应的就是GT Quad的专用参考时钟引脚。这一点和你上板调试息息相关如果选错了通道后面物理上根本没时钟进来。GT TypeGT收发器类型这个一般不用手动选Vivado会根据器件自动带出。你只需要确认和板卡实际使用的GT位置一致即可如果自动识别的GT类型和你板卡实际不同后面布线会有大量DRC报错。2.3 数据接口选择Streaming、Framing与用户接口位宽配置界面的Data Flow和User Interface这组选项决定了你业务逻辑和IP核之间以什么形式交换数据。Data Flow Mode有Duplex双工、Simplex单工等选择最常见的就是Duplex收和发同时工作。Simplex适用于纯单向传输比如一个只发、一端只收的采集系统可以节省部分资源。User Interface框架强烈建议第一次用的人先选Streaming模式。Streaming模式下IP呈现给你的接口就是经典的AXI-Stream形式的收发通道你只需要把数据往s_axi_tx_tdata上一放、tvalid一拉另一端接收侧等m_axi_rx_tvalid有效后把数据读走就行像水流一样不需要关心帧结构。而Framing模式多了一套帧定界逻辑给你增加了一些控制信号比如帧起始、帧结束适合需要按包传输、对帧格式有控制需求的场景。但Framing模式带来的额外工作量和排查难度都明显升高我用过一次后就记住了没有十足把握先别一上来就用Framing。Data Width用户接口位宽位宽直接决定user_clk频率。一次处理的数据位宽越宽user_clk频率就越低时序压力越小。常见的32bit、64bit都有人用。我们算一下就很清楚了线速率5Gbps在64B/66B编码下有效载荷数据率约5Gbps × 64/66 ≈ 4.85Gbps。如果用户接口64bituser_clk 4.85Gbps / 64bit ≈ 75.8MHz如果用户接口32bituser_clk ≈ 151.5MHz。Vivado在IP里会自动帮你生成合适的user_clk但我们心里要有这个大概换算方便规划用户侧FIFO位宽和跨时钟域逻辑。2.4 流量控制与校验选项哪些能开哪些尽量别碰Aurora 64B/66B在配置页面里还会有Flow Control相关的选项。默认的代码流控Code-based Flow Control是我们经常用到的。它用的是IP核内部的流控代码集一旦接收端FIFO快满就会自动反向发送流控代码让对端暂停发送。这个在绝大多数场景下可以保持默认打开能避免数据溢出丢包。还有一个用户流控User Flow ControlUFC是针对用户自定义流控帧的扩展机制。我个人的经验是如果只是传数据流UFC可以关闭。开了UFC你需要处理额外的用户流控接口和一个独立的小数据通路复杂度会明显增加排查问题时多一个变量。Aurora协议本身已经有流控机制兜底不到特殊需求不用碰UFC。校验方面IP会提供hard_err、frame_err等错误指示信号。调试阶段强烈建议全部拉出来接ILA或者直接引到LED很多链路问题都是靠看这几个错误信号定位的后面会细讲。3. 用Example Design把链路“点亮”仿真篇3.1 一键生成Example Design工程配置完IP后在IP Sources窗口里找到你生成的Aurora IP右键选择Open IP Example Design。Vivado会询问你工程保存路径通常放到一个独立目录避免和主工程混在一起。生成出来的example design工程里顶层已经帮你把GT参考时钟、复位逻辑、用户数据生成器frame_gen和用户数据校验器frame_check都接好了还有一套完整的仿真测试平台。这一步做的所有事情都是为了让你先不写一行业务代码就能在仿真里看到channel_up拉高、数据正确收发。这个Example Design是调试Aurora最重要的参照物不要关掉。后面你自己写用户逻辑时直接照着它的顶层模块往外改比自己凭空例化IP要稳得多。3.2 仿真跑起来后重点观察哪几个信号在Vivado里对example design直接Run Simulation等仿真推进一段时间后会看到几个关键信号变化gt_pll_lockGT的PLL锁定信号一般最先拉高代表参考时钟和PLL配置没有问题。lane_up每条物理lane的对齐完成信号。64B/66B链路建立过程中需要收发双方交换初始化序列这个过程需要一定时间。channel_upAurora通道整体建立成功。这个信号拉高是真正可以传用户数据的前置条件。frame_err/hard_err数据校验和硬错误信号正常应该一直为低。现在问题来了很多新手在example design里跑仿真等了半天也没看到channel_up拉高然后就开始怀疑人生。其实大概率只是仿真时间太短。Aurora链路初始化包含模块同步、通道对齐多个阶段在仿真里可能需要几百微秒甚至毫秒级别的时间。默认仿真时间经常只有10us或者几十us当然看不到channel_up。我自己的做法是直接看testbench顶层里的仿真时长设置或者运行仿真的脚本里对应的run -all时间直接改成比如200us、500us。64B/66B的example design仿真一般跑个一两百微秒channel_up就会拉起来了耐心等就行。3.3 仿真过程中我见过的几个翻车现场仿真阶段最常见的坑不外乎下面几种复位时间不够。example design的复位模块里一般会有计数器强制拉长复位时间确保GT和IP内部状态机全部归零。如果你自己写了testbench只给一个极短的复位脉冲就想让Aurora正常启动那channel_up基本不会起来。这个IP的复位信号至少要保持几个us我会习惯性把它拉到10us以上再释放。仿真时钟频率和IP配置不一致。Aurora IP生成时有个init_clk参数通常是50MHz或100MHz你的testbench里给这个时钟的频率要和IP配置完全一致。否则内部初始化状态机跑到一半就乱掉最终表现就是channel_up永远低。强行修改example design导致链路建立条件被破坏。有些人觉得example design生成的数据流太简单想直接替换成自己的数据模块结果无意中把链路初始化状态的握手逻辑改坏了。我建议仿真验证阶段先保持example design原封不动等链路通了之后再一点点加入自定义逻辑。4. 上板调试从constraint到channel_up拉高的完整过程4.1 约束文件DRC RTSTAT-2只是开始仿真通过只是第一步上板之后才是真正的硬仗。把example design综合、实现、生成bitstream这条路首先要过约束这一关。Example Design生成时自带了一套完整的XDC约束文件里面包含了GT位置、参考时钟引脚位置等。但当你在自己的工程里例化Aurora IP时这些约束不会自动搬过来需要你自己整理。很多DRC报错就是从这个环节冒出来的。最典型的报错就是开头提到的DRC RTSTAT-2。看到它时不要慌本质上是说有一路时钟没有走专用时钟资源导致MMCM/PLL无法获得稳定输入。在Aurora工程里这种情况通常出现在GT参考时钟上——你把参考时钟信号放到了普通IO引脚或者从逻辑内部产生了一个时钟驱动GT而不是让外部时钟芯片输出接到MGTREFCLK专用引脚。解决办法是检查XDC里MGTREFCLK引脚的PACKAGE_PIN是否锁在对应GT Quad的专用参考时钟引脚上并把时钟约束正确地创建成primary clock。有些板卡还需要你在原理图上确认参考时钟芯片有没有被正确配置否则引脚对了时钟芯片不输出也是白搭。提示RTSTAT-2的另一类来源是用户逻辑里把高速时钟经过普通BUFG或者逻辑倍频后又接到GT的PLL上。GT参考时钟必须是外部晶振/时钟芯片直接到MGTREFCLK然后经过GT内部专用时钟路径进入PLL任何普通逻辑绕一圈都不行。4.2 上板先看硬件状态不要一上来就抓数据bitstream下载进去之后第一步不是关心数据对不对而是先把下面几个信号拉出来看gt_pll_lock是否拉高。如果拉不高先查GT参考时钟是否真的进了芯片建议用示波器或逻辑分析仪确认板卡上的MGTREFCLK引脚有信号、频率正确、幅度足够。各lane的GT TX/RX reset_done是否拉高。reset_done没有拉高说明GT内部复位流程都没走完。channel_up是否拉高。这一步是核心大多数板级问题都集中在这里。我之前调试过一块板子FPGA配置好后gt_pll_lock始终不拉高。查了半天发现参考时钟芯片是I2C可编程的板子上电后默认寄存器配置不对根本没有输出125MHz时钟。后来在FPGA里用I2C控制器先初始化了时钟芯片再让FPGA重新配置GT问题立刻消失。所以遇到PLL不锁先别急着改代码从头到尾检查一下时钟链路。调试硬件管理器不一定要打开完整版Vivado工程如果你只是需要下载bitstream、看信号电平直接用Vivado Lab Edition打开Hardware Manager就够了启动快、占资源少。等确认通道建立没问题再回完整版工程里做正式验证。4.3 复位时序Aurora最不讲道理的一环Aurora IP的复位信号port_reset是异步复位、同步释放的逻辑但对复位时序的要求很严格必须在GT参考时钟和init_clk都稳定之后才能释放。很多人直接用一个按键复位接到port_reset上电瞬间按键复位倒是没问题但GT时钟还没稳定Aurora的初始化序列可能已经错乱了之后哪怕你再松开复位链路也建立不起来。最安全的做法是参考example design里的复位模块它用一个计数器先强制拉低所有复位一段时间等到init_clk稳定后再释放同时监听GT的reset_done信号等它拉高了才认为GT复位完成。这个逻辑其实不复杂但非常重要。我踩过坑之后已经养成习惯了所有Aurora相关的复位一律拷贝example design里的复位模块不自己造轮子。另外一个细节复位释放之后链路建立不是瞬间完成的。64B/66B协议里发送端会持续发送初始化序列接收端需要检测到多个连续有效序列才认为通道对齐。这个过程从几十微秒到几毫秒都有可能取决于线速率和GT参考时钟。所以上板调试时如果channel_up不是立刻起来先等几秒再下结论。4.4 用户逻辑接入握手机制不能想当然channel_up拉高之后你已经可以在example design里看到frame_gen和frame_check在收发数据了。但替换成用户自己的逻辑时又有一批问题冒出来。务必使用user_clk。Aurora IP会生成一个user_clk输出所有用户侧接口信号s_axi_tx_tdata、s_axi_tx_tvalid、m_axi_rx_tvalid等都必须由这个user_clk驱动或采样。有人图省事直接用了系统时钟100MHz接收数据偶尔对偶尔错查都查不出来。本质上是时钟域没有对齐。注意AXI-Stream握手。发送端口有s_axi_tx_tready你tvalid拉高的同时必须等tready为高才算真正发送成功接收端口m_axi_rx_tvalid拉高时必须在同一个时钟沿把m_axi_rx_tdata采走。如果接收侧没跟上数据就会丢失。我自己写发送侧状态机时习惯用一个简单的FIFO先缓存业务数据再按tready节奏慢慢发避免突发写入导致握手失败。frame_err和hard_err要连出来。哪怕你只是调试一个简单点灯也建议把这两个错误信号引到ILA或者GPIO。它们能告诉你链路是完整不通、还是通了但数据出错、还是物理层硬错误。不同错误对应完全不同的排查方向没有这两个信号你只能靠猜。4.5 上板验证流程我通常这么走给一个我自己习惯的上板验证顺序照着做至少能少走一半弯路先把example design原封不动生成bitstream下载确认channel_up能拉高frame_err始终为低。把板卡上Aurora发送端和接收端逻辑调换成你的简化版用户逻辑比如发送一个固定递增数接收端检查是否正确。在用户逻辑里加入ILA观察发送数据、接收数据、tvalid/tready握手信号。最后再把速度跑满做长时间压测看有没有偶发的hard_err或者数据丢弃。这套流程的核心原则是“一次只改一个变量”。如果example design都通不过那问题基本不在你的用户逻辑上而是在板级物理环境或IP配置上如果你逻辑替换后出问题问题基本就在握手和时钟域上。5. 常见问题与排查技巧实录一张速查表Aurora的调试问题看起来千奇百怪其实归纳下来就那么几类。我把这几年我实际遇到比较多的问题汇总成了一张速查表不只是告诉你怎么改还会解释一下背后的原因方便你自己举一反三。现象可能原因排查与解决办法仿真时channel_up一直为低仿真时间太短复位时间不足init_clk频率和IP配置不一致延长仿真时间到200us以上把复位时间加到10us检查testbench时钟频率与IP init_clk配置匹配上板后gt_pll_lock不拉高GT参考时钟没有输出参考时钟引脚接错时钟芯片未初始化示波器确认MGTREFCLK频率和幅度检查XDC中引脚是否锁定在对应Quad用I2C初始化时钟芯片上板后lane_up不拉高两端的lane数或线速率不一致光纤/连接器没插好发送端没有发出初始化序列确认两端IP参数完全一致检查SFP/QSFP光模块光功率检查发送端GT TX reset_done是否正常channel_up拉高但数据全错跨时钟域问题用户接口位宽不匹配发送端和接收端数据流控不一致确认用户逻辑全部使用user_clk确认两端Data Width一致检查AXI-Stream握手信号时序frame_err一直为高链路质量差发送数据格式和Framing模式不匹配踩了流控的边界检查物理连接和信号完整性如果是Framing模式检查帧头帧尾信号考虑把UFC关闭hard_err一直为高物理层误码严重GT参考时钟抖动太大线速率超过板卡材料能力降低线速率试一下换成质量好的线缆/光模块查看板卡GT的RX眼图综合/实现时报DRC RTSTAT-2参考时钟未走MGTREFCLK专用引脚GT时钟路径上有普通逻辑检查XDC中MGTREFCLK的引脚约束确认时钟芯片输出直接连到GT专用引脚不要用BUFG再接到GT PLL误码率随运行时间缓慢上升温度导致GT参数漂移时钟源长期不稳定用户逻辑FIFO溢出长时间压测观察温度检查FIFO深度和水线设置适当降低线速率留余量这里面有两条是我觉得最容易被人忽略的。第一条两端线速率和Data Width必须完全一致。Aurora链路两端如果线速率不同GT的PLL没法定频channel_up根本不可能拉高。有些板卡你可能用的是Aurora 8B/10B另一端用的是64B/66B那协议类型都不一样当然也连不上。这类问题最气人的是它不会给你任何明确报错你只能一个参数一个参数去核对。第二条不要轻视电源和时钟质量。Aurora跑在5Gbps以上时GT对参考时钟的抖动非常敏感。125MHz时钟从时钟芯片出来如果经过较长的走线再经过连接器很容易带上噪声。板级设计上用差分走线、加端接、参考时钟走线远离高速串行线这些硬件侧的细节虽然不属于代码范畴但会在误码率上十倍百倍地暴露出来。最后再分享一点个人经验如果你正在准备的第一个Aurora项目我劝你把心态放平。我第一次调Aurora 64B/66B的时候光是channel_up拉不起来就折腾了整整两天最后发现是SFP笼子上的光模块没有插到位纯硬件问题代码一行没改。后来我总结出经验调试高数串口永远先把物理层、时钟、复位这三件事排干净再去看协议和逻辑。如果你能拿到一块官方开发板强烈建议先在官方板上用example design把链路跑通感受一下正常的channel_up拉高需要多长时间、哪些信号应该在什么顺序出现再去啃自己画的板子。如果一开始就在自制板上做硬件和逻辑的问题混在一起排起来非常消耗耐心。最后再说一个我自己很受用的小技巧把channel_up、hard_err、frame_err、gt_pll_lock这几个信号不管调试哪个模块都固定引到一组GPIO上接个LED。别看就这么一个小动作很多时候你写代码写烦了余光瞄一眼LED就知道链路有没有掉线比翻ILA波形快多了。这组LED我用到现在已经成为所有高速串口工程的保留节目了。
返回列表