干过高速ADC或者射频直采项目的人,十有八九都被JESD204B的时钟配置折磨过。这个东西本身协议栈就分好几层,FPGA侧还要同时伺候 device clock、SYSREF、GT refclk,三个时钟一个不对,链路就给你脸色看。更头疼的是Xilinx关于JESD204B的资料分散在PG066(JESD204 IP核)和PG198(JESD204 PHY)两份文档里,很多人从头翻到尾,觉得看懂了,结果一上板子还是抓瞎。我自己第一次调JESD204B接口的时候,CGS(Code Group Synchronization)折腾了整整三天,最后发现问题的根源根本不是代码,而是PG066里一句不显眼的时序说明没注意到。今天就把我反复踩坑后总结出来的3个Xilinx文档细节拎出来说清楚,全部是PG066和PG198里重点标注过的内容,照着做未必能保证一次通,但至少能让你少走好几个礼拜弯路。
1. 先把JESD204B的时钟体系理清楚,不然细节无从谈起
在看文档细节之前,有必要先把JESD204B到底需要哪几路时钟、它们之间是什么关系这件事捋一遍。很多人在这一步就开始含糊,后面读PG066和PG198自然读不进去。JESD204B是纯串行同步协议,它对时钟的要求比普通LVDS/CMOS接口苛刻得多,因为数据恢复靠的是CDR,而CDR只能恢复出数据和时钟的相对关系,恢复不出绝对相位。
JESD204B链路涉及的核心时钟主要有三路。第一路是device clock,也就是JESD204B IP核的工作时钟,它决定了LMFC(Local Multi-Frame Clock)的生成,最终所有lane上的数据都在LMFC边界上对齐。第二路是SYSREF,这是subclass 1模式下的对齐参考信号,用来校准device clock的相位,使得发射端和接收端的LMFC边界精确对齐。第三路是GT reference clock,它经过GT的QPLL或者CPLL倍频之后产生串行收发器的位时钟,也就是线速率时钟。
这三路时钟的关系可以用一句话概括:SYSREF是“标尺”,device clock是“刻度”,GT refclk是“动力”。没有SYSREF,多片ADC或者多通道之间的边界就对不齐;没有device clock,JESD204B IP核内部状态机就跑不起来;没有GT refclk,高速收发器根本没法工作。三者缺一不可,而且它们之间的相位关系、频率比例都必须严格满足要求。
在实际工程中,这三路时钟通常由一个时钟芯片(比如LMK04828)统一产生,保证同源和确定的相位关系。但很多项目为了省成本,会用两个独立晶振分别给FPGA和ADC供时钟,这种情况下SYSREF和device clock的相位关系就完全不可控,JESD204B链路能建立起来纯属运气好。这也是为什么所有大厂参考设计里,时钟树都是精心设计过的,绝不是随手画的。
PG066和PG198这两份文档,本质上就是在回答一个问题:这三路时钟分别应该满足什么约束,以及不满足的话会出什么问题。接下来的三个细节,全部围绕这个核心展开。
2. 细节一:PG066里SYSREF采样窗口和LMFC相位关系的标注,比你想的更严格
PG066里关于SYSREF的描述分散在好几个章节,但最核心的时序约束藏在“Clocking”和“SYSREF”两个小节里。文档明确说明了SYSREF信号必须与device clock满足建立时间和保持时间的要求,并且SYSREF的采样是发生在device clock的上升沿。这里面最容易被忽略的一点是:IP核内部对SYSREF的采样并不是单纯的打两拍同步,而是有一个确定性的采样窗口,用来区分SYSREF是落在当前LMFC周期的哪个阶段。
为什么这个重要?因为JESD204B链路建立时,接收端和发射端都要在SYSREF的边沿之后重新对齐LMFC相位。如果SYSREF刚好落在device clock建立时间附近,采样结果就会不确定,IP核捕获到的SYSREF事件就会抖动,表现出来就是链路状态寄存器里的NIT(Non-Identical Lanes)或者SYSREF错误位置不定,严重时直接导致CGS失败。
2.1 PG066文档里关于SYSREF的三个关键参数,很多人根本没注意到
PG066的SYSREF章节明确提到了三个关键参数。第一个是SYSREF setup time,第二个是SYSREF hold time,第三个是SYSREF pulse width。这三个参数在文档的时序表格里都有给出,不同系列器件数值会有点差异,但量级都在几百皮秒到几个纳秒之间。我见过很多项目,SYSREF是从时钟芯片出来之后直接拉一根线到FPGA的普通IO,中间没有任何约束,板子仿真也过了,结果实测SYSREF建立时间差了几百皮秒,导致链路间歇性失败。
解决方案也很简单,就是严格按照PG066里的要求,在XDC里给SYSREF设置输入延迟约束,并且用set_multicycle_path配合set_false_path之类的约束约束掉多余路径。但坦白讲,与其事后补约束,不如在设计时就保证SYSREF走线足够短、足够干净,最好直接接到FPGA的专用SYSREF引脚上。Xilinx在UltraScale+系列里有Dedicated SYSREF pin,不占用普通IO,走线延迟是可控的。
2.2 连续SYSREF和单脉冲SYSREF的处理逻辑完全不同
PG066里关于SYSREF_MODE的描述也是一个高频出错点。文档把SYSREF分为两种模式:一种是连续模式(Continuous),另一种是单次模式(One-shot)。连续模式要求SYSREF信号一直存在,IP核会在每次SYSREF沿到来时重新捕获LMFC相位;单次模式则是只在链路初始化时给一个脉冲,IP核捕获一次之后就不再关注SYSREF。
这两种模式对应的场景不同,连续模式通常用于需要动态调整时钟相位的系统,比如多板同步或者动态重配场景;单次模式则用于固定配置的系统。选择错误的模式会导致IP核在运行过程中反复捕获SYSREF,产生意外的LMFC边界跳变,表现出来就是数据偶发错位。PG066里明确建议,如果SYSREF不是持续存在的,就必须配置为单次模式,否则IP核会因为找不到SYSREF而报错。这个细节在文档里占的篇幅不大,但实际工程中踩中的人非常多。
2.3 根据文档推导SYSREF约束的完整步骤
用PG066的公式可以算出LMFC周期,然后反推SYSREF相对device clock的相位要求。LMFC周期的计算公式是:LMFC周期 = (F × K × 10) / 线速率,其中F是一个帧内的字节数,K是每多帧的帧数。比如线速率是10Gbps,F=4,K=32,那么LMFC周期 = (4×32×10)/10Gbps = 128ns。这个计算在PG066的“Deterministic Latency”章节有明确说明。
有了LMFC周期之后,再结合PG066里给出的SYSREF setup/hold时间,就能确定SYSREF相对device clock的相位窗口。实际操作中,我会在XDC里用set_input_delay把SYSREF相对device clock的延迟约束在文档规定的窗口内,然后跑时序收敛。这个过程不复杂,但前提是你必须回到PG066把对应表格的参数查准,不同速度等级的器件数据不一样。
3. 细节二:PG198里GT参考时钟和QMCPLL/CPLL选择的坑,比你想的更隐蔽
PG198是JESD204 PHY的文档,里面关于GT参考时钟的描述特别容易被忽略。很多人以为refclk只要频率对就行,实际上refclk的抖动、来源、以及和QPLL/CPLL的配置关系才是决定链路能否稳定工作的关键。
3.1 QPLL和CPLL到底选哪个,PG198里有明确倾向
PG198的GT Clocking章节花了很多篇幅讲QPLL和CPLL的区别。简单说,QPLL(Quad PLL)是每个GT Quad共享的,适合多个lane跑同一个线速率的场景;CPLL是每个lane独立的,适合单个lane不同线速率、或者通道数量少的场景。文档里提到,对于多通道JESD204B,强烈建议使用QPLL,因为它能保证同一个Quad内所有lane的时钟同源,避免lane之间的相位偏斜。
但这里有个隐蔽的坑:QPLL的参考时钟频率必须满足一个特定的频率范围,而且它和线速率之间的倍频关系必须是整数关系。PG198的表格里给了不同线速率下QPLL参考时钟的推荐值,用错的话QPLL会锁不住,或者锁定之后抖动恶化。我自己就遇到过用QPLL跑9.8Gbps,refclk给的是122.88MHz,QPLL死活锁不上,换成156.25MHz一次就锁住了——因为9.8Gbps和122.88MHz之间达不到QPLL的整数分频关系,而156.25MHz可以。
3.2 GT参考时钟的来源选择,文档里反复强调的两条路径
PG198里明确区分了两种GT参考时钟的来源路径:一种是从专用参考时钟引脚进入,另一种是从普通IO经过BUFG进入。文档原话的意思很清楚——强烈建议使用专用参考时钟引脚,因为普通IO路径会引入额外的抖动和不确定性,严重时会导致误码率上升。
实际上,UltraScale+器件的GT参考时钟引脚是固定的,比如GTHE3/GTYE3的REFCLK引脚。如果用普通IO接时钟芯片输出,哪怕频率完全正确,QPLL也可能因为抖动过大而无法锁定。这个坑在原理图设计阶段就要规避,等画完板子再改就麻烦了。PG198里给了一张GT参考时钟源选择的流程图,核心逻辑就是:能走专用引脚绝不用普通IO。
3.3 CPLL配置里参考时钟要等于线速率除以小整数的约束
CPLL的配置相对灵活,但也有一个硬约束:参考时钟频率必须等于线速率除以一个小整数。PG198里给出的约束表格明确列了CPLL参考时钟频率和线速率的关系,比如线速率10Gbps,参考时钟可以是156.25MHz(除以64)或者125MHz(除以80)。这个约束的本质是CPLL内部的VCO频率范围有限,必须保证参考时钟经过倍频后落在VCO的可锁定范围内。
实际项目里,不少人为了省时钟资源,把JESD204B的线速率设为和GT参考时钟一样的频率,比如线速率10Gbps、参考时钟也选10GHz,这显然不可能。正确做法是参考时钟选一个低频、低抖动、好获得的频率源,然后通过QPLL/CPLL倍频上去。这个逻辑看似简单,但我在代码评审里不止一次见过新手把线速率和参考时钟搞成同一个数量级。
4. 细节三:PG066里复位和初始化时序的要求,是CGS失败的隐形元凶
CGS(Code Group Synchronization)失败绝对能排进JESD204B调试“最让人崩溃问题”的前三名。链路明明连上了,时钟也给了,但CGS就是过不去,或者偶尔能过去、偶尔过不去。这种时候十有八九不是线速率问题,而是复位和初始化时序没满足PG066的要求。
4.1 PG066里复位信号的依赖关系,顺序反了就会出鬼
PG066的“Resets and Initialization”章节详细描述了JESD204B IP核的复位层次:axi_resetn、areset、gt_reset三个复位信号之间不是简单的或门关系,而是有严格的先后依赖。文档明确说明,GT复位必须在所有初始化配置完成之后释放,而IP核复位又依赖GT的稳定输出。三者顺序反了,就会出现IP核状态机跑起来但GT还没稳定的情况,CGS自然过不去。
我调试过的一个项目就是典型例子:FPGA上电后立即释放IP核复位,然后才去配置GT参考时钟和LPLL,结果CGS间歇性失败。排查到最后才发现是复位顺序问题,改成先让GT锁定、再释放IP核复位之后,问题彻底消失。这个细节在PG066的复位章节里是重点标注的,但很多人看文档时一扫而过,没有结合自己的初始化流程去核对。
4.2 SYNC信号和CGS状态机的关系,PG066里给了明确要求
PG066里对SYNC信号的处理也有明确说明。JESD204B协议里,接收端通过拉低SYNC表示请求同步,发送端收到SYNC拉低后开始发送K28.5字符,接收端连续收到4个K28.5字符后CGS完成,SYNC拉高。
但PG066特别指出,CGS完成之后SYNC信号不能立刻撤销,必须保持至少一个多帧周期,否则发送端可能还没有稳定接收到同步确认,就会重新回到失步状态。这个细节在实际调试中表现为:SYNC波形上看已经完成同步,但链路数据流里偶尔还有误同步或者重新同步事件。排查方法是用ILA抓SYNC和IP核状态寄存器的变化,确认SYNC拉高时刻是否满足PG066的保持时间要求。
4.3 按PG066推荐的初始化顺序,配置JESD204B接口只需六步
根据PG066的初始化顺序要求,我总结出一套固定流程,照着做基本不会出CGS问题。第一步,保证device clock和GT refclk稳定,这个稳定不是指存在,而是指频率锁定、相位稳定;第二步,确保SYSREF已经按要求配置好,如果是单次模式,确认SYSREF脉冲已经正确发送过一次;第三步,释放GT复位,等待GT的txresetdone/rxresetdone信号拉高;第四步,释放IP核复位,等待IP核状态寄存器显示link ready;第五步,配置ADC/DAC芯片侧的相关寄存器,使其开始发送或接收数据;第六步,观察SYNC信号,确认CGS完成后链路进入数据阶段。
这套流程的核心思想是:时钟和复位是所有操作的前提,任何一步都不能跳过。PG066在初始化章节给了类似的顺序框架,但实际项目里因为要配合外部芯片的配置时序,经常被打乱。我的建议是,把初始化流程写成一个有限状态机,每一步的完成条件都用一个信号表示,不要在时序上留有“同时发生”的模糊地带。这也是PG066文档里反复强调的一点:JESD204B是确定性协议,路径上每个环节都必须有明确的先后关系。
5. 常见问题与排查技巧实录
掌握了上面三个文档细节,基本能避开80%的坑。但剩下的20%往往更加隐蔽,需要结合具体现象去排查。这里整理一份我实际调试中遇到过的问题速查表,配合PG066和PG198一起看会更有针对性。
| 故障现象 | 可能原因 | 排查手段 |
|---|---|---|
| 链路完全无法建立,SYNC一直为低 | GT refclk频率错误或QPLL未锁定 | 检查GT status寄存器,确认QPLL locked信号 |
| CGS间歇性成功,但数据错位 | SYSREF相位不满足建立/保持时间 | 用ILA抓SYSREF和device clock的相位关系,检查XDC约束 |
| 链路建立后偶发重新同步 | 复位顺序不对,或SYSREF模式配置错误 | 确认GT复位和IP复位顺序符合PG066要求 |
| 高低温下误码率明显上升 | 参考时钟抖动指标不够,或REFCLK走线靠近噪声源 | 用频谱仪测参考时钟相噪,检查PCB布局 |
| 多片ADC之间相位不一致 | 各片ADC的SYSREF到达时间不一致 | 检查SYSREF在PCB上的等长设计,必要时做板级相位补偿 |
再补充一个小技巧:调试JESD204B链路时,千万不要上来就抓数据。先把链路状态寄存器列表读一遍,Xilinx在PG066里给出了这些状态位的完整说明,根据状态位能快速定位问题在时钟、复位、还是SYSREF阶段。我一般在硬件调试脚本里加上一个循环读取状态寄存器的功能,上电后自动打印,省去很多来回切换的麻烦。
另外,GT复位相关信号(gt_reset、reset、power_down)的初始化顺序也值得留意。PG198里专门提到,power_down信号必须先释放,然后才是reset释放,反过来会导致GT内部状态机异常。我之前在一个Aurora 8B/10B项目里就吃过这个亏,后来做JESD204B时就学会了先查这类基础信号。
这里还想提醒一下SYSREF走线的问题。SYSREF频率通常不高,几MHz到几十MHz,很多人因此觉得走线不用太讲究。但SYSREF的边沿质量直接影响采样的一致性,如果走线过长、过孔过多,边缘变缓,采样点就会抖动。在实际项目中,SYSREF走线长度最好控制在1英寸以内,离其他高速信号至少3倍线宽的距离,有条件的话加一个AC耦合电容到时钟芯片的SYSREF输出端。PG066里对SYSREF脉冲宽度有明确要求,脉宽太窄会导致IP核采不到,太宽且频率不合适又会影响正常捕获,具体数值还是回到文档对应表格去查。
6. 从文档细节到实际操作的三点心得
文档读一遍和用一遍的区别非常大。PG066和PG198加起来好几千页,没有人能全部背下来,关键是把和自己项目相关的章节反复看透。我把这几个踩坑点再浓缩成三句话,方便大家记:
第一,SYSREF不是随便给个脉冲就完事的,它的相位、脉宽、模式都要和device clock、LMFC边界严格对齐,PG066里每个时序表都值得单独拿出来对着自己的设计检查一遍。第二,GT参考时钟的配置优先级高于一切,QPLL还是CPLL、频率选多少、走哪条路径,这些在原理图阶段就必须定死,后面改不仅费时还可能改不回来。第三,复位顺序出问题,表现往往是微妙且间歇的,不是完全不能工作,而是偶尔抽风,排查起来极费精力,所以一开始就按PG066的初始化序列设计,别偷懒。
最后再分享一个真实体会。我之前调试一块板子,JESD204B链路在常温下一切正常,一进高低温箱就报错。查来查去,最后发现是SYSREF源时钟芯片的供电滤波没做好,导致低温下时钟相噪恶化。换了一个低噪声LDO后问题彻底消除。这个经历给我的教训是:JESD204B系统里,时钟相关的每一个环节都值得较真,包括供电。PG066和PG198虽然不会直接告诉你电源怎么设计,但“时钟质量链”这个思路贯穿始终。做这个接口,文档要细读,板级要细查,两手都得硬。