ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

FPGA千兆以太网实战:Xilinx 7系列GTX收发器与SFP光口实现1000BASE-X链路

FPGA千兆以太网实战:Xilinx 7系列GTX收发器与SFP光口实现1000BASE-X链路 做FPGA千兆以太网很多新手第一反应是去接RGMII接口、买一颗外部PHY芯片、再把MDIO配置寄存器捣鼓半天。但实际上如果你的FPGA是Xilinx 7系列及以上的芯片完全可以用SFP光口直接搞定千兆传输而且硬件复杂度比电口方案低不少传输距离还能从100米直接干到几十公里这就是XAPP1082这个参考设计最吸引人的地方。我最初接触这个方案时也踩了不少坑但摸清楚GTX收发器内置的PCS/PMA链路之后整个思路就豁然开朗了。今天这篇文章就以Xilinx 7系列FPGA SFP光模块为例把从硬件引脚到工程移植、再到Ping通上位机的完整流程拆开揉碎了讲一遍代码和思路都来自XAPP1082适合手里正好有带SFP座子开发板的同学也适合想搞明白GTX到底怎么用来做高速接口的初学者。1. 为什么千兆传输优先选SFP光口方案选型背后的逻辑1.1 电口方案的“三座大山”距离、外围器件和协议负担如果你用过RGMII 外部PHY芯片的方案一定对这几件事有印象第一传输距离受限于双绞线最长100米工业现场或数据中心上联场景经常会卡在这里第二外围电路一点也不省心——PHY芯片要配25MHz晶振、要加网络变压器、要处理MDI差分对上的共模电感PCB布局一不注意信号质量就崩了第三MDIO配置是个无底洞PHY芯片的寄存器手册动辄上百页想把自协商、速率、双工模式调对没点经验真搞不定。相比之下SFP光口方案把这三座大山全搬走了。光模块直接插在SFP连接器上FPGA内部GTX收发器完成物理层编码解码中间不需要任何外部PHY芯片。那GTX凭什么能替代PHY因为Xilinx 7系列GTX收发器内部把PCS和PMA都做进去了PMA负责高速串并转换PCS里自带8B/10B编解码、弹性缓冲、逗号检测和对齐逻辑这些本来就是以太网PHY的核心工作。所以SGMII/1000BASE-X协议的物理层部分直接被GTX“吞”掉了硬件上只需要保证IML差分线从GTX引脚连到SFP座的TD/RD上就行。1.2 SGMII和1000BASE-X决定GTX工作模式的一道关键选择题新手最容易混淆的就是SGMII和1000BASE-X这两个名词它们决定了GTX内部PCS的工作模式XAPP1082里也可以针对这两种模式做切换。对比项SGMII1000BASE-X协议定位MAC与外部PHY之间的接口PHY与光模块/对端设备之间的接口典型应用场景MAC芯片外接PHY芯片PHY再连RJ45FPGA直连SFP光模块或对端设备上的SFP/PHY是否依赖外部PHY依赖SGMII只到MAC-PHY边界不依赖GTX直接驱动光模块自协商机制PHY与对端协商后将结果通过SGMII传递PCS内部有自协商状态机与对端直接协商XAPP1082中的应用如果你板上还有电口PHY可以选这个模式接SFP光模块就选1000BASE-X也是本文章的主角当你用SFP光模块时GTX自然要工作在1000BASE-X模式。整个链路是FPGA内部MAC - GTX的PCS/PMA - 差分对 - SFP光模块 - 光纤 - 对端设备可以是交换机、也可以是另一块FPGA板卡。对端交换机看到的就是一个标准1000BASE-X光口直接插上就能协商链路互操作性强得一匹。1.3 XAPP1082到底给你省了多少工作量XAPP1082是Xilinx官方发布的参考设计全称大概意思是“在7系列GTX收发器中使用SGMII/1000BASE-X PCS/PMA IP”。它给了一整套可综合的工程源码包含一个简单的以太网MAC、GTX收发器配置、FIFO接口封装、以及一个可以回Ping的演示应用程序。你拿到手里改一改引脚约束烧进板子就能和电脑或交换机通过光口通信。它最大的价值不是让你直接照抄而是向你完整展示GTX的使用链路参考时钟怎么给、复位时序怎么处理、收发数据通路怎么对接用户逻辑。理解了这套框架以后做10G甚至更高速度的接口思路也都是相通的。2. SFP接口硬件设计引脚定义与外围电路的关键细节2.1 SFP连接器20Pin引脚逐一盘点SFP座子在FPGA开发板上很常见很多人拿来就用却连每个引脚是干嘛的都没搞清。这里我按SFP标准定义把20个引脚列出来重点标出必须接的部分引脚号信号名方向功能说明必须接1VeeT电源发射端地必须2TX_Fault输出发射故障指示模块内部检测到异常会拉高建议接FPGA3TX_Disable输入发射关闭控制高电平或悬空时关闭光发射必须处理4MOD_DEF2双向I2C数据线SDA读取模块EEPROM建议接5MOD_DEF1双向I2C时钟线SCL建议接6MOD_DEF0输出模块在位检测接地表示模块存在建议接7Rate_Select输入速率选择千兆场景通常不需要可悬空8LOS输出信号丢失指示接收光功率不足时拉高必须接FPGA9VeeR电源接收端地必须10VeeR电源接收端地必须11VeeR电源接收端地必须12RD-差分输出接收差分负端接GTX_RXN必须13RD差分输出接收差分正端接GTX_RXP必须14VeeR电源接收端地必须15VccR电源接收端供电一般3.3V必须16VccT电源发射端供电一般3.3V必须17VeeT电源发射端地必须18TD差分输入发射差分正端接GTX_TXP必须19TD-差分输入发射差分负端接GTX_TXN必须20VeeT电源发射端地必须实际设计时最核心的差分信号就四根GTX_TXP/GTX_TXN连TD/-GTX_RXP/GTX_RXN连RD/-。很多开发板会在这两条差分对上串一个0欧电阻或交流耦合电容XAPP1082的参考设计在GTX输出侧本身就带了交流耦合你在适配自己板子时要看清板载有没有重复耦合电容处理不当会影响信号眼图。2.2 电源与PCB布局光模块比你想的娇贵SFP模块的3.3V供电稳定性直接影响光发射功率和接收灵敏度。我见过不少人在电源设计上翻车模块发光功率忽高忽低误码率时有时无最后发现是SFP供电电源纹波太大。建议VccT和VccR分别用磁珠隔离并联一组10uF 0.1uF去耦电容如果板上还有空余位置加一个0欧电阻做单点连接也很有帮助。差分走线要控制100欧姆差分阻抗TD/TD-与RD/RD-两组线尽量走在表层少打过孔对内等长控制在5mil以内。GTX引脚到SFP座子的距离越短越好这组高速信号跑到1.25Gbps虽然有8B/10B编码兜底但布线太随意还是容易出偶发错误。2.3 参考时钟成败的关键一环SFP千兆以太网对GTX参考时钟有明确要求必须提供125MHz频率稳定度最好在100ppm以内。注意这里说的是125MHz不是156.25MHz那是10G以太网用的别拿错了。XAPP1082的示例工程里用了一个可编程时钟芯片来产生125MHz如果你自己画板直接用125MHz有源差分晶振或者普通有源晶振也行。务必确认你的开发板上晶振输出频率是不是125MHz很多板子集成的时钟是可编程芯片默认配置可能输出100MHz或其它频率那GTX的线速率就完全不对了链路完全起不来。3. XAPP1082工程结构拆解从时钟到数据通路的四个核心模块3.1 整体架构这个参考设计到底由哪些部分组成打开XAPP1082的源码初次看会觉得文件特别多但理清层次后核心只有四块以太网MAC层小MAC负责以太网帧的封装与解封装、CRC校验、帧过滤输出标准MII接口数据。它的存在就相当于把电脑里网卡MAC层的活儿干了一部分。GTX收发器SGMII/1000BASE-X PCS/PMA IP物理层核心完成8B/10B编解码、串并转换、自协商、时钟恢复等这层由Vivado的Transceivers Wizard配置生成的IP核实现。FIFO接口封装把MII数据流转换成用户友好的突发读写接口和你的业务逻辑对接。这部分设计在XAPP1082中已经写好你只需要往里填数或者从里面取数。演示应用程序自带ARP响应和Ping回复逻辑烧进板子后不用写任何用户代码就能被ping通。这对新手验证链路是否正常简直是雪中送炭。3.2 时钟域与复位时序GTX最容易翻车的地方GTX内部有多个时钟域从参考时钟产生的并行时钟TXUSRCLK、从恢复时钟得到的并行时钟RXUSRCLK、以及用户逻辑侧的接口时钟。XAPP1082的设计里用户侧接口时钟通常由GTX的TXOUTCLK分频或直接派生这样做的好处是发送路径天然同步不需要做跨时钟域处理。复位时序是另一个大坑。GTX要求复位信号在参考时钟稳定后释放GTTX_RESET和GTRX_RESET有严格的先后关系而且复位脉冲宽度必须达到一定周期数。XAPP1082里的复位模块是一个经过验证的状态机新手千万别自作聪明改成简单的电平复位——我有一次为图省事直接在顶层把GTX复位引脚绑到全局复位上结果芯片上电后GTX状态一路异常查了整整两天才发现是复位时序没满足要求白白看了两天波形。老老实实按官方复位模块来它能处理电源稳定、参考时钟锁定再到收发器复位的完整时序。3.3 用户侧数据接口一个可以直接“抄作业”的FIFO读写示例XAPP1082里用户侧的收发接口设计成了一个类似FIFO读取/写入的形式。发送侧你向发送FIFO写入数据MAC会自动组帧发送接收侧MAC收到完整帧之后存入接收FIFO你按帧读出。下面是一段典型的用户逻辑向发送通道写入一段UDP负载数据// 发送通路用户接口示例XAPP1082风格 // 注意具体端口名称以实际工程为准这里展示的是数据流交互方式 always (posedge user_clk) begin if (!tx_fifo_full) begin tx_fifo_wr_en 1b1; tx_fifo_wr_data {byte_counter, 16hA5A5}; // 应用数据拼装 byte_counter byte_counter 1b1; if (byte_counter 8d31) begin tx_fifo_wr_en 1b0; // 一帧数据写够了 byte_counter 8d0; end end else begin tx_fifo_wr_en 1b0; end end代码本身很简单但要注意XAPP1082的MAC帧处理是有最小帧长限制的如果你写的数据量太短MAC层会自动补Pad到64字节。接收侧每次读出一个完整帧后系统会把帧的CRC字段剥掉再送给你省了你校验CRC的活。实际操作中我推荐先用它自带的Ping功能确认物理链路再动手写自己的用户数据收发这样定位问题时会清晰很多。3.4 板卡信息配置改IP和MAC地址的入口XAPP1082工程里有一个配置文件或者参数定义区里面存着FPGA的MAC地址、IP地址、子网掩码和默认网关。默认配置的IP在代码注释中有标注通常在192.168.1.x这个网段内。你需要把它们改成自己局域网内的合法地址并且保证和电脑在同一网段。高手移植的新手特别容易忘改这个直接烧了官方默认地址就开pingping不通就开始怀疑硬件折腾一圈最后发现是地址冲突或网段不对。配置信息一般在工程顶层有parameter定义搜一下类似“LOCAL_MAC”和“LOCAL_IP”的关键字就能找到改成你的目标地址重新综合即可。4. 实战落地从新建工程到Ping通上位机的完整流程4.1 准备工作需要什么工具和板卡要把XAPP1082跑起来你需要准备这些一块带SFP光口的Xilinx 7系列FPGA板卡比如Artix-7、Kintex-7都行使用GTX收发器。这里我以Artix-7为例讲解芯片型号不同时GTX的位置会变但思路完全一样。一个千兆SFP光模块多模模块配LC-LC光纤跳线模块型号随便华为、Finisar、Intel等品牌都可以关键是速度等级要支持1G。一台有千兆网口的电脑把网卡IP配成和FPGA端同一网段。Vivado开发环境建议用2018.3以上的版本版本太老有些IP配置界面不一致。另外如果你用的是第三方的板子最好确认一下SFP座子上的两只差分对具体接到了FPGA的哪个GTX Bank、哪个通道上以及125MHz参考时钟接的哪个引脚。这些信息在开发板原理图里写得清清楚楚移植工程前必须先核对这些引脚关系。4.2 移植工程的三处必改位置从Xilinx官网下载XAPP1082的zip包解压后你会看到一个Vivado工程或者ISE工程不同版本文件组织不一样但移植到自己的板卡上时基本只需要改三个地方第一引脚约束文件XDC。把SFP相关的引脚号改成你板子上实际的引脚位置包括GTX_TXP/TXN、GTX_RXP/RXN、SFP_PRESENT、SFP_LOS等尤其是GTX引脚必须和MMCM/GTX参考时钟在同一个Bank的合法位置上。第二GTX参考时钟引脚。125MHz时钟接到板卡的某个专用时钟引脚上XDC里要约束到对应的MGTREFCLK引脚。这里注意GTX参考时钟引脚在不同Bank不能混用GTX收发器必须使用相邻的MGTREFCLK这在Vivado的Transceivers Wizard里会校验。第三晶振频率约束。如果板载125MHz时钟来自可编程时钟芯片可能还要给时钟芯片写配置程序或者在FPGA里例化一个MMCM对GTX输出的恢复时钟做处理确保用户侧逻辑拿到的是干净的时钟。比较省事的做法是直接用与GTX TXOUTCLK同源输出的时钟做用户时钟避免引入额外的时钟抖动。4.3 综合、布线、下载的完整操作流程在Vivado里完成以下步骤新建工程芯片型号选对比如xc7a35tcsg324-1。把XAPP1082所有RTL文件添加进来如果是旧版本顶层文件可能在gtx_tx_rx或者application层对照源码说明找到顶层即可。写好XDC约束包括所有输入输出引脚、时钟约束。时钟约束用create_clock指定125MHz参考时钟再用set_input_delay/set_output_delay给SFP差分对打上约束如果嫌麻烦可以先不设但综合时序报告会有一堆warning实际性能也可能打折扣。执行综合、布线生成bitstream。Artix-7上编译一次大概10到20分钟取决于芯片规模和电脑配置。连接JTAG下载器绑定bitstream然后烧录。等待FPGA上电完成、GTX复位状态机跑完用光纤把SFP模块连到交换机或电脑的光口上。如果你电脑没光口最简单的方式是连到一台千兆交换机再用网线把电脑接交换机上或者直接连另一块同样跑XAPP1082的FPGA板卡。烧录成功后观察SFP模块侧边的link灯状态正常情况下连接到交换机后几秒内交换机和光模块的link指示灯会点亮。此时你在电脑上打开命令行ping一下FPGA的IP地址记得把电脑的IP配到同一网段能看到TTL64左右的回复就说明千兆以太网链路已经全线打通了。4.4 没有开发板也能学纯仿真思路如果你的板子还没到手也可以用Vivado自带仿真器跑XAPP1082的收发通路仿真。给GTX的复位模块提供虚拟的时钟和复位激励观察用户侧FIFO在仿真中能不能完成一帧数据的写入和读出。不过GTX硬核在仿真里跑不了真实的高速串行数据所以仿真主要是验证MAC、FIFO和用户逻辑之间的交互时序。对新手来说仿真可以在没硬件时提前理解这套数据流的运转方式为后面上板调试节省大量时间。5. 避坑实录我调试SFP千兆链路时遇到的三类问题5.1 link_up信号起不来从LOS到自协商的排查链路这是最常见的故障现象光模块插上光纤SFP模块的link指示灯死活不亮。我在现场调试通常按下面的顺序排查先看SFP模块的LOS引脚电平。LOS在高电平时表示接收不到光信号如果光纤两端只插了一头或者光模块收发搞反了LOS必然是高的。把光纤另一头插到交换机上之后如果LOS还是高先怀疑光模块本身或者光纤跳线有问题换一根试试是最快的办法。再查GTX复位流程。用ILA抓GTX相关状态信号确认复位状态机有没有卡在某个状态。GTX复位对参考时钟依赖极大如果参考时钟不稳定复位永远无法完成。用手头的示波器或ILA抓一下GTX的TXOUTCLK没波形就说明GTX根本没起来这时候十有八九是参考时钟配置不对或者板卡上的可编程时钟没输出125MHz。最后查自协商状态机。1000BASE-X的自协商是通过发送配置字C1和接收对端配置字完成的如果GTX一直发C1但收不到对端的响应链路也起不来。用ILA抓PCS层的sync_status和link_up信号link_up一直为低大概率是自协商没完成。这时检查两端是否同为1000BASE-X模式如果对端是SGMII电口交换机协议上是不兼容的需要把FPGA端改成SGMII模式再接PHY芯片之前就有朋友忽视这个拿着1000BASE-X的光口直接去插SGMII转SFP的模块折腾了半天。5.2 能Link Up但Ping不通问题出在MAC层链路指示灯亮了自协商也完成了结果Ping不通这种情况比link_up不亮更让人摸不着头脑。我的经验是先抓板上的以太网帧收发计数和错误计数——XAPP1082工程里带了一些调试计数器如果接收CRC错误在持续增长说明物理层有误码优先检查光模块质量和光纤连接头是否脏污如果根本没收到帧优先级就是先看MAC有没有过滤掉非本机MAC地址或广播帧再看接收FIFO有没有满是不是你的用户逻辑一直没读数据导致新帧被丢弃了。这里有一个特别容易踩的坑FPGA端的MAC地址和IP地址要实实在在配到被测主机中。有些新手把FPGA的MAC地址设成全零或者出厂默认值对端设备在做ARP解析时可能直接不回应。把配置参数里的MAC地址改成任意合法的本地地址比如00:11:22:33:44:55IP改成192.168.x.x网段并且保持和电脑的ARP缓存一致ping之前可以先arp -d清一下缓存往往问题迎刃而解。5.3 偶发丢包和误码GTX参考时钟抖动惹的祸还有一种情况是链路能通ping也通但大流量下丢包率上升。用ILA观察GTX的RX错误计数如果持续增加说明接收端误码严重。经验上这首先要怀疑参考时钟的抖动过大。此前有一块板子用的参考时钟是普通单端晶振转差分没有经过低抖动时钟芯片结果1G线速率下BER偏高换成低抖动时钟源后问题消失。7系列GTX对参考时钟的纯度确实有要求建议有条件直接用板载的SiTime或类似低抖动差分振荡器或者用FPGA的GTREFCLK专用引脚搭配时钟Buffer别用一个纯粹的单端晶振对到P端、N端直接接地草草了事。另外还要检查差分走线有没有经过连接器或过孔跳变一旦阻抗不连续反射就会造成眼图闭合。在板卡不改版的情况下可以尝试调整GTX的TX预加重和接收均衡参数Vivado的Transceivers Wizard里提供了可配置选项适当增强预加重有时候能把误码降下来。虽然这是一条治标不治本的路但作为快速验证手段非常有效。5.4 小技巧TX_Disable是新手最容易忽视的“隐形杀手”我特意把这条单独拎出来说。SFP模块的TX_Disable引脚特性在不同品牌模块上不完全一样有些模块在内部上拉引脚悬空就默认禁用发射此时模块不会发光但看起来模块又是“正常插着”的。很多新手遇到发射端完全没光、对端接收不到任何信息查了半天原理图才发现是TX_Disable上拉了却没被拉低。正确做法是把TX_Disable引脚通过10K电阻下拉到地或者在FPGA侧约束成输出低电平。同理SFP_PRESENT在位检测引脚也最好接上拉电阻并连到FPGA输入这样FPGA能感知光模块是否插好调试时多一个有效的状态信息。6. 从1G到更高速率SFP方案后续还能怎么扩展搞定XAPP1082这套千兆链路之后你会发现GTX收发器的潜力远不止于此。同样是SFP座子或SFP座子如果你的FPGA是Kintek-7、Virtex-7、UltraScale系列内部GTX/GTH可以运行在更高的线速率上直接对接10G以太网、CPRI、JESD204B等协议就是下一个自然进阶方向。从XAPP1082这套代码迁移到10G以太网时最大的差异在三点一是物理层从8B/10B编码换成64B/66B编码吞吐效率高了二是GTX换成了GTH/GTY参考时钟从125MHz变成156.25MHz三是MAC层需要支持10G的流水线架构。但你在XAPP1082里学到的GTX复位时序、时钟架构、FIFO数据流交互这些基本功放到10G甚至25G的设计里依然成立所以这套参考设计作为高速接口的入门教材含金量是实打实的。把XAPP1082完整跑通一遍不仅意味着你的FPGA板卡多了一个好用的网络接口更意味着你对GTX收发器的理解从“听说过”变成了“亲手调通过”。以后无论是做高速数据采集、图像传输还是分布式控制系统的板间互连这条链路都能作为最基础的通信底座。我个人的体会是做FPGA高速接口先别急着追新架构把官方参考设计的代码逐行读懂、亲手改到自己的板子上跑通、再用ILA把所有信号都抓过一遍这个过程的成长速度远超看十篇博客文章希望这篇文章能帮你少走一些我走过的弯路。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进