ARTICLE DETAIL

资讯详情

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

FPGA光纤通信入门:Aurora回环测试实战解析

FPGA光纤通信入门:Aurora回环测试实战解析 一提到FPGA光纤通信不少人第一反应就是“高速接口很唬人入门门槛不低”。但其实只要手头有一块带高速收发器的FPGAArtix-7、Kintex-7这类都行配一个SFP/SFP光模块再走一遍Xilinx免费的Aurora 8B/10B IP核把最基础的数据回环测试跑通光纤通信这扇门就算推开了一大半。为什么我这么推崇回环测试因为它不需要任何对端设备也不依赖复杂的协议栈只要你用一根光纤把发送和接收环回去甚至直接在IP内部做回环就能在几分钟内验证整条链路是否正常。这个测试一旦通过后面做点对点数据传输、更高层协议封装心里就有底了。这篇文章我把从协议原理到IP配置、从用户逻辑编写到上板排错的完整过程整理出来希望能帮到正在啃FPGA光纤通信这块硬骨头的朋友。1. 项目思路拆解先把Aurora到底在干什么搞清楚1.1 Aurora协议的本质8B/10B编码背后的设计逻辑Aurora是Xilinx提供的一套免费高速串行通信协议它在底层调用的就是FPGA内部的GT高速收发器GTP、GTX、GTH这类物理层模块。GT收发器本身负责把并行数据变成高速串行比特流送到光模块Aurora则是定义了一套链路层规则让发送端和接收端知道“链路什么时候建立”“数据什么时候有效”“空闲时发什么字符”。这里必须提一下8B/10B编码。简单说就是每发送8位有效数据实际会在线上传输10位多出来的2位用来保证直流平衡和时钟恢复。对使用者来说最直接的影响是线路速率和有效数据速率之间永远差一个0.8的系数。比如我们常说的2.5Gbps线路速率实际有效数据传输能力只有2Gbps左右。很多人第一次算吞吐量时容易栽在这上面以为2.5G带宽就能跑满2.5G数据实际上永远做不到。理解了这层关系再看Aurora IP核的配置参数就能想明白了线路速率、参考时钟、数据宽度这几个参数是绑定在一起的。后面第三节我会详细算。1.2 回环测试到底是测什么回环测试英文叫Loopback Test本质就是把发送端的数据“绕”回到接收端然后比对数据是否正确。在Aurora IP核里回环可以在多个层级实现近端PMA回环数据在GT收发器的模拟前端就转回RX通道不经过光纤。这测的是GT本身的收发链路和时钟恢复能力。近端PCS回环在编解码逻辑层回环侧重点在8B/10B编解码和通道对齐逻辑。外部光纤回环数据真正经过FPGA发送端、光模块、光纤再从自己的光模块接收端回到FPGA。这测的是完整物理链路包括SFP模块、光纤、电源噪声对信号质量的影响。我建议的测试路径是“由内到外”先用近端PMA回环排除GT物理层的问题再切换成外部光纤回环验证光模块和光纤。这样一旦出问题你就能快速锁定故障范围不会手忙脚乱。1.3 这个项目的验证信号链路整个项目的核心验证信号就三组链路建立信号 channel_up拉高表示Aurora链路已经握手成功这是所有功能的前提。复位完成信号 gt_txresetdone / gt_rxresetdone表示GT收发器复位流程结束可以开始正常收发。用户侧数据接口AXI4-Stream总线发送端和接收端都靠它搬运数据。回环测试的最终判断标准就是看接收端收到的数据是不是和发送端完全一致。正常情况下上板后你会看到channel_up稳定拉高误码计数始终为0。如果这个目标达到了整条链路的物理层和链路层就基本没问题了。2. 硬件环境与工具准备选对板卡和光模块少走一半弯路2.1 硬件清单与选型考量做这个项目硬件上最核心的是三样FPGA开发板、光模块、光纤线。开发板我首选带SFP/SFP笼子的板卡比如常见的黑金AX7A035、正点原子达芬奇系列、米联客的MA703系列都可以。关键点在于FPGA芯片必须带GT收发器Artix-7系列里后缀带T的型号都支持比如XC7A035T、XC7A075T、XC7A100T。不带T的型号没有高速收发器跑不了Aurora。光模块方面如果开发板的SFP笼子是多模接口就买850nm多模模块如果是单模就买1310nm单模模块。很多初学者在这上面栽跟头——买错波长、买错模式链路起不来。另外注意入门测试不需要买贵的高速模块一个千兆或2.5G速率的SFP模块完全够用。光纤线通常用LC转LC的跳线。做外部回环测试有两种接法一种是买光纤环回线厂家直接做成一个头另一种是拿两根跳线把同一块板子的TX和RX对接起来。后者更常见操作也简单。2.2 两种回环方式的实际区别与操作我特别强调一下内部回环和外部回环的操作差异用IP核内部的Near-end PMA Loopback时数据流在FPGA芯片内部就走完了“发送→接收”的过程。这种方式的好处是不依赖光模块和光纤即使手上没有光模块也能先跑通逻辑非常适合第一步验证。缺点是不能验证真实物理链路的信号质量。外部光纤回环则需要把光模块插到SFP笼子里再用光纤把模块的TX和RX短接。此时数据流是FPGA GT发送端→光模块激光器→光纤→光模块接收器→FPGA GT接收端。整个物理链路都覆盖到了所以误码率才能真正反映信号质量。遇到误码问题除了看FPGA侧还要检查光模块、光纤接头是否脏污、接触是否良好。我的习惯是先把IP的Loopback配置选成Near-end PMA Loopback跑一次确认逻辑没问题然后把配置改成None重新综合上板插上光纤跑外部回环。两次测试都通过了才算完整验证。2.3 开始之前必须确认的三件事动手创建工程前我建议你先做三个检查能省掉后面大量排查时间第一确认开发板原理图里SFP笼子接的是FPGA的哪个GT Quad、哪条lane以及参考时钟用的是哪个引脚。这些在板卡配套的原理图里都能找到记下来建约束要用。第二确认板卡的GT参考时钟频率。Aurora IP核在配置时会要求输入GT Refclk频率如果板载时钟是125MHz或156.25MHz都和常规配置兼容。第三确认开发板电源管理。GT收发器对电源纹波比较敏感MGTAVCC和MGTAVTT这两路电源不能有较大纹波否则高速链路误码率会显著上升。如果手头有示波器上电后先量一下纹波再说。3. Aurora IP核配置实操把每个参数看懂再用3.1 Line Rate、参考时钟与数据宽度的计算关系打开Vivado在IP Catalog中搜索“Aurora 8B/10B”双击打开配置界面。重点参数有以下几个Line Rate线路速率推荐的入门值是2.5Gbps或3.125Gbps。选太高的话普通SFP模块和PCB走线质量未必能胜任选太低测试意义有限。以Artix-7平台为例2.5Gbps是一个很稳妥的起点。GT Refclk参考时钟通常配置为125MHz或156.25MHz。这个时钟由板卡晶振提供必须和实际硬件对上。Dataflow Mode选择Duplex表示收发独立全双工。Half-duplex也可以测但不推荐因为回环测试需要同时收发。Lanes通道数入门选1个lane即可。多lane涉及通道绑定和skew补偿复杂度会提升不少。User Interface有Framing和Streaming两种。Framing模式下支持tlast信号来标识帧结尾做数据校验比较方便Streaming模式更像一个无限制数据流适合持续吞吐测试。回环测试我推荐Framing。这几个参数之间有个核心公式用户时钟频率 线路速率 ÷ 10 ÷ 并行数据位宽系数。举个例子2.5Gbps线路速率8B/10B编码会把它变成250M个符号每秒如果数据宽度是32位即每次并行处理4字节那么用户侧时钟就是250M ÷ 4 62.5MHz。如果数据宽度配成16位用户时钟就是125MHz。注意不同Vivado版本在数据宽度选项上有差异但道理是一样的。配置完IP后Vivado会在摘要页自动给出用户时钟频率你核对一下是否符合这个计算如果差很多那就是配置问题。3.2 关键引脚说明gt_reset、power_down、channel_up、reset_doneAurora IP核顶层有一堆信号第一次接触很容易被吓到。但回环测试最关心的就这几个gt_reset这是GT收发器的复位信号必须按IP的要求正确驱动。很多IP的example design里自带了一个复位控制模块直接把它的输出接到gt_reset你只要保证外部复位信号能触发这个模块就行。官方example design里对复位时序有专门处理建议新手直接沿用不要自己造轮子。power_down这个信号控制GT收发器的电源状态。正常工作时必须拉低如果误拉了高电平通道永远起不来。调试时如果你发现channel_up死活不拉高先检查这脚。channel_up链路建立成功标志是回环测试最重要的观察信号。外部回环模式下这个信号通常需要几毫秒甚至更长时间才能拉高千万别一上电看它没拉高就以为坏了。gt_txresetdone / gt_rxresetdone发送端和接收端的复位完成标志。这两个信号拉高后GT收发器才进入正常工作状态。如果它们一直为低说明复位时序有问题要往前查。init_clk初始化时钟IP内部复位逻辑和初始化逻辑都用这个时钟。一般100MHz即可注意它必须比线速率对应的用户时钟更容易获得且稳定。3.3 IP例化与Example Design的正确用法配置完IP后Vivado会让你选择是否打开Example Design。这里我强烈建议第一次做直接打开Example Design。Example Design里包含了完整的复位逻辑、数据生成与校验模块、以及一个简单的回环演示通常用BRAM装数据然后通过TX发送再从RX接收比对。你只需要完成引脚约束、综合、上板打开Vivado的Hardware Manager就能看到链路状态和误码相关指示。先把官方示例跑通了再改写成自己的用户逻辑这样排查问题会轻松很多。如果你要手动例化IP记得在顶层模块里把这几个信号单独引出来方便接ILA观察波形。经验之谈把channel_up、gt_txresetdone、gt_rxresetdone、s_axi_tx_tvalid、s_axi_tx_tready、m_axi_rx_tvalid全部挂到ILA上出问题一眼就能定位。3.4 引脚约束和时钟约束的坑引脚约束的核心是GT位置必须正确。GT收发器在FPGA内部是按Quad组织的每个Quad包含多个lane和一个参考时钟输入。SFP笼子接的lane在原理图上会标明比如“XC7A035T-2CSG324”的SFP可能接在Quad 0的GTX_Y_0等位置。约束文件里必须把GT位置、参考时钟引脚、以及对应电平标准写对。还有一个高频坑GT参考时钟引脚必须使用MRCC/SRCC时钟输入脚不能用普通IO。如果开发板设计时没注意这个问题参考时钟根本进不了GT的时钟网络链路直接废掉。经验上Vivado在综合时如果检测到GT时钟位置不合法会报错。但有些板卡约束文件里有多个可用的参考时钟你必须确保Aurora IP配置时选择的参考时钟引脚与约束文件里实际用的引脚一致否则就会出现“配置看起来没问题上板后链路死活起不来”的情况。4. 回环测试逻辑编写自己写一个最小误码检测器4.1 帧格式与校验方案的选择跑通Example Design之后就该改成自己的逻辑了。回环测试最关键的是要能判断数据是否正确所以必须设计一个带校验的帧格式。最简单可靠的方案是“帧头 数据 累加和”。帧头用一段固定pattern比如连续两个32位的0xAAAAAAAA数据段放递增计数器32位最后放一个32位累加和。接收端在检测到帧头后开始接收数据同时计算累加和最后一个周期把计算值和收到的校验值比对结果不同就认为出错。为什么我推荐用递增计数器加累加和而不是用CRC因为回环测试的重点是验证链路是否稳定而不是验证协议设计。累加和实现起来简单直观出错就能立刻暴露等以后做真正的数据传输再换CRC不迟。如果你想更严谨也可以用CRC32但在Artix-7入门阶段没必要增加这个复杂度。4.2 发送端逻辑状态机与AXI-Stream接口时序Aurora IP核的用户接口是AXI4-Stream简洁理解就是tvalid/tready握手tdata传数据tlast表示帧结束。发送逻辑我写成一个简单的状态机帧结构是1拍帧头 N拍递增数据 1拍校验和。发送端在S_IDLE状态下拉高tvalid发出帧头之后每个时钟周期输出一个数据字数据字的值是递增计数器同时把累加和算出来等到数据区发完最后一拍把累加和放到tdata上同时拉高tlast表示这一帧结束。为了逻辑更直观我给出一个简化的发送模块框架代码重点是理解状态跳转和握手时序localparam [1:0] S_HDR 2d0, S_DATA 2d1, S_CHK 2d2, S_GAP 2d3; reg [31:0] counter; reg [31:0] sum; reg [5:0] d_cnt; reg [1:0] state; always (posedge user_clk or negedge rst_n) begin if (!rst_n) begin state S_HDR; s_axi_tx_tvalid 1b0; s_axi_tx_tlast 1b0; counter 32h0; sum 32h0; end else begin case (state) S_HDR: begin s_axi_tx_tdata 32hAAAAAAAA; s_axi_tx_tvalid 1b1; s_axi_tx_tlast 1b0; sum 32h0; d_cnt 6d0; if (s_axi_tx_tvalid s_axi_tx_tready) state S_DATA; end S_DATA: begin s_axi_tx_tdata counter; s_axi_tx_tvalid 1b1; sum sum counter; counter counter 32h1; if (s_axi_tx_tvalid s_axi_tx_tready) begin if (d_cnt DATA_WORDS - 1) state S_CHK; else d_cnt d_cnt 1b1; end end S_CHK: begin s_axi_tx_tdata sum; s_axi_tx_tvalid 1b1; s_axi_tx_tlast 1b1; if (s_axi_tx_tvalid s_axi_tx_tready) begin state S_GAP; s_axi_tx_tlast 1b0; end end S_GAP: begin s_axi_tx_tvalid 1b0; state S_HDR; end endcase end end这里我特意加了一个S_GAP状态目的是发射完一帧后让tvalid拉低一个周期再开始下一帧。这样接收端更容易用帧头去对齐不会因为连续帧导致校验错位。实际工程中你也可以用tready信号来控制发送速率但回环测试场景对吞吐要求不高保持简单即可。4.3 接收端逻辑帧头对齐与校验计数接收端逻辑比发送端稍复杂一点核心是“找帧头、对数据、算校验、比结果”。在Framing模式下Aurora IP核输出侧的m_axi_rx_tvalid表示数据有效m_axi_rx_tdata是数据内容m_axi_rx_tlast标识帧的最后一拍。接收状态机从IDLE状态开始等tvalid拉高后检测tdata是否等于帧头。一旦匹配就进入数据接收状态每个周期把tdata累加等到tlast拉高时把收到的累加值和最后一个数据字即校验字段比较如果不等错误计数器加1。always (posedge user_clk or negedge rst_n) begin if (!rst_n) begin r_state IDLE; rx_sum 32h0; err_cnt 32h0; frame_cnt 32h0; end else begin if (m_axi_rx_tvalid) begin case (r_state) IDLE: begin if (m_axi_rx_tdata 32hAAAAAAAA) begin r_state DATA; rx_sum 32h0; end end DATA: begin rx_sum rx_sum m_axi_rx_tdata; if (m_axi_rx_tlast) begin r_state IDLE; frame_cnt frame_cnt 1b1; if (rx_sum ! m_axi_rx_tdata) err_cnt err_cnt 1b1; else err_cnt err_cnt; // 正确帧计数保持 end end endcase end end end注意上面的代码里DATA状态在tlast拉高时m_axi_rx_tdata携带的是校验字段而rx_sum是之前所有数据字的累加和两者比较就能判断本帧是否出错。当然这里的时序在具体实现上要留意累加和与最后一帧数据在同一拍比较所以rx_sum的更新要能在同一拍读到旧值这需要根据实际时序微调一下。比如把累加和打一拍再和校验值比较。这些细节在仿真里一眼就能看出来所以写完后务必先仿真。别急着上板。4.4 上板调试流程与判定标准当发送和接收逻辑都写好、综合通过后开始上板调试。操作步骤我一般这样走先加一个ILA核把channel_up、user_clk、err_cnt、frame_cnt、s_axi_tx_tvalid、m_axi_rx_tvalid、m_axi_rx_tdata这几个信号全部拉出来。接着把bit文件下载到板卡打开Hardware Manager的ILA窗口。正常表现应该是这样复位释放后channel_up会在几百微秒到几毫秒内拉高。ILA波形里能看到m_axi_rx_tvalid周期性拉高且tdata内容看起来像是递增数据。err_cnt始终为0frame_cnt持续增加。如果这三条都满足恭喜你回环测试通过了。接下来你可以尝试改变线路速率、修改数据宽度或者把数据扩充到更大规模测试链路的极限。也可以同时用两块板子把光纤从板卡A的TX连到板卡B的RX做真正的双端通信——但那是后话先把回环跑稳再说。5. 常见问题与排查技巧实录5.1 channel_up迟迟不拉高怎么办这是回环测试里最让人抓狂的问题但大概率是以下原因之一照着排查基本能解决先看gt_reset的驱动是否正常。如果复位信号一直处于复位状态GT收发器永远不会完成初始化。可以检查外部复位按键或复位控制器逻辑确认复位释放后gt_txresetdone和gt_rxresetdone能拉高。再看power_down信号。如果这个引脚被误拉高通道电源被关断channel_up不可能拉高。用ILA或者直接在代码里强制把它拉低排除问题。然后检查参考时钟。用ILA观察init_clk是否正常参考时钟如果没起来IP内部状态机根本无法推进。很多情况下是板卡参考时钟引脚约束错误导致的。最后如果用的是外部光纤回环检查光模块是否插好、光纤是否接对TX和RX交叉接模块收到信号才能上报LOS灭掉。有些光模块有TX_DISABLE引脚需要拉低才能发光也要留意。5.2 误码率突然上升的排查思路如果回环测试一开始是好的跑了一段时间后误码率升高或者err_cnt开始增长通常不是逻辑问题而是物理环境问题。电源纹波是最大嫌疑。GT收发器高速运行时MGTAVCC通常是1.0V和MGTAVTT通常是1.2V这两个电压如果纹波超过几十毫伏误码率就会明显上升。我用示波器实测过板卡供电设计不佳的Artix-7板卡在满载速率下MGTAVCC纹波能达到100mV这时无论怎么调逻辑误码都压不下去。其次是光纤和光模块的接触问题。可以把光纤拔插几次用无尘纸擦拭光纤端面或者换一根光纤测试。别小看这一项光纤端面脏污导致的误码经常被误判成逻辑问题。还有一点容易忽略环境温度。SFP光模块工作时会发热如果开发板散热不好温度升高后光模块的发射功率和接收灵敏度都会变化误码率随之上升。给模块加个散热片往往能改善不少。5.3 复位、时钟和电源的几个隐蔽坑这里分享几个我自己踩过、也在社区里反复看到别人踩的坑。第一复位信号亚稳态。FPGA上电后外部复位信号没有做同步处理就直接用了这在低速逻辑里可能看不出问题但在GT收发器这种高速场景下很致命。Aurora IP核的example design里已经做了复位同步处理所以再次建议新手直接用官方example design的复位方案。第二用户时钟域和GT时钟域混淆。Aurora IP核内部有两套时钟用户时钟接口用的是user_clkGT收发器内部用的是线速率相关的串行时钟。你在用户逻辑里操作的数据全部都在user_clk域千万别拿GT时钟或其他时钟去驱动AXI-Stream接口否则时序约束过不了或者上板表现诡异。第三电源上电顺序。有些开发板的GT电源和核心逻辑电源如果没有按顺序上电GT上电复位后会处于异常状态。虽然绝大多数开发板电路已经做好时序管理但如果你用自己搭的板子一定要仔细看GT收发器的电源上电要求否则回环测试会出现“第一次上电能通断电再上电就不通”的奇怪现象。遇到这种偶然性问题我通常的习惯是复位后做一个较长时间的等待再观察复位完成信号。如果还不行就把demo里的复位逻辑多走几遍或者考虑人工再触发一次gt_reset。6. 写在最后的一些实操体会回环测试这个东西看起来简单但它是整个FPGA高速接口设计里最扎实的一块垫脚石。我见过不少人一上来就想直接跑通完整的收发传输结果被各种底层问题折磨几天最后发现连GT复位都没处理好。所以我的建议是别跳步老老实实把回环测试跑透。这不仅仅是验证IP核更是在培养你对高速链路调试的直觉——什么时候该看复位什么时候该查时钟什么时候该怀疑电源这些经验只能靠实操积累。另外提一个细节Aurora IP核的Example Design里自带的回环逻辑其实已经很好用但你最好还是亲手写一遍发送和接收逻辑。因为Example Design经过了Xilinx官方优化很多细节被隐藏起来了一旦出现非标准问题不理解底层逻辑就很难排查。自己写一遍哪怕写得糙一点你对AXI-Stream接口时序的理解都会上一个台阶。最后再分享一个小技巧调试时可以把线路速率降得很低比如降到1Gbps甚至更低看看回环是否稳定。如果降速后稳定、升速后出错那大概率是物理链路质量或者电源问题而不是逻辑问题。这样就能快速定位方向不用在逻辑代码里瞎找。希望这篇文章能帮你少踩几个坑顺利跑通你的第一块FPGA光纤通信板卡。
返回列表