
1. 从一块板子到四块板子为什么单卡扛不住200Gbps单张VU13P板卡本身已经算是FPGA圈子里的大块头了。Virtex UltraScale 系列的 VU13P 芯片逻辑单元数量在百万级DSP Slice 和 UltraRAM 的配置也相当充裕单板做几十Gbps量级的数据采集和预处理一般来说不会太吃力。但一旦你把目标定在200Gbps 的持续数据汇聚情况就完全不一样了。我先说一个很多人容易忽略的事实200Gbps 不是带宽够大就能跑的问题而是一个系统级瓶颈问题。它同时牵扯到芯片内部的资源调度、板级的高速收发器布局、多卡之间的时钟同步、数据流的背压控制以及上位机侧的数据落地能力。任何一环掉链子最终你看到的都是丢包、溢出或者吞吐量上不去。1.1 单卡方案的三个硬性天花板我在早期验证阶段试过用单张 VU13P 硬扛全部数据流结论是理论可行工程上不划算。具体卡在三个地方。第一是收发器数量。VU13P 的 GTY/GTM 收发器数量虽然不少但你要同时接多路光纤输入、还要留出板间级联的通道再算上调试用的回环口通道分配会非常紧张。单卡把所有光纤口都用来收数据就没有余量做卡间互联了。第二是内部逻辑资源的争抢。200Gbps 的数据流进来之后你要做协议解析、数据对齐、缓存调度、格式转换这些逻辑本身就要吃掉大量 LUT 和 BRAM。如果所有处理都堆在一张卡上布局布线PR阶段会非常痛苦时序收敛难度陡增尤其是跨时钟域的部分。第三是功耗和散热。VU13P 满载功耗本身就高单卡承担全部负载时板卡局部热点温度会迅速攀升长时间跑下来稳定性堪忧。这不是靠加个风扇就能解决的涉及供电设计和散热结构的整体考量。所以多卡级联不是为了炫技而是被带宽、资源和热设计逼出来的必然选择。1.2 多卡级联的核心思路分工而不是堆叠多卡级联最容易走偏的思路是把四张卡当成一张大卡用也就是让每张卡都做同样的事只是数据分片。这种做法在理论上没问题但实际落地时会遇到同步和汇聚的麻烦。我更推荐的思路是功能分工让一部分卡专门负责数据接收和预处理另一部分卡负责汇聚和深度处理卡与卡之间通过光纤口做高速互联。这样每张卡的职责清晰资源分配也更合理。具体到 200Gbps 这个量级一个比较稳妥的架构是前端采集卡2张每张负责约 100Gbps 的原始数据接入做物理层对齐、CRC 校验、初步过滤汇聚处理卡1张接收前端卡送来的数据做全局排序、聚合、格式统一输出/存储卡1张把处理完的数据通过高速接口送给上位机或存储阵列。这个分工不是固定的你可以根据实际的数据特征调整。但核心原则是不要让任何一张卡同时承担收、聚、发三个角色否则资源争抢会让你在时序收敛阶段痛不欲生。1.3 光纤口在这里扮演什么角色光纤口也就是高速串行收发器加光模块的组合在多卡级联里承担两个任务一是板间数据通道二是时钟同步的物理基础。用光纤而不是铜缆做板间互联主要考虑三点传输距离不受限于铜缆的衰减、抗电磁干扰能力强、单通道速率可以做到很高25Gbps 甚至 50Gbps 每通道。对于 200Gbps 的汇聚需求你可以用多通道并行来实现比如 8 通道 × 25Gbps或者 4 通道 × 50Gbps。这里有个实操细节通道绑定Lane Bonding的 skew 控制。多通道并行传输时各通道之间的到达时间差必须控制在一个很小的范围内否则接收端无法正确重组数据。VU13P 的 GTY 收发器支持通道绑定但你需要正确配置 buffer 和 deskew 逻辑这部分后面会详细讲。2. 硬件拓扑与通道分配把200Gbps拆成可落地的数字聊完为什么要多卡接下来必须把 200Gbps 这个数字拆开落到每一根光纤、每一个收发器通道上。很多项目在方案阶段就埋了雷就是因为拓扑设计时没有把带宽账算清楚。2.1 四种常见拓扑的取舍多卡级联的拓扑结构直接决定了数据流向和同步复杂度。我实际验证过或见过别人用的主要有四种拓扑类型结构描述优点缺点适用场景星型一张主卡连接多张从卡控制简单主卡统一调度主卡带宽压力大单点瓶颈卡数少、汇聚比高环形卡与卡首尾相连布线规整扩展方便延迟随卡数增加故障影响全局流水线处理网状任意两卡可直连路径灵活带宽充裕收发器消耗大布线复杂卡数少但交互密集混合型前端星型后端环形兼顾灵活与效率设计复杂度高大规模级联对于 200Gbps 四卡级联这个具体场景我最终选的是混合型两张前端采集卡各自通过独立光纤链路连到汇聚卡星型部分汇聚卡再通过一条高速链路把处理结果送到输出卡点对点部分。这样前端到汇聚是并行的不会互相抢带宽汇聚到输出是串行的但只需要一条链路。2.2 每张卡的收发器预算算收发器账的时候不能只看数据带宽还要把协议开销、调试通道、冗余留出来。我一般按实际带宽 × 1.2来估算所需通道数。以 25Gbps 每通道为例前端采集卡接收 100Gbps 原始数据需要 4 通道接收向汇聚卡发送 100Gbps需要 4 通道发送。加上 1 通道调试回环总共约 9 通道。汇聚卡接收两路各 100Gbps需要 8 通道接收向输出卡发送 200Gbps需要 8 通道发送。加上调试通道约 17 通道。输出卡接收 200Gbps需要 8 通道接收加上上位机接口和调试通道约 10 通道。VU13P 的 GTY 收发器总数是够的但你要注意收发器在芯片上的物理分布。不同 Quad 的收发器到高速接口的走线长度不同高速通道尽量选靠近光模块的 Quad可以减少信号完整性问题。2.3 参考时钟与同步方案多卡级联最容易被低估的就是时钟问题。每张卡都有自己的参考时钟源如果各卡时钟独立运行即使频率标称相同实际也会有 ppm 级的偏差。这个偏差在短时间内看不出来但跑上几分钟之后各卡的数据缓冲区就会因为读写速率不匹配而溢出或读空。我的做法是选一张卡作为时钟主卡通过光纤链路把时钟信息嵌入数据流中传输从卡从数据流中恢复时钟。VU13P 的 GTY 收发器支持从接收数据中恢复时钟CDR恢复出来的时钟可以作为从卡本地逻辑的参考。具体实现上我在发送端的数据帧里插入周期性同步字接收端用同步字做相位对齐。这样即使各卡本地晶振有偏差也能通过同步字不断校正保证长时间运行不漂移。注意时钟恢复的环路带宽要仔细调。带宽太窄跟踪不上快速抖动带宽太宽又会把发送端的抖动放大。一般建议环路带宽设在 1MHz 到 4MHz 之间具体值要根据你的数据帧结构和抖动容限来定。3. 光纤链路的物理层配置从GTY参数到眼图物理层是整个级联系统的地基。地基没打好上层逻辑写得再漂亮也没用。这一章我把 GTY 收发器的关键配置和调试过程拆开讲。3.1 GTY收发器的关键参数VU13P 的 GTY 收发器配置项很多但真正影响链路稳定性的核心参数就那么几个。我列一个实际项目中用到的配置表参数设置值说明Line Rate25.78125 Gbps对应 100G 以太网的每通道速率Reference Clock161.1328125 MHz晶振频率需与线速率匹配Encoding64b/66b开销小直流平衡好TX Diff Swing800 mV根据光模块驱动要求调整TX Pre-emphasis3.5 dB补偿通道高频损耗RX EqualizerDFE CTLE自适应均衡应对通道损耗CDR Loop Bandwidth2 MHz时钟恢复环路带宽这些值不是拍脑袋定的。TX Pre-emphasis 要根据你的 PCB 走线损耗来调走线越长、损耗越大预加重就要越大。RX 端的均衡器则要跟发送端的预加重配合最终目标是让接收端的眼图张开度足够大。3.2 眼图调试的实操过程眼图是判断物理层链路质量最直观的工具。我一般用误码仪BERT或者 FPGA 内置的 IBERT 工具来扫描眼图。调试步骤大致是这样先扫 TX 眼图在发送端不加预加重的情况下用示波器看输出眼图。如果眼图已经闭合说明发送端配置有问题先解决发送端。加预加重再扫逐步增加预加重值观察眼图张开度的变化。找到张开度最大的那个点但不要取极值留一点余量。扫 RX 眼图在接收端用 IBERT 扫描水平和垂直方向的眼图。水平方向反映的是时钟恢复的质量垂直方向反映的是幅度余量。记录最佳采样点眼图中心就是最佳采样点。实际配置时采样点要稍微偏离中心一点偏向历史数据一侧这样对抖动更有容忍度。我踩过的一个坑是眼图看着很好但误码率就是下不去。后来发现是通道间的 skew 没有校准。眼图只反映单通道质量多通道绑定时还要看通道间的对齐情况。3.3 通道绑定与skew校准多通道绑定传输时各通道的到达时间差skew必须控制在一个 bit 周期以内否则接收端无法正确重组数据。VU13P 的 GTY 支持自动 skew 校准但需要正确配置。校准的基本流程是发送端在所有通道上同时发送一个已知的对齐序列接收端测量各通道到达时间的差异然后通过调整各通道的 buffer 延迟来对齐。这里有个经验值skew 校准后的残余偏差应小于 0.2 UIUnit Interval。对于 25Gbps 的线速率1 UI 约等于 40ps0.2 UI 就是 8ps。这个精度要求对 PCB 走线等长设计提出了很高的要求一般要求各通道走线长度差控制在 5mm 以内。提示如果 PCB 已经做好了走线等长没法改可以通过 GTY 内部的延迟调整来补偿。但补偿范围有限一般只能补几百 ps。所以最好在设计阶段就把等长做好。4. 数据流架构从接收、缓存到汇聚的完整链路物理层通了之后接下来就是数据怎么在 FPGA 内部流转。这部分是逻辑设计的核心也是资源消耗的大头。4.1 接收路径的分层设计我把接收路径分成四层物理层接口层、协议解析层、缓存调度层、汇聚输出层。每一层的职责明确层与层之间通过标准化的接口通信。物理层接口层直接对接 GTY 收发器负责串并转换、8b/10b 或 64b/66b 解码、通道对齐。这一层的输出是整齐的并行数据流位宽一般是 64 位或 128 位。协议解析层负责识别数据帧的边界、提取有效载荷、做 CRC 校验。如果数据有特定的协议格式比如自定义的帧结构这一层还要做字段解析。缓存调度层是整条链路的关键。数据从接收端进来速率可能不均匀需要先缓存再平滑输出。我用的是异步 FIFO 令牌桶的组合FIFO 解决跨时钟域和速率匹配问题令牌桶控制输出速率防止下游溢出。汇聚输出层把多路数据合并成一路做最终的格式转换和发送。4.2 缓存深度的计算方法缓存深度不够会导致溢出丢包缓存太深又会增加延迟和 BRAM 消耗。怎么算这个深度基本公式是缓存深度 最大速率差 × 最大突发持续时间。举个例子接收端瞬时速率是 100Gbps下游处理能力是 80Gbps速率差是 20Gbps。如果最大突发持续时间是 10 微秒那么需要的缓存深度是20Gbps × 10μs 200Kbit 25KB考虑到位宽转换和余量实际配置我会取 32KB 到 64KB 的 BRAM。但实际项目中速率差往往不是恒定的而是随数据内容波动的。这时候就要用动态水位线来控制设置高水位线和低水位线水位超过高线时通知上游降速低于低线时通知上游提速。这样可以在保证不溢出的前提下尽量减少缓存深度。4.3 跨时钟域处理的三个原则多卡级联系统里跨时钟域CDC是绕不开的。我的处理原则是第一能不用异步就不用异步。如果两个时钟域的频率是整数倍关系尽量用同步设计避免 CDC 带来的不确定性。第二必须异步时用握手而不是打拍。简单的打两拍同步只适用于单比特控制信号多比特数据必须用握手协议或者异步 FIFO。第三CDC 路径要做时序约束。很多人忘了给 CDC 路径加set_false_path或set_max_delay约束导致工具在优化时把这些路径当成普通路径处理引入了不必要的延迟甚至错误。我在一个项目里遇到过因为 CDC 约束缺失导致的问题数据在跨时钟域时偶尔出现错误但仿真时完全复现不出来。后来加了set_max_delay -datapath_only约束问题才消失。这个坑排查了整整两天。5. 时序收敛与布局布线多卡设计中最耗时的环节多卡级联设计的时序收敛难度比单卡设计高出一个数量级。原因很简单逻辑资源用得多、时钟域多、跨时钟域路径多、高速接口的时序要求苛刻。这一章我讲讲实际项目中怎么把时序啃下来。5.1 时序收敛的优先级策略面对一个时序违例一大堆的设计最忌讳的是哪里违例改哪里。正确的做法是先分类再按优先级处理。我的优先级排序是高速接口时序GTY 相关的时序必须最先收敛这是整个系统的基础。跨时钟域路径CDC 路径的时序问题会导致功能错误优先级仅次于高速接口。关键数据路径数据流的主通道时序违例会直接影响吞吐量。控制逻辑控制路径的时序余量一般较大可以最后处理。处理每一类时手段也不同。高速接口主要靠约束和位置约束CDC 路径靠约束和同步器结构数据路径靠流水线切割和逻辑优化。5.2 流水线切割的实操技巧数据路径时序违例最有效的办法是加流水线。但流水线不是随便加的加不好会引入新的问题。我的经验是在组合逻辑深度超过 4 级的地方加流水线。VU13P 的 LUT 延迟和布线延迟加起来4 级组合逻辑差不多就是一个时钟周期的极限。流水线寄存器要加在数据路径上不要加在控制路径上。控制路径加流水线会改变控制时序可能导致功能错误。加流水线后要重新评估延迟。流水线会增加数据延迟如果系统对延迟敏感要重新计算。还有一个技巧是用寄存器复制来减少扇出。当一个信号扇出很大时布线延迟会显著增加。把信号复制几份分别驱动不同的负载可以有效减少延迟。5.3 位置约束的使用时机位置约束Placement Constraint是一把双刃剑。用得好可以显著改善时序用不好会让布局布线变得极其困难。我一般在两种情况下使用位置约束一是高速接口的收发器位置。GTY 收发器的位置是固定的必须用位置约束把它们锁定到正确的 Quad 上。二是关键模块的区域约束。当一个模块的逻辑被工具散布到整个芯片上时模块内部的布线延迟会很大。用Pblock约束把这个模块限制在一个区域内可以显著减少布线延迟。但位置约束不要滥用。我见过有人给每个模块都加了区域约束结果工具没有足够的布局空间布线失败。一般来说只给最关键的 2 到 3 个模块加区域约束就够了。6. 实测数据与踩坑记录前面讲的都是设计层面的东西这一章我分享一些实测数据和实际踩过的坑。这些内容在官方文档里找不到都是真金白银换来的。6.1 实测吞吐量与资源占用最终系统在四卡级联配置下的实测数据指标实测值备注持续吞吐量198.5 Gbps理论值的 99.25%端到端延迟约 12 μs从接收到输出误码率 1e-15连续运行 72 小时单卡 LUT 占用约 65%汇聚卡最高单卡 BRAM 占用约 70%缓存消耗为主单卡功耗约 75W满载吞吐量没有跑到 200Gbps 整是因为协议开销和同步字的占用。198.5Gbps 的有效吞吐已经满足大部分应用需求。6.2 三个印象深刻的坑第一个坑光模块兼容性。我们最初选了一款便宜的光模块规格书上写的支持 25Gbps但实际跑起来误码率很高。换了好几个批次都一样。后来换成另一款品牌模块问题立刻消失。教训是光模块不要只看规格书要实际测试。不同厂家的模块在抖动、消光比等指标上差异很大。第二个坑电源纹波导致的高速链路不稳定。系统跑一段时间后偶尔出现链路中断。排查了很久最后用示波器看电源纹波发现 GTY 供电轨上的纹波超标。加了滤波电容之后问题解决。高速收发器对电源质量非常敏感供电设计不能省。第三个坑散热不足导致的性能降级。在密闭机箱里连续跑几个小时后吞吐量会缓慢下降。一开始以为是逻辑问题后来监控温度发现芯片结温超过了 100 度触发了内部降频保护。改善散热结构后吞吐量恢复稳定。VU13P 这种大芯片散热设计要按满载功耗的 1.5 倍来留余量。6.3 长时间运行的稳定性验证短时间跑通不难难的是长时间稳定运行。我一般会做三轮验证第一轮72 小时连续运行监控误码率、吞吐量、温度、功耗。第二轮温度循环测试从低温到高温反复循环验证温度变化对链路的影响。第三轮电源波动测试模拟供电电压波动验证系统的容错能力。这三轮下来基本能覆盖大部分实际使用场景。如果还有问题那多半是设计层面的隐患需要回到原理图或逻辑层面排查。7. 几个容易被忽略的工程细节最后分享几个在实际项目中容易被忽略但影响很大的细节。7.1 复位信号的亚稳态处理多卡系统里复位信号往往来自不同的时钟域。如果复位信号没有做同步处理释放时可能落在时钟的亚稳态窗口导致部分寄存器复位、部分没有复位系统行为不可预测。我的做法是所有复位信号都经过两级同步器并且在同步器之后加一个复位展宽电路保证复位信号至少保持若干个时钟周期。这样即使复位释放时遇到亚稳态也能在下一个周期稳定下来。7.2 调试通道的预留多卡系统一旦部署到机箱里再想接调试器就很麻烦。所以设计阶段一定要预留调试通道。我一般会预留至少一路低速串行通道比如 UART 或 I2C用于读取各卡的运行状态、温度、误码计数等信息。另外还会预留一路高速回环通道用于在线测试链路质量。这些调试通道在正常工作时可以关闭不占用带宽需要时再打开非常方便。7.3 固件升级的考虑FPGA 的固件升级是个麻烦事尤其是多卡系统。如果每张卡都要单独接 JTAG 升级维护成本很高。我的方案是通过光纤链路做远程固件升级。在每张卡上预留一个小的配置控制器接收来自主卡的升级指令和数据写入配置 Flash。这样只需要连接主卡就能升级整个系统。这个功能在项目初期就要规划后期再加会很困难。7.4 日志与监控长时间运行的系统没有日志和监控就是盲人摸象。我在每张卡上都实现了轻量级的日志系统记录关键事件链路建立、链路中断、缓存溢出、温度超限等并通过调试通道上报。监控数据包括各通道误码计数、缓存水位、芯片温度、供电电压、吞吐量。这些数据实时上报到主卡主卡再汇总给上位机。有了这些数据出问题时能快速定位不用盲目猜测。这套监控系统本身也消耗资源但相对于它带来的运维便利这点资源消耗完全值得。我在实际项目中的体会是监控系统的投入在系统上线后的第一个月就能回本。