我在一个项目里需要在两块FPGA之间做点对点高速视频流传输需求净带宽大概3Gbps。刚开始我打算直接用Aurora 8B/10B IP核自己搭协议栈结果从GT复位到链路初始化再到数据稳定传输一路踩坑光是确认“链路up”的信号就折腾了两天。后来切到Xilinx Chip2Chip IP核它把Aurora PHY、链路层、流控和AXI4-Stream接口全部封装好配置界面里只需要关心线速率、数据宽度和参考时钟。这篇文章我会把Chip2Chip IP核在配置和仿真阶段遇到的关键问题整理一遍重点讲Aurora PHY通信配置时的决策逻辑、仿真启动时的复位序列以及几个让波形变红的隐形根源。内容适合正在用Vivado做FPGA间通信设计和仿真的朋友尤其踩过“GT起不来”和“channel_up永远不拉高”这类坑的人。1. Chip2Chip与Aurora PHY这套组合到底在做什么1.1 Chip2Chip IP核的本质Chip2Chip IP核是Xilinx提供的一个面向“芯片到芯片”点对点通信的解决方案。它底层跑的是Aurora 8B/10B协议但用户不需要关心Aurora的通道绑定、时钟补偿、帧格式这些细节。IP核对外暴露的是干净的AXI4-Stream接口发送侧只管把数据流推进去接收侧只管把数据流读出来中间的高速串行传输全部由IP核自己打理。用一句话概括Chip2Chip是Aurora IP核的上层简化封装专门为了“两个FPGA之间无脑传数据”这种场景。在Vivado里配置Chip2Chip时很多选项和Aurora IP完全一样因为底层就是同一个GT transceiver和同一套Aurora链路层逻辑。只不过Chip2Chip帮你把用户侧的握手状态机写好了这对项目进度紧张的场景非常友好。1.2 Aurora协议在Chip2Chip里的角色Aurora协议是Xilinx私有的轻量级高速串行协议它定义了物理层和链路层的分工。物理层负责用FPGA内部的GTX/GTH/GTY transceiver做高速串行收发包括8B/10B编解码、串并转换、时钟恢复链路层则负责初始化、通道对齐、错误检测、时钟补偿序列的插入与移除。Chip2Chip IP核直接使用Aurora作为传输管道所以你在配置界面里看到的“Line Rate”“GT Reference Clock”“Data Width”这些参数本质上是Aurora PHY的参数。你把它配对了Chip2Chip才能正常工作。有些朋友会问那我直接例化Aurora IP核不就行了确实可行但直接例化Aurora IP时你需要自己处理用户接口的流控、帧协议、初始化握手。比如发送端什么时候可以发数据、接收端怎么判断一个帧结束了、通道绑定失败怎么办。这些东西在Aurora IP核里面只给了最底层的端口用户侧的状态机完全要自己写。Chip2Chip就把这些脏活累活全包了。1.3 为什么选Chip2Chip而不是直接撸Aurora我当时的决策很简单项目周期紧我不想在链路层协议上花太多时间。用Chip2Chip之后我的RTL代码里只需要维护一个AXI4-Stream接口的状态机发送侧检测tready接收侧处理tvalid核心业务逻辑很快就跑起来了。代价是灵活性降低。Chip2Chip只支持单通道点对点不支持多通道绑定也不支持Aurora的广播、多播这些高级功能。如果你的应用是两个FPGA之间固定的一对一高速流传输Chip2Chip是最省心的选择。如果要做复杂网络拓扑还是得回归Aurora IP甚至更底层的手写GT。2. 配置前的三个计算题线速率、用户时钟和GT参考时钟很多人的Chip2Chip仿真起不来问题往往出在配置阶段拍脑袋填参数。这一节讲清楚三个关键计算填完再动手。2.1 线速率怎么定从吞吐量倒推线速率不是随便选的要从实际有效带宽倒推。Aurora 8B/10B编码每个字节要额外传2bit所以链路有效数据率只有线速率的80%。假如你需要净荷3Gbps那GT线速率至少是3Gbps ÷ 0.8 3.75Gbps选线速率时不能只按理论值选还要留出余量。因为Aurora链路会周期性插入时钟补偿序列这也会吃掉一部分带宽。我的习惯是至少留10%的余量例如需求3Gbps我选4Gbps线速率这样即使有少量重传也不至于断流。Vivado的Chip2Chip配置界面里线速率选项一般从几百Mbps到6Gbps以上都有具体上限取决于你使用的FPGA器件和GT transceiver类型。7系列里GTX普遍支持到6.6GbpsUltrascale的GTH/GTY会更高。选型时先查器件手册别等到综合报错再回头改。2.2 用户接口时钟和数据宽度的关系数据宽度决定了用户侧AXI4-Stream接口的时钟频率。Chip2Chip IP核的数据宽度常见选项是2字节、4字节、8字节。用户时钟和线速率、数据宽度的关系是用户时钟频率 (线速率 × 0.8) / (数据宽度 × 8)举个例子线速率4Gbps数据宽度4字节32bit用户时钟就是4Gbps × 0.8 / 32bit 100MHz这个时钟是用户逻辑工作的时钟也是复位、握手信号的时间基准。配置IP核时一定要把这个时钟算准否则后续状态机时序分析跑不过。我当时算完用户时钟后又专门确认了一下FPGA内部的时钟资源能不能生成这个频率。如果要用MMCM/PLL分频还要看输入时钟范围是否满足。有些同学配置时没注意用户时钟设成250MHz但FPGA内部逻辑根本跑不到250MHz导致时序收敛失败。2.3 参考时钟选择与GT位置映射GT参考时钟是另一个大头。Chip2Chip IP核需要外部提供一个参考时钟给GT transceiver的PLL。这个参考时钟频率通常等于线速率除以一个系数常见的是线速率/2或线速率/4。例如线速率4Gbps参考时钟可以用125MHz4GHz/32这里需要查手册——实际上不同GT型号支持的参考时钟频率范围不同。实际操作中Vivado的IP配置界面会让你选择参考时钟的来源比如refclk是来自某个专用时钟引脚还是来自GT Quad内部。关键点是参考时钟引脚必须落在你使用的GT所在的Quad上。不同Quad的高速时钟引脚物理位置不同选错了要么编译时布线困难要么干脆产生不了时钟。我栽过一次芯片上选了GTH Bank 224但在配置界面里把参考时钟引脚选成了Bank 225的时钟引脚结果综合过了布局布线时报错说参考时钟无法驱动目标GT的PLL。后来按照Vivado的GT Placement提示重新选了参考时钟问题才解决。除此之外power_down端口必须在用户逻辑中显式拉低。Chip2Chip IP核会有gt_power_down或类似的端口仿真时如果悬空GT永远处于power down状态链路自然起不来。这个不起眼的问题最容易让人怀疑人生。3. 仿真启动的细节复位、初始化与链路建立的正确姿势仿真阶段最容易出问题的就是复位时序。Chip2Chip底层是Aurora而Aurora链路初始化有一套严格的握手流程。在testbench里随便来个“上电后拉高复位再拉低”的节奏十个有九个会卡在初始化。3.1 复位信号的拉低顺序和时长Chip2Chip IP核通常有一个整体复位信号可能叫axi_reset或者gt_reset。这个信号不是简单的一上电就解除就可以。Aurora链路要求GT的TX和RX在复位释放后完成各自的PLL锁定、TX复位完成、RX复位完成然后才进入通道握手。正确做法是上电后先拉低复位信号保持至少10个用户时钟周期。等待IP核输出的gt_tx_reset_done和gt_rx_reset_done拉高。两个都拉高之后再释放用户侧的AXI4-Stream复位。在testbench里可以用一个简单的状态机来跟踪这个流程。伪代码类似initial begin reset_n 0; #100; wait(tx_reset_done rx_reset_done); (posedge user_clk); reset_n 1; end注意wait语句前面最好加一个超时保护防止GT一直不完成复位时仿真卡死。3.2 如何确认Aurora链路初始化完成Chip2Chip IP核通常会输出一个链路状态信号比如channel_up或者link_up。只有这个信号拉高才表示Aurora PHY链路初始化完成可以发送用户数据。在仿真平台里我习惯写一个等待任务task wait_link_up; begin while (!link_up) begin (posedge user_clk); if ($time 1_000_000) begin $error(Link up timeout!); $finish; end end end endtask这个超时时间要根据参考时钟和线速率估算。Aurora初始化通常需要交换若干帧在仿真中可能需要几十到几百微秒。如果你的testbench只跑几个微秒就断言失败那多半是超时时间不够不是逻辑错。3.3 仿真时常见的超时陷阱我见过一种经典场景testbench里给了参考时钟也给了复位但channel_up就是一直不拉高。后来发现是init_clk没有配置。Chip2Chip IP核需要用户提供一个慢速初始化时钟通常几十MHz比如50MHz用于GTPLL的配置和链路初始化。如果这个时钟没有给或者给了之后频率不对链路就会一直卡在复位状态。另一个常见陷阱是GT的复位完成信号在仿真中保持低电平。这是因为仿真模型里GT参考时钟需要先跑一段时间PLL才能锁定。有些GT仿真模型要求参考时钟运行至少10微秒后gt_pll_lock才会拉高。所以testbench里不要急着检测channel_up先让时钟和复位稳定跑一段。还有的朋友用ModelSim仿真时波形显示红色X排除逻辑后才发现是glbl模块没有编译进去。Xilinx的仿真库要求编译glbl模块用来初始化全局复位、配置高阻等。忘了把这个文件加到仿真工程里GT模型就会输出一堆X整个波形看起来就跟最上面的红线一样。4. 实战调试中的避坑清单从波形红线到数据错位仿真通过不等于板级没问题。但仿真阶段埋下的定时错误后面板级排查会更痛苦。这里把我在多个项目里遇到的高频坑列一下。4.1 AXIS接口的信号时序坑Chip2Chip的用户接口是AXI4-Stream。发送侧你需要等待tready为高才能拉高tvalid并给出有效数据。有些朋友写状态机时只关心tvalid不管tready结果仿真里数据看起来全发出去了但接收端根本收不齐因为数据在握手不完整时被丢掉了。接收侧也有坑。Chip2Chip会把tkeep和tdata对齐地输出。如果接收逻辑没解析tkeep认为每个周期数据都是完整的就会在最后一拍数据不完整时产生错位。尤其数据宽度超过4字节后tkeep的组合情况更多必须按AXI4-Stream规范解析。我习惯在testbench里做一个数据比对模块发送端带上递增的序列号字段接收端校验序列号是否连续。一旦跳号立刻打印错误并结束仿真。这样能快速暴露握手和被解析错误而不是淹没在长长的波形里。4.2 共享逻辑与example design的坑Vivado的GT类IP都有“Shared Logic”选项Chip2Chip也一样。可以选择Include、Explicit或None。这个选项控制GT_COMMONPLL、时钟分频等公共电路放在哪里。如果一个工程里同时用了多个Chip2Chip或Aurora IP把它们都设置成Include Shared Logic综合时会报错说GT_COMMON原语被多个模块驱动。正确做法是只让其中一个IP Include共享逻辑其他IP选择Explicit方式在顶层模块中手动例化共享逻辑或者使用IP自带的Example Design封装。我踩过一次更隐蔽的两个Chip2Chip IP共享同一个GT参考时钟共享逻辑放得离其中一个IP比较远结果时钟偏斜导致误码率升高。这个在仿真中根本看不出来只能靠板级眼图测量。后来我把两个IP放在同一个Quad共享逻辑放在中间位置问题才解决。4.3 仿真不收敛/波形为X的排查链路如果波形里大量信号是红色X或高阻Z按这个顺序排查检查参考时钟是否有效。在GT参考时钟引脚上添加一个断言确认时钟频率接近预期。检查init_clk是否存在且运行。检查复位信号是否已释放以及释放时序是否满足IP核要求。检查gt_power_down是否拉低。检查glbl模块是否编译进仿真工程。检查IP核输出的所有时钟信号user_clk、init_clk_out等是否已经产生。大部分情况下波形为X的根源就是某个基础时钟或复位没给到位。不要一头扎进状态机分析先把时钟复位树检查一遍。4.4 真实项目中的一次链路不稳定调试有一块板子两片Kintex-7通过Chip2Chip通信仿真全通但连续跑半小时后偶尔出现CRC错误。用ILA抓soft_err信号发现会偶发拉高一个周期。查了Aurora协议soft_err通常表示接收端检测到8B/10B编码错误或帧校验错误。用IBERT做误码率测试发现在某一组GT差分对上误码率偏高。最终定位是PCB上这一组差分信号的过孔阻抗不连续加上参考层被电源隔断导致信号质量恶化。换了一张改版的PCB后问题消失。这个经历说明一个残酷现实Chip2Chip的逻辑和仿真做对了不代表物理链路就一定稳定。FPGA高速串行通信的上限往往取决于PCB和电源设计而不是RTL逻辑。5. 一套可复用的调试流程与检查表5.1 链路状态寄存器速查调试Chip2Chip时以下信号是必须盯着的信号/寄存器作用正常状态channel_upAurora通道建立标志高电平gt_tx_reset_doneGT发送端复位完成高电平gt_rx_reset_doneGT接收端复位完成高电平gt_pll_lockGT PLL锁定高电平hard_err硬错误标志通道丢失等低电平soft_err软错误标志编码错误等低电平user_clk用户逻辑参考时钟运行init_clk初始化时钟运行这些信号不一定全都有精确名称但Vivado生成的Chip2Chip example design里都能找到对应端口。拿到一个新IP第一件事就是打开example design的仿真工程把信号名抄下来。5.2 从仿真到板级调试的检查清单仿真阶段参考时钟频率是否按配置设置。init_clk是否运行。复位释放顺序是否符合要求。channel_up是否在规定超时时间内拉高。用户数据发送是否在channel_up之后才开始。有没有检查tready握手的完整性。板级阶段使用ILA观察channel_up和soft_err。使用IBERT对每一对GT差分线做误码率测试。用示波器检查参考时钟波形质量。如果出现周期性错误检查时钟补偿序列是否被异常删除。PCB上高速差分对距离、过孔数量、参考层连续性都要核查。5.3 我的几句实在话用了两年多Chip2Chip我的体会是它确实把Aurora的门槛降低了大半但并不是有了IP就能躺平。真正决定项目成败的还是配置时的计算、复位时序的严谨、仿真的充分覆盖以及板级信号完整性的基本功。小事上建议拿到Vivado生成的example design别急着往自己工程里套先跑一遍example的仿真确认IP在当前器件和版本下能work。然后自己写testbench时把超时断言写充分。一个自带超时检测、数据比对、错误上报的testbench能帮你在后续版本迭代里省下大量排查时间。另外一个小技巧在testbench里故意把GT参考时钟往上拨动一点或者加一些随机抖动看看Chip2Chip的时钟恢复能力如何。虽然这不能完全模拟真实PCB噪声但能提前暴露出一些过于紧的时序假设。我靠这个提前拦截过一次因为参考时钟容限不够导致的链路不稳定问题算是成本最低的“预实验”了。
阅读完成 · 觉得有帮助?