1. 写在前面:为什么SerDes是FPGA工程师绕不过去的一道坎
很多刚接触FPGA的朋友都会遇到这样一个场景:芯片选型的时候明明看中了高速接口能力,等真正拿到板卡准备调的时候,却发现所谓GTX、GTH、Transceiver这些名词一个个都认识,但连起来就完全不知道从哪儿下手。甚至不少做了两三年逻辑开发的工程师,一提到SerDes还是会下意识往后缩一下,觉得这东西太难了。
我个人的看法是,SerDes接口设计之所以让很多人觉得“劝退”,并不是因为协议本身有多深奥,而是因为它同时踩中了三个最容易让人劝退的点:第一,模拟前端的概念和数字逻辑完全是两套思维;第二,调试手段少,波形看不见摸不着,出问题全靠经验和眼力;第三,Xilinx和Intel两家工具的配置项差异极大,网上的教程大多是“点完IP就跑通”,根本没有解释为什么这么配、为什么这么连。
这篇文章我想从一个实际做过多个高速接口项目、踩过不少坑的工程师视角,尽量把FPGA实现SerDes的完整路径给你捋清楚。从GT Transceiver的架构分析开始,到IP核配置、代码结构、板级调试,最后集中整理一份避坑清单。目标是让刚要入门的人能从中找到一条可复现的路线,也让已经调过但总被奇怪问题卡住的同行,能对照里面的经验找到原因。
2. 高速接口设计整体思路:先搞清楚SerDes到底在解决什么问题
2.1 并行总线为什么到了Gbps级别就走不通了
在聊GT Transceiver之前,我们先退一步问一个很基本的问题:为什么需要SerDes?说白了就是串行器和解串器的合称,本质上是把多路并行数据在发送端变成一路高速差分信号,在接收端再把这一路高速信号还原成并行数据。那为什么不直接用并行总线传?答案是频率上不去了。
并行接口要传得够快,无非两条路:加宽位宽或者提高时钟频率。加宽位宽带来的问题是PCB布线面积和引脚数,而且每条线之间的等长关系、串扰控制难度都跟着飙升。提高时钟频率则直接撞上信号完整性的墙,数据有效窗口越来越窄,对于板级信号的反射、串扰、同步开关噪声都极度敏感。很多做过DDR3/DDR4的朋友应该有体会,那些并行总线的源同步时钟、读写DQS对齐,调起来已经够费劲了,再往上提速就是几何级的痛苦。
串行方案把高速信号集中到一两对差分线上,通过嵌入时钟、均衡器等手段来解决传输损耗和时钟同步问题。这样单通道速率可以轻松上到几Gbps甚至几十Gbps,而且线对数量大幅度减少,对PCB布局布线友好得多。这就是为什么今天几乎所有的高速接口——PCIe、SATA、USB3.x、以太网、CPRI、JESD204B——底层物理层全都是SerDes在做传输。
2.2 嵌入时钟、CDR与通道编码的关系
既然串行链路里只有数据线,没有单独的时钟线,那接收端怎么恢复出时钟来对数据进行采样呢?这就是SerDes架构里最有意思的部分。发送端在数据流里周期性嵌入时钟信息,接收端用CDR电路从数据边沿中提取出时钟,再拿这个恢复时钟去采样数据。
但是接收端的CDR并不是万能的,它需要数据流中频繁出现跳变沿才能持续跟踪频率和相位。如果发送的都是一长串0或者一长串1,数据线上根本没有电平翻转,CDR很快就不锁了。所以需要一种机制来保证数据流有足够的翻转密度,这就是通道编码存在的意义。
最常见的两种是8b/10b编码和64b/66b编码。8b/10b把8位数据映射成10位码字,通过查表保证连续0/1的游程长度不超过5位,同时保证足够多的跳变沿用于时钟恢复。代价是25%的编码开销,也就是说5Gbps的线速率实际有效数据带宽只有4Gbps。64b/66b开销小得多,只有3.125%,但同步字+扰码器的设计复杂度更高,一般用于更高端的GTH/GTY甚至更高速的接口。做项目选哪种编码,本质上是带宽利用率和实现复杂度之间的权衡。
2.3 FPGA里SerDes的实现载体:GT Transceiver
在Xilinx的FPGA里,承载SerDes功能的是GT Transceiver,根据器件系列分为GTP、GTX、GTH、GTY等,可以看作是FPGA内部的一排专用硬核模块。每一路GT通道包含发送端和接收端两大块,每一块又分成PMA模拟前端和PCS数字逻辑两层。Intel FPGA的Transceiver架构也是类似思路,只是命名和配置方式不同。
关键点在于,这些GT通道是独立于可编程逻辑的专用电路,它们走的不是CLB阵列,而是独立的电源域、独立的时钟网络和专用的高速参考时钟引脚。在做芯片选型的时候,高速接口通道数量往往直接决定了一颗芯片的价格档位,所以实际项目里必须精确规划需要多少通道、多少线速率,不能拍脑袋认为“既然有GT就用它传所有数据”。
3. GT Transceiver核心细节:PMA、PCS和时钟架构深度解析
3.1 从PMA到PCS:高速收发器里的分工逻辑
理解GT Transceiver最简单的方式,是把它拆成两个部分。PMA是靠近引脚的那部分模拟电路,负责差分信号的收发、串并转换、时钟恢复,说白了是一切和模拟、高速电信号相关的工作。PCS则是靠近FPGA逻辑的那部分数字电路,负责通道编码解码、弹性缓冲、时钟修正、伪随机码生成等,主要做数据的组织和格式处理。
开发的时候,我们在IP核配置界面设置线速率、参考时钟、协议模板,工具会帮我们把PMA和PCS的参数自动配置好。但这不代表开发者可以完全不理解这两层结构。调试的时候经常遇到一个情况:数据一帧一帧地错误,但链路已经up了。这种问题往往就是PCS层的对齐、弹性缓冲设置不对,而不是模拟层的问题。反过来,如果链路根本起不来,那就是PMA层的CDR没锁上、均衡没调好、差分极性接反了这类模拟层问题。
我之前带过一个项目,链路就是一直up不了,Xilinx的ibert工具里看到RX端状态一直显示no signal。排查了半天,最后发现是板子上差分对的正负端接反了,PMA层的极性未设置,导致CDR根本无法锁定。这种问题如果不懂PMA和PCS的分工,会比较难定位。
3.2 时钟架构:参考时钟、发送时钟与恢复时钟
GT Transceiver的时钟体系是整个设计的灵魂,也是最多人踩坑的地方。总共有三套时钟需要理清楚。
第一套是参考时钟,从专用REFCLK引脚进入GT通道。参考时钟经过内部的PLL倍频之后,产生串行高速时钟,用于确定发送端的线速率。参考时钟的频率不是随便选的,而是由线速率和PLL配置共同决定的。比如5Gbps的线速率,参考时钟可以用125MHz,也可以用250MHz,甚至100MHz,但每一种配置对应不同的PLL倍频系数。关键是参考时钟本身的精度和抖动必须达标,这个抖动指标是皮秒级别的,直接用普通的板上时钟是不行的,通常要选专用的低抖动晶振。
第二套是发送端的并行时钟,也就是TXUSRCLK。发送的并行数据要在TXUSRCLK的节拍下写入GT通道的FIFO,然后由PCS层打包发送。这个并行时钟频率是由线速率除以接口位宽得到的。比如5Gbps、32位接口,那么TXUSRCLK就是156.25MHz。需要特别注意的是,这个时钟要与GT内部PLL输出的时钟同源,所以IP核一般会提供一个TXOUTCLK,外部逻辑必须把这个时钟反馈回TXUSRCLK输入,或者通过BUFG连接过去。这点在实际设计中极其容易出错,很多人写成异步时钟就直接废了。
第三套是接收端的恢复时钟。RX恢复时钟由CDR电路从收到的数据流中提取出来,经过分频后得到RXUSRCLK。因为发送端和接收端的参考时钟总存在细微的频率偏差,所以RXUSRCLK和本地逻辑的时钟不是完全同频的,需要通过PCS层弹性缓冲和时钟修正机制来抵消这种偏差。这也是为什么很多SerDes协议里会规定必须周期性发送逗号字符或者SKP Ordered Set,目的之一就是做时钟修正。
3.3 回环模式:最强大也是最重要的调试武器
GT Transceiver里内置了多种回环路径,这是调试高速链路最实用的功能,我甚至觉得学会了用回环模式,SerDes调试就成功了一半。
近端PMA回环(Near-End PMA Loopback)是直接在PMA的串行输出端把数据环回到同一通道的PMA输入端,信号不经过引脚,也不经过PCB走线。这种回环用来验证GT通道本身是否工作正常,因为信号没有经过物理通道,链路建立速度最快。近端PCS回环(Near-End PCS Loopback)则是在PCS层直接把数据环回,用于验证PCS逻辑配置是否正确。
远端回环(Far-End PMA Loopback)是把数据发到对端设备,对端设备在PMA层把收到的数据原路返回。这种模式下信号经过了真实的PCB走线,但不对端关注协议的上层处理逻辑,通过这种方式可以验证物理链路和通道配置。
调试的顺序建议是从近端PCS回环开始,然后近端PMA回环,再跳到远端回环。每跳一个模式都能缩小可能出问题的范围。我在实际项目中总结出的经验是,不管是IBERT自带的误码测试,还是用户自定义那逻辑,只要回环模式能误码为零,就说明GT通道的物理层没有大问题,后面就可以放心去调协议层。
4. 实操过程:基于Xilinx 7系列从IP配置到环路测试全流程
4.1 前期准备:确认参考时钟和线速率的匹配关系
拿到板子的第一步,不是开Vivado建工程,而是先看原理图,确认REFCLK引脚接在哪、频率是多少、哪几个GT通道共享这个参考时钟。以Xilinx Artix-7系列为例,通常一个QUAD里有四个GTX通道共用一组参考时钟输入,如果用错了QUAD或者频率不匹配,IP配置时就会报错,或者干脆无法生成线速率。
确定线速率时要同时考虑三个因素:实际需要的有效带宽、参考时钟频率是否匹配、FPGA芯片的GTX最高速率是否足够。Artix-7的GTX最高线速率一般是6.6Gbps,Kintex-7的GTX能到12.5Gbps,Virtex-7的GTH更高一些。做设计需求评估时,一定要留出通道编码的带宽开销。比如用8b/10b编码时,如果应用层需要3Gbps有效带宽,对应的线速率至少得3.75Gbps,一般留足余量取4Gbps或5Gbps。
时钟选择上还有一个隐藏问题:PCB上REFCLK走线的质量。很多开发板的参考时钟为了兼容多协议,会用一个可编程时钟芯片输出,这种时钟在低频时没问题,但在高频需求下抖动指标可能不够。连接GTX的REFCLK如果走线过长或者过孔太多,也会引入额外的抖动。如果是自研板,强烈建议给出专用低抖动时钟源给REFCLK。
4.2 IP核配置:GTX Transceiver关键选项逐项分析
在Vivado中调用GT Wizard时,配置界面虽然很多,但其实核心选项就那么几类。第一类是协议模板,如果只是做自定义传输,可以选Start from Scratch,避免被模板自动带入一堆不需要的协议配置。第二类是线速率和参考时钟,这里要填入目标线速率和参考时钟频率,工具会自动计算并显示TX/RX User Clock的频率。第三类是编码方式,8B/10B还是其他,这一步决定后面的有效带宽。
第四类是接口位宽。我个人的建议是保证数据位宽和实际处理字节对齐,比如用8b/10b编码时,位宽最好选20bit或40bit这样的整数倍,可以避免后续逻辑中处理半字节对齐的麻烦。位宽越大,并行时钟越低,对FPGA逻辑时序的压力越小,但代价是GT通道和逻辑之间数据总线的宽度会更大,占用更多布线资源。
第五类是控制接口和状态信号。常见的有TX/RX Reset Done、TX/RX Polarity、Loopback控制等。必须把TX Reset Done和RX Reset Done信号引出来,做外部复位逻辑的状态判断,这是最容易忽略的。
工具配置完成后会生成一个example design,里面包含了GT初始化状态机和简单的数据通路。建议初学者在这个基础上进行修改,而不是完全自己写初始化流程。GT的复位时序非常讲究,自己写出错概率很高。
4.3 代码结构:基于Example Design重构用户数据通路
用Example Design做底板之后,通常要做三件改造:精简掉不需要的模块、加入自己的数据源和校验逻辑、改掉默认的时钟来源。
我先看一下例程里的初始化状态机,它会在复位释放后依次完成GT TX和RX的复位、等待Reset Done信号拉高、然后切换用户时钟。这些步骤的顺序不能乱改,尤其是等待Reset Done信号这一步,必须在用户时钟稳定之后再去操作数据通路。很多自定义设计跑飞,问题就出在Reset Done还没拉高就开始往GT里灌数据了。
接着是数据通路。Example Design里通常会包括一个简单的数据发送模块和一个接收比对模块。我们可以把发送模块替换成自己的PRBS生成器或者自定义帧结构,接收端替换成对应的校验模块。测试初期强烈建议先用PRBS做误码测试,因为PRBS可以自动校验误码,不需要复杂的组帧和解帧逻辑,便于把注意力集中在物理链路上。
PRBS模块的数据位宽要和GT的接口位宽一致,比如32位的接口就生成32位的PRBS,GT IP内部会自动把32位并行数据拆成串行比特流发送,接收端接收后并行输出,再做PRBS校验。如果CRC或者帧校验和不对,先不要怀疑链路数据,先检查是不是PRBS生成器多项式没对齐。
4.4 回环模式下的第一次链路建立
当IP配置、例程代码跑通之后,先别急着接对端设备,第一步做片内回环。
把GT的Loopback端口设为近端PCS回环,然后上位机通过JTAG或者逻辑分析仪观察复位状态机的状态和Reset Done信号。如果Reset Done能正常拉高,说明GT通道初始化成功,PCS层的配置没问题。接下来切换到近端PMA回环,这时候信号经过了PMA内部的串并行转换和CDR电路,链路是否能够建立就取决于CDR能否锁定。用Vivado的IBERT工具可以更直观地看到RX眼图和误码率。
近端PMA回环如果误码为零,恭喜你,GT通道本身的物理层基本可靠。这时候就可以把回环模式切回正常模式(none),然后接上对端设备做远端回环测试。远端回环时重点观察CDR Lock状态和误码情况。如果误码高企且不稳定,首先考虑的是参考时钟的频偏是否超过了CDR的跟踪范围,其次是PCB走线的回损、串扰等信号完整性问题。
4.5 高级测试:眼图扫描与参数调整
当误码率持续处于一个不太理想但又不至于完全断链的状态时,可以用IBERT做眼图扫描。眼图的打开程度直接反映了这条链路的信号裕量。如果眼图闭合得厉害,可以先尝试调整RX端EQ均衡器的设置。GTX的RX均衡器通常支持多级可调,从DFE到LPM,需要在性能与功耗之间做权衡。
发送端的预加重和去加重参数也需要根据PCB走线长度来调整。通常走线越长,高频损耗越大,需要加大去加重强度来补偿。这个过程没有太多理论捷径,基本是靠实测+手感。我通常会先试几个极端值看看眼图趋势,再通过二分法逼近最优值。这个方法虽然土,但确实是最快的。
做IBERT扫描的时候还要注意选择的PRBS类型要和链路的位宽、速率匹配。通常PRBS-7用于短距离或者调试阶段,PRBS-15、PRBS-23更接近真实数据的频谱特性,用于最终验收阶段。如果测试时用PRBS-7能通过,换PRBS-23就不断报错,这基本上说明链路裕量已经接近临界了,不适合批量生产。
5. 避坑指南:高速接口设计中那些教科书里不写的坑
5.1 复位时序:GT的复位和FPGA逻辑复位必须分开处理
这是我个人认为SerDes设计里排第一的坑。很多人习惯性地把GT的复位信号和整个FPGA的全局复位连在一起,一按复位键就全部重来。这种做法在低速逻辑里没问题,但是GT的复位释放过程有严格的先后顺序,从PLL复位到TX复位再到RX复位,每一级都要等上一条链路完成,而完成标志就是Reset Done信号。
正确的做法,是在GT IP外部用状态机构建一个复位时序控制器,等待各部分的Reset Done拉高之后再释放数据通路的复位。同时,在对外部逻辑而言,必须等两者Reset Done同时为高之后,才能开始收发数据。如果这两个信号没处理好,即使GT内部实际上是正常的,数据通路也完全无法工作,而且问题看起来时好时坏,排查起来极其痛苦。
此外,GT的复位还有软复位和硬复位之分。软复位只复位特定的通道功能,比如只复位RX或者只复位PLL,不会影响整个QUAD;硬复位则会复位整个QUAD内的所有通道。设计复位逻辑时分清楚这两者的区别,避免小问题引发大范围的重新初始化。
5.2 时钟修正与弹性缓冲:频偏的隐形杀手
弹性缓冲是PCS层中用来吸收发送端和接收端之间的频率偏差的存储器。它工作在恢复时钟域和本地用户时钟域的边界上,通过不断调整读指针的位置来容忍累积的频率误差。
问题在于,这个容忍范围是有限的。如果两端参考时钟的频偏超过了容限,长时间运行后缓冲就会溢出或者下溢,导致数据出现连续的未对齐错误。我遇到过最典型的场景,是用一个质量很差的参考时钟源,实际频率偏差达到了上千ppm,远超过GTP默认设置的几百个ppm容限,结果表现为系统运行十几分钟后突然出现一团乱码,随后又自行恢复,非常隐蔽。
解决方式有两种:一是更换更高精度的参考时钟源;二是利用协议层做时钟修正。比如8b/10b协议通常会在帧结构中周期性插入逗号字符,PCS层遇到逗号字符时会做一次时钟修正,重新调整缓冲指针,从而避免溢出。设计自定义协议时,必须在帧结构中预留这类修正字段,否则长时运行必出问题。
5.3 极性反转与差分端接:看起来很小,坑起来要命
板上差分走线在设计时偶尔会出现正负端标示相反的情况,或者连接器到子卡之间的走线发生了定义反转。这时候链路表现为要么完全无法锁定,要么数据全部取反,但CDR还能勉强锁定。GTX的收发端都提供了极性控制端口,TX Polarity和RX Polarity,通过设置可以翻转单端的逻辑电平极性。
排查这个问题的技巧是,先发一个固定值,比如0xBC,然后看接收端收到的数据。8b/10b编码时,发送数据的码字有明确极性属性,如果收到的数据总是呈现按位取反的关系,那大概率就是极性接反了。设置一次极性翻转之后,再看数据是否正确,就能快速确认。
还有一个容易让人困惑的点:如果只是RX端数据全反,可能是接收极性接反;如果TX端明明发得对但RX端所有数据都呈现取反状态,也有可能是发送端极性反了,导致发送出去的信号的差分极性本身就反了。不要被“接收端数据反了就是因为接收端极性错了”这种思维定式带偏。
差分端接的问题同样隐蔽。很多板子的GTX引脚附近没有加交流耦合电容,或者加了耦合电容但差分阻抗不匹配。交流耦合电容的容值和带宽需要根据线速率选择,太小会衰减低频分量导致眼图变差,太大则占据板面积且成本更高。一般0.1uF是几个Gbps速率下的常见选择,但更高速率可能要用低到0.01uF的电容才能保证足够的带宽。见过不少速率上不去的情况,最后发现就是耦合电容选大了。
5.4 参考时钟的抖动到底会有多致命
之前说过参考时钟的抖动很重要,这里展开讲一下实际案例。有一次做5Gbps的GTX链路,代码和配置完全照搬一个成功的旧项目,但新板卡就是跑不稳定,误码率一直降不下来。排查到最后,发现新板卡的参考时钟源有一颗电源纹波特别大。
GTX内部的PLL在倍频参考时钟时会同时把参考时钟上面携带的相位噪声按倍频系数放大,线速率越高放大越明显。如果参考时钟在几十kHz到几MHz频偏范围内的相位噪声超标,PLL输出的高速时钟的抖动就会严重恶化,最终直接体现在接收端眼图闭合上。这也是为什么Xilinx要求MGT参考时钟必须使用专用的低抖动振荡器输出,而不能直接共享用于FPGA逻辑的普通时钟。检查参考时钟质量时,除了看频率精度和ppm,一定要关注抖动指标,有条件的话用频谱仪看一下相位噪声曲线。
5.5 电源完整性:SerDes的命门
GT Transceiver对电源的敏感程度远高于普通逻辑,尤其是PMA和PLL的供电。Xilinx器件手册中对于MGT供电电源的纹波要求通常只有十几毫伏甚至几个毫伏。普通数字逻辑的供电如果纹波高一些可能只是增加延迟不确定性,但MGT的模拟电路如果供电纹波超标,会直接表现为高速信号抖动恶化、CDR失锁。
PCB设计时需要重点关注两个方面:一是MGT电源的滤波电容要尽可能靠近FPGA的供电引脚,并且电容组合要覆盖宽频带的去耦需求;二是MGT电源与数字逻辑电源尽量分隔,避免数字逻辑的开关噪声耦合到模拟电源域。这些工作做在原理图和PCB阶段是最省力的,如果等调试时才发现电源有问题,改板成本极高。
我见过一个团队,产品在高低温循环测试时频繁出现断链,排查了一周最后发现是一个DC-DC电源在低温条件下纹波飙升,导致GTX的CDR失锁。问题不在FPGA逻辑,也不在软件配置,完全在电源设计。
5.6 开发板调试的常见误区与排查速查表
调试SerDes链路时,最容易陷入的误区就是“盲猜”。一会儿猜是配置问题,一会儿猜是代码问题,一会儿又觉得是板子问题。实际上,高速链路调试最高效的方式是分层隔离,把问题定位到PMA、PCS、用户逻辑三个阶段中的某一个。
我把平时排查过程中遇到的高频问题整理成一个速查表,基本能覆盖95%的初级调试场景:
| 现象 | 可能原因 | 排查手段 |
|---|---|---|
| Reset Done不拉高 | 参考时钟没进来或者频率/电平不对 | 示波器测量REFCLK引脚,确认频率和摆幅 |
| Reset Done正常,但数据全错 | 极性接反、接口位宽不匹配、时钟频率错误 | 发送固定码型,检查接收数据与预期关系 |
| 误码率极高且不稳定 | 电源纹波大、参考时钟抖动超标、走线阻抗异常 | IBERT做眼图扫描,调整均衡参数 |
| 运行一段时间后突发误码 | 弹性缓冲溢出、时钟修正机制失效 | 检查频偏,确认帧结构中时钟修正字段 |
| 链路建立不了,回环也不通 | GT通道配置错误、电源异常 | 先用Near-End PCS回环逐级排除 |
| 8b/10b编码运行时偶发跑偏 | 逗号对齐失败、码字边界错位 | 增加码流中对齐字符密度,检查PGM序列配置 |
6. 从测试到落地:自定义协议的工程化要点
6.1 用户数据通路与GT接口的位宽对齐策略
当链路物理层稳定之后,面临的下一件事就是怎么把自己要传的业务数据正确地塞进GT接口。GTX的并行数据接口位宽通常是20bit或40bit(8B/10B模式)或32bit/64bit(不使用8B/10B时),而业务数据往往是一整字节对齐的。这里的关键就是字节对齐问题。
比如使用20bit位宽的8B/10B模式时,20bit实际上包含两个10bit的编码组,也就是两个字节的数据。如果业务数据是32位总线,直接往20bit接口上怼,肯定不行。需要先把32位数据拆成4个字节,每两个字节编码为一组,再按时钟节拍送入20bit接口。这个过程看起来简单,实际操作中容易在数据补齐、组帧、跨时钟域处理上出bug。
我的建议是最初设计的时候就把数据通路层和GT接口层彻底分开,中间通过FIFO或者自定义握手接口做缓冲。GT接口层只需关心如何把发送FIFO里的数据取出来塞进GT,以及把GT收到的数据写进接收FIFO。业务逻辑不需要知道GT接口是20bit还是40bit,只需按自己习惯的位宽与FIFO交互。这样既降低了逻辑与GT耦合的复杂度,也为后续更换不同位宽的GT接口留了余地。
6.2 自定义协议时的帧结构与对齐字符设计
如果不需要兼容某种现成协议,纯粹做自定义传输,帧结构设计就完全取决于自己了。这里最容易掉坑的地方是对齐字符没有规划好。
8b/10B模式中,K字符(控制字符)用于标识特殊位置。自定义协议可以在数据流中周期性插入K字符作为码字边界标识。接收端在连续字节流中搜索K字符来建立字节对齐,所以K字符不能太稀疏,一般推荐每个对齐周期内至少出现一次,否则接收端重新对齐的时间会过长,影响链路恢复速度。
帧结构还应该包含长度字段和CRC校验。CRC在高速数据传输中几乎是必须的,因为物理层误码率即使很低,在数据量很大的情况下也会有个别比特翻转,没有CRC的上层是无法及时发现数据错误的。另外我强烈建议帧结构中加一个递增的帧序号字段,这样接收端可以看到丢帧和重排的情况,这在排查链路稳定性和FIFO溢出问题时非常有价值。
6.3 跨时钟域的一些经验:不要把恢复时钟直接当系统时钟用
GT接收端输出的RXUSRCLK是CDR恢复出来的时钟,它和发送端的时钟以及本地系统时钟之间存在频偏。直接把RXUSRCLK接到整个数据接收逻辑上,虽然可以简化数据通路,但会给后续跨时钟域处理埋下巨大隐患。
一个更稳妥的做法是,在GT的RX接口处放一个异步FIFO,写时钟用RXUSRCLK,读时钟用本地系统时钟。这样下游逻辑全部工作在本地时钟域,不需要再考虑恢复时钟与系统时钟的同步问题。但要注意,异步FIFO本身需要一个正确的空满指示逻辑,在读写速率差很小的情况下,经典同步器方案是够用的。如果速率差较大,要在FIFO设计中加适当的余量,防止读端连续读空。
我自己做接收通路时通常会在FIFO后端再加一个简单的链路状态机,定期检查是否有新数据到达,如果长时间无数据且FIFO为空,就判定链路异常,对外输出一个错误状态。这种“看门狗”逻辑对现场运维特别有用,能快速区分是链路断了还是数据本身就是这么稀疏,对调试帮助很大。
7. 最后的实战心得:从一个过来人的角度多说几句
SerDes接口设计说难确实难,它要求同时具备模拟电路、高速数字电路、协议设计和FPGA开发的知识储备;说简单也简单,只要在正确的框架下按步骤走,它不过是一个可以预测和控制的工程过程。
我个人的体会是,做这类设计最重要不是背住某个IP的某个配置,而是建立一套自己的调试方法论。我在每个SerDes项目里都会刻意做三件事:一是先把回环模式玩透彻,让物理层验证变成习惯动作;二是保留一个最小可用的工程版本,每次改动都做差分对比,防止改着改着把一个能用的项目改成半死不活;三是在工程里留下充分的观测信号,不管是IBERT还是逻辑分析仪,尽量能实时看到关键信号的中间状态。
另外有一点想特别提醒,不要迷信网上那些“照着点几下就通了”的教程。对应到SerDes这个领域,配置工具只是把寄存器的值写对了,真正难的是理解这些值背后的物理意义和系统约束。你越早理解参考时钟、线速率、编码方式、位宽这四者之间的关系,后续做多通道扩展、更换器件型号、提升速率这些事情就越从容。
这篇内容写到这儿,差不多把我这些年积累的FPGA实现SerDes的核心经验都掏出来了。如果你刚好卡在某一步出不来,建议先停下来,回头对照一下第5节和第6节的排查思路,很多时候答案并不复杂,只是我们把问题想复杂了。