ARTICLE DETAIL

资讯详情

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

FPGA高速互联实战:Aurora 8B/10B IP核配置与调试全解析

FPGA高速互联实战:Aurora 8B/10B IP核配置与调试全解析 去年帮客户做一块多通道高速采集板第一版方案用LVDS并口把ADC数据搬到主控FPGA32对差分线在PCB上绕得我头大实际传输带宽跑到800Mbps左右就再也上不去了。后来我把方案整体改成Xilinx的Aurora 8B/10B IP核一对差分线轻松跑到5Gbps传输时延降到了微秒级以下。从那之后凡是板间、板内FPGA到FPGA的高速互联我基本闭眼优先选Aurora。这个IP核在Xilinx现在叫AMD的Vivado里提供了完整封装配合官方文档PG046就能直接使用。网上关于Aurora 8B/10B的资料比较零散要么只讲原理不讲配置要么直接甩一句“按文档来”。对第一次接触的人来说光IP配置页面里的参数就能卡住大半天。这篇文章我把从原理、配置、实例化到调试的完整链路梳理出来适合正在做FPGA高速接口、看了PG046又没完全看懂的朋友也适合刚接触Vivado、想在项目里引入高速串行传输的工程师。简单讲Aurora 8B/10B是一个轻量级的链路层协议IP核它借助FPGA内部的GTX/GTH等高速收发器实现点对点的可靠数据传输。它不关心上层跑的是什么协议只负责把字节从这个FPGA搬到另一个FPGA。正因为它足够轻协议开销小、延迟低在很多数据采集、雷达信号处理、图像传输场景里它比PCIe、以太网都更合适。下面就从“为什么要用Aurora”开始讲起。1. Aurora 8B/10B的定位一条只管搬运数据的专用车道1.1 先搞清楚它在协议栈里的位置很多刚接触Aurora的朋友容易把它和PCIe、以太网混为一谈实际上大家的层级完全不同。Aurora只定义了物理层之上的轻量数据链路层解决的是“两个FPGA之间如何可靠地把字节搬过去”这个问题。至于搬过去的字节是什么含义是无符号数还是图像像素是TCP/IP报文还是某个自定义协议包Aurora一概不管。这一点跟以太网差别很大。以太网是完整的协议族有MAC层、IP层、传输层每一层都有复杂的封装和解封装延迟和开销都比较大。PCIe则更像是“总线协议标准”定义了完整的层次结构和软件模型适合CPU与设备间的互连。如果只是想在两块FPGA之间传原始数据PCIe的复杂度有点杀鸡用牛刀。正因如此Aurora在FPGA高速互连项目里非常受欢迎。它不需要CPU参与不需要操作系统驱动甚至不需要外部PHY芯片只要两端FPGA各自例化一个Aurora核把差分线连起来上电后链路就能自动完成初始化和字节对齐。对大部分嵌入式系统来说这是效率最高、开发周期最短的方案。1.2 8B/10B编码20%的带宽开销换来哪些好处Aurora 8B/10B这个命名核心就是8B/10B编码。发送端把每个原始字节拆成8个bit再映射成10个bit的码字最终通过GT串行收发器发出去。多出来的2个bit不是浪费而是为链路可靠性服务的。首先8B/10B编码保证了直流平衡。串行链路上如果长时间出现连续的0或连续的1接收端的交流耦合电容会积累直流漂移导致信号鉴别错误。8B/10B通过控制码流中0和1的数量比例让信号平均电平保持稳定。其次它保证了足够多的电平跳变这样接收端的CDR时钟数据恢复电路才能从数据流中不断提取时钟信息实现收发同步。第三它自带错误检测能力接收端如果收到非法码字或者运行差异违例可以直接判定链路出错这对调试非常有用。用生活里的例子理解8B/10B就像快递运输里每8个货箱必须搭配2个“平衡锤”保证车身不偏不倚地行驶同时车厢里会装“定位标签”让卸货端准确知道哪里开始算一箱。多付20%运费换来的是运输过程稳定、定位清晰在高速电路里这非常划算。1.3 和PCIe、以太网、裸SerDes对比之后的选择我整理了一张选型对比表基本覆盖做FPGA板间互联时常用的几类方案。方案协议开销延迟外部PHY使用难度适合场景Aurora 8B/10B20%编码开销帧头开销低不需要中FPGA间/板间点对点高速传输PCIe较高中不需要需PCIe控制器高与CPU/系统总线互连以太网(10G MACPHY)较高较高需要高与标准网络互通的场景裸GT收发器无最低不需要中自己实现链路协议裸GT收发器虽然开销为零、延迟最低但你需要自己处理CDR、字节对齐、错误检测、重传机制等一系列问题开发量并不小。Aurora把这些基础工作都做完了用户只需要关心业务数据怎么塞进去、怎么取出来这对项目周期紧张的团队来说非常友好。至于到底选哪颗FPGA来做建议先翻一遍Xilinx的选型手册重点看GT数量和线速率等级是否满足你的带宽规划。2. IP核配置每一个参数背后都是物理现实2.1 在Vivado里创建Aurora核先选Framing还是Streaming在Vivado的IP Catalog里搜Aurora 8B/10B双击后第一页会要求选择Framing还是Streaming。Framing模式提供帧同步用户数据以帧为单位发送每帧有边界标记适合需要明确数据包边界的场景。Streaming模式则是无界连续数据流没有帧头和帧尾适合恒速采样流、图像行数据这类连续数据。我个人的建议是如果应用层协议自己定义了包头包尾或者数据本身就是连续流水优先选Streaming因为Framing模式每个帧都要额外插入Dedicated Byte存在固定开销。反过来如果对端设备希望按包为单位做同步解析Framing模式能省去很多麻烦。这个选择要在创建IP时确定并且两端配置必须一致。我自己就在项目里吃过亏发送端用Framing接收端不小心选了Streaming链路能起来但数据全是乱的排查半天才发现是模式不匹配。2.2 Line Rate、参考时钟和Lane数先算明白再动手Line Rate指每个串行lane的线速率也就是GT收发器上实际跑的比特翻转速率。由于8B/10B有20%开销有效数据速率约等于线速率乘以0.8。比如线速率5Gbps有效速率大约4Gbps如果用户接口是32位4字节用户时钟就是4Gbps除以32bit约125MHz。这个换算公式要记牢后面配置用户逻辑、评估吞吐全靠它。参考时钟同样关键。每个GT Quad需要一个高质量差分参考时钟常用取值一般是Line Rate除以某个整数因子比如5Gbps线速率常配125MHz或250MHz10Gbps常配156.25MHz。不同FPGA系列的GT时钟范围不同配置时Vivado会自动做合法性校验如果不合法会直接报错。这里顺便提醒一句参考时钟并不一定等于线速率除以2或除以4不同系列GT的QPLL/CPLL分频比有差异最稳妥的方式是配置页面里看Vivado的提示。Lane数的选择主要看总吞吐需求。比如你需要的有效带宽是8Gbps单条lane线速率设5Gbps有效只能到4Gbps那就要选2条lane。经验是不要把Lane数压得很极限因为用户逻辑本身还有FIFO、总线的处理开销一旦吞吐跑满后端时序压力会很大留点余量对系统稳定性有明显帮助。2.3 GT收发器相关配置QPLL/CPLL、极性和端接别踩坑Aurora核创建时会自动生成对应的GT IP但有几点需要额外留意。第一是PLL选择。多Lane场景建议用QPLL它位于一个Quad内部能同时为多条lane提供统一时钟保证lane间频率一致单Lane或者较低速率场景CPLL也够用。用QPLL时一个Quad里的4条lane最好共用一个参考时钟和相关配置否则容易出现lane之间频率误差。第二是极性。如果PCB布线时TX的正负端接反了或者连接器定义反了GT可以配置发送/接收端极性翻转这个功能在样板调试时很救命至少不用改板。但要注意修改极性后链路初始化和comma对齐逻辑也要相应处理建议尽量在原理图阶段就规避。第三是端接。GT高速差分对通常要求100欧差分端接和AC耦合电容这个必须严格按板卡原理图来。如果在FPGA评估板上测试基本都已处理好如果是自制板出现高频误码第一个要查的就是端接和耦合电容。2.4 双方必须对齐的参数Dedicated Byte、流控、字节序创建Aurora IP时还有几个参数不像Line Rate那么显眼但两端配置不一致会导致链路起来后数据依然错乱。Dedicated Byte默认值是0xBC也就是K28.5控制字符。在Framing模式下每个数据帧的起始位置会出现这个专用字节接收端依靠它完成帧对齐如果两边设成了不同值接收端会一直找不到帧边界。流控方面默认关闭打开后会占用一部分用户带宽只有发送端可能长时间不发送数据、同时又不希望链路断开时才需要用到。字节序则比较“接地气”当用户接口数据位宽超过1字节后每个时钟周期会同时送多个字节这时涉及谁先谁后的问题。如果两端字节序不一致32位数据会被拆成4个字节按不同顺序重组数字直接对不上。这个参数没有谁一定对关键是两端保持一致。这些细节都是实际项目里踩过的坑官方文档写得比较隐晦。3. 从生成Example Design到跑通用户接口3.1 快速看懂Example Design的内部结构配置完IP核后强烈建议在Sources面板右键选Open IP Example DesignVivado会生成一个可以直接综合、仿真的示例工程。第一次接触Aurora的朋友先用这个工程在自己的板子上跑通回环再往自己逻辑里移植会省力很多。Example Design的结构一般包括顶层Aurora模块、GT基础模块、用户时钟管理模块和复位生成模块。顶层已经把IP核以及GT复位、时钟资源都例化好了你只要补上引脚约束、提供板上的差分时钟和数据线连接就能看到lane_up和channel_up状态拉高。很多朋友不知道Example Design怎么打开在IP配置页面里干瞪眼其实这个功能特别好用。示例工程里通常还带简单的数据统计和ILA观测模块比如发送固定pattern接收端做比对你可以在Vivado硬件管理器里直接跑起来看误码计数是否增加。这一步对验证板卡硬件质量特别有效。我一般先把整条链路以外部回环方式跑一遍确认GT通道没问题才开始写自己的用户逻辑。3.2 用户数据接口像操作FIFO一样收发数据Aurora核的用户接口是AXI4-Stream风格没有地址、没有读写命令就像操作FIFO。发送方向有s_axi_tx_tdata、s_axi_tx_tvalid、s_axi_tx_tready和s_axi_tx_tlast接收方向有m_axi_rx_tdata、m_axi_rx_tvalid等。时序规则不复杂tvalid和tdata同时拉高表示数据有效tready拉高表示对端可接收只有tvalid和tready都拉高时数据才算真正传走。// 发送端简单示例用户数据有效且对端ready时送出一个32bit数据 always (posedge user_clk) begin if (user_reset) begin s_axi_tx_tvalid 1b0; s_axi_tx_tdata 32d0; s_axi_tx_tlast 1b0; end else if (channel_up s_axi_tx_tready) begin s_axi_tx_tvalid tx_en; s_axi_tx_tdata tx_data; s_axi_tx_tlast (tx_cnt FRAME_LEN - 1); end end接收端更简单m_axi_rx_tvalid拉高时直接取数。一个容易忽视的细节是Aurora核的时钟和复位是独立的。用户接口有自己的user_clk和串行链路时钟不同频所以用户逻辑里必须用user_clk来采样所有用户接口信号这个时钟一般就是2.2节算出来的那个用户时钟。3.3 复位和Channel Up/Lane Up状态位链路up之后再发数Aurora核对外暴露了两个关键状态位lane_up表示每个lane已完成字节对齐和comma同步channel_up表示所有lane都up并且整个链路可以使用。用户逻辑判断“能否发数”一定要看channel_up而不是lane_up。复位时序也有讲究。核的复位输入通常要低有效并保持足够多的时钟周期Example Design里专门生成复位模块直接复用就好。链路初始化完成后别火急火燎地在第一拍就发数据。我遇到过数据前几个周期偶发丢包的情况后来在检测到channel_up后延时几十个user_clk周期再使能发送问题就消失了。具体原因和GT的comma对齐稳定时间有关但用一个小延时就能规避性价比很高。4. 调试实录链路起不来、数据错位、误码忽高忽低4.1 链路起不来的第一现场排查这是Aurora项目里最常遇到的问题。channel_up一直拉不高我排查时一般按这个顺序先看参考时钟是否起振、频率对不对再看复位是否正常释放然后用ILA抓GT内部状态和lane_up信号。参考时钟真是一大堆问题的源头。某次换了块板子原理图上写的是125MHz实际焊接的晶振却是100MHzIP配置按125MHz设置链路自然起不来。拿到板子第一步先确认QPLL/CPLL后的频率是否在合法范围。另外高速通道的电源质量也会影响链路建立GT_AVCC、GT_AVTT这些专用电源纹波偏大时link up会很随机。如果时钟、复位都正常但lane_up依旧不拉高就要怀疑差分线连接质量。用示波器在FPGA的TX引脚附近量一量如果波形边沿太缓多半是端接或线缆问题。高速信号千万别图省事用普通杜邦线飞线测试线一长误码率直线上升。我后来换了同轴屏蔽线加高质量连接器才稳定下来。4.2 数据错位、全0全1的常见原因链路起来了但数据不对这种问题比链路起不来更让人头疼。排查方向有三个字节序不对、Dedicated Byte不一致、以及用户接口的tlast给错位置。字节序问题在2.4节提过特征是对端收到的32位数据和本地字节顺序对不上比如0x11223344收到0x44332211。这种情况调整IP核配置里的字节序或者把用户逻辑里的字节重新排列就行。全0或者全1的情况先检查发送端是不是在channel_up拉高之前就发了数据。用户接口会把明明无效的数据也当成正常数据送到对端于是接收端拿到一堆空数据。另一个隐蔽点Framing模式下tlast信号如果一直不拉高对端会认为当前帧永远没结束数据一直不刷新。对端数据“憋着不动”的时候优先检查发送端帧长计数对不对。另外数据位宽和帧长最好设计成整数关系避免tlast落在非对齐位置这种边界情况最难排查。4.3 用ILA配合Aurora核做在线观测Aurora这种高速串行链路普通逻辑分析仪根本抓不到差分信号最好用的工具还是Vivado自带的ILA核。建议在用户逻辑里把channel_up、lane_up、s_axi_tx_tvalid/tready、m_axi_rx_tvalid和rx_error_detected都连到一个ILA上一次采样就能同时看清链路状态和数据流状态。调试误码问题时可以把触发条件设在rx_error_detected的上升沿这样ILA会抓取误码发生前后的数据方便观察是否特定pattern触发错误。接收端还要留意GT输出里的rx_char_is_k、rx_disperr等信号它们能直接反映8B/10B解码是否出错。另外如果做外部回环测试就是把FPGA的TX差分对直接接回RX误码还高的话基本可以确定是硬件信号完整性问题用户可以先把用户逻辑放一边专注检查时钟和布线。4.4 和其它IP配合时的常见区别Aurora vs SGMII等在FPGA高速接口开发里大家还经常遇到SGMII IP核、Ethernet子系统等。一个容易混淆的点是SGMII IP核如果配合外部PHY芯片一起使用一般应配置成MAC模式因为SGMII本身只是MAC和PHY之间的接口协议需要外部PHY芯片完成物理层编码和线路驱动。Aurora恰好相反它不需要外部PHY芯片GT收发器本身就是物理层IP核在链路层实现了字节对齐、comma检测和流控逻辑。两者的本质区别在于Aurora是点对点透明传输SGMII是为以太网MAC-PHY互连服务的。刚接触时一定要先搞清楚手上的IP核属于协议栈的哪一层。Xilinx的IP库名称都叫IP但适用场景差别很大拿SGMII的思路去理解Aurora一开始就会走弯路。5. 实测吞吐和应用扩展方向5.1 不同配置下的有效带宽参考我在实际项目里用过几种配置整理成表格供参考。以8B/10B编码为前提有效带宽均按线速率乘以0.8计算。线速率Lane数有效带宽用户接口宽度用户时钟3.125Gbps12.5Gbps32bit78.125MHz5Gbps14Gbps32bit125MHz5Gbps416Gbps128bit125MHz6.6Gbps210.56Gbps64bit165MHz实际有效带宽里还要扣除Framing模式每帧的Dedicated Byte开销但如果数据帧较长这个损耗很小。测试时我用ILA统计实际吞吐与理论值基本吻合。唯一要留意的是用户逻辑FIFO读写效率、总线位宽会影响最终吞吐尤其是128bit用户接口后端布局布线的时序约束要仔细处理否则频率上不去吞吐也达不到预期。5.2 从Aurora 8B/10B升级到更高带宽的路线Aurora 8B/10B适合6.6Gbps以下的线速率。如果想跑10Gbps、25Gbps甚至更高Xilinx还提供Aurora 64B/66B版本编码开销更低但对链路初始化和CDR要求更严格。很多新项目如果板卡信号质量好、成本允许会直接选64B/66B因为它在高带宽场景下有效吞吐更有优势。不过我的经验是产品选型从来不是越快越好。如果只是FPGA之间几十厘米短距离互联8B/10B版本的稳定性和成熟度更有优势如果规划带宽需求在20Gbps以上再考虑64B/66B或者100G以太网方案。升级时重点检查板卡的高速信号完整性和连接器选型速率上去了布线、背板、连接器都会成为新的瓶颈。最后再分享一个很个人的体会。我第一次用Aurora时被PG046那本厚重的文档劝退过总觉得里面全是英文术语好像离自己很远。后来发现把它当成“黑盒”用先跑通Example Design再去啃细节学习曲线会平缓很多。真正深入之后Aurora反而是我用过最容易上手的Xilinx高速IP之一。如果你正准备在两块FPGA之间搭一条高速路我的建议是先从文档的配置页开始算好线速率和Lane数然后直接生成Example Design把它跑起来再说。只要链路建起来剩下的用户接口操作真的就跟接FIFO一样简单了。
返回列表