先说点实在的
做高速数据采集这一行,前些年大家用的还多是LVDS或者并行CMOS接口的ADC,那时候FPGA选型相对好办,管脚够、Bank够就行。但这两年ADC的采样率一路往5GSPS以上冲,并行接口的管脚数量、同步时序、功耗全都吃不消了,JESD204B接口就成了绕不开的必经之路。
如果你搜到这篇文章,大概率是遇到了相似的场景:手里有一块集成JESD204B接口的高速ADC板卡,想用FPGA把数据收回来做处理,但翻了半天资料,发现协议文档晦涩难懂,IP核配置选项几十个,SYSREF到底怎么给,确定性延迟怎么保证,链路不稳是哪里出了问题——这些问题没人给捋清楚。我写这篇东西,就是想以自己实际调通过的项目为底子,把JESD204B从硬件连线、时钟设计、参数换算、IP配置到数据采集验证的完整链路拆开讲一遍。
文章会比较长,但保证每一节都能对应到实操环节。无论你是刚接触JESD204B的新手,还是已经搭好环境但数据一直不对的老手,按着这套思路走下去,大概率能把问题收敛到很小的范围内。
1. 系统架构与方案选型
1.1 为什么必须用JESD204B而不是并行接口
在确定用JESD204B之前,我先把三代接口方案做个横向对比,方便你判断自己到底该走哪条路。
| 接口类型 | 典型速率 | 优缺点 | 适用场景 |
|---|---|---|---|
| 并行CMOS | 100MHz以下 | 简单但对齐难、管脚多、功耗高 | 低速工业采集 |
| LVDS | 800MHz以内 | 差分抗干扰好,但数据线多,PCB布线压力大 | 采样率1GSPS以下 |
| JESD204B | 单通道最高12.5Gbps | 通道数少、布线简单、支持多片同步 | 高速ADC/DAC、相控阵、软件无线电 |
拿一块双通道、14bit、1GSPS的ADC来说,用LVDS接口至少需要28对数据线加时钟线,FPGA侧要占用两到三个Bank的高速管脚,布线阶段光是做等长就得折腾好几轮。换成JESD204B之后,如果配置成L=2,只需要两对高速收发器差分线就全部搞定,PCB面积和走线压力立减。
我刚开始接触这个接口的时候也犯过嘀咕,觉得协议那么复杂,IP核配置那么多选项,是不是反而得不偿失。但把板子做出来之后才体会到,JESD204B所谓的“复杂”,是把以前在PCB上做的时序对齐工作搬到了芯片内部,风险和成本其实更低。
1.2 方案选型时最容易忽略的三件事
第一件是FPGA的高速收发器速率是否覆盖。你别看ADC标称JESD204B接口,实际线速率可能超过某些老型号FPGA的GTX上限。我见过有人拿了块Artix-7去做12Gbps的链路,结果发现GTX最高只能跑6.6Gbps,最后只能降配或者换芯片,方案推倒重来。选型阶段一定要先算线速率,再去比选收发器能力。
第二件事是参考时钟和SYSREF的产生。JESD204B对时钟质量要求极高,抖动稍微大一点,误码率指数级上升。很多开发板上的可编程振荡器只是为了让你能跑起来,实际工程里还是要上专用时钟芯片,比如LMK04828这种带时钟分配和去抖功能的。
第三件事是ADC和FPGA之间的电源域问题。高速接口对电源纹波极敏感,哪怕几十毫伏的干扰都会反映到误码上。方案阶段就得把模拟电源、数字电源、收发器电源做分区规划,不要等到调不通了才怀疑电源——那时候已经晚了。
2. 硬件设计要点
2.1 链路连接与终端匹配
JESD204B物理层本质上就是高速串行链路,所以硬件设计上遵循高速SerDes的通用规则。每对差分线之间要求100Ω±10%的差分阻抗,走线需要控制好参考平面连续性,尽量避免过孔、换层。如果链路长度超过一定阈值,建议在接收端加上交流耦合电容,一般0.1μF是常用值。
需要注意的一点是,JESD204B是内嵌时钟的,它的时钟信息是编码在数据流里的(8B/10B编码),所以不需要像并行接口那样单独布时钟线。ADC的采样时钟通过FPGA的时钟引脚或者专用时钟芯片产生,SYSREF信号则作为两个器件的同步基准,走线尽量等长,避免因为SYSREF偏斜导致确定性延迟不稳定。
另外,FPGA高速收发器的参考时钟引脚的输入摆幅、端接方式,一定要对照FPGA手册做检查,不是随便一个时钟输出都能直接驱动。我用过好几种开发板,有些板子上参考时钟的走线经过了缓冲器,相位噪声变差之后链路余量明显下降,后来改成直连才稳定下来。
2.2 电源与时钟树的处理
高速ADC的供电通常分为模拟电源(AVDD)、数字电源(DVDD)、驱动电源(DRVDD),每路电源之间要用磁珠或π型滤波隔离。FPGA侧的高速收发器需要独立的电源轨,而且对纹波要求通常在10mV以内,否则会直接影响发送端眼图质量。
时钟树设计是JESD204B最容易翻车的地方——有时候链路配置全都正确,但SYSREF不定时出现毛刺,就会导致链路反复重新同步。我调试过的一个项目里,SYSREF信号走线经过了一个非终结的过孔,反射导致边沿抖动,确定性延迟就一直不稳定,后来在靠近FPGA引脚处加了个对地电容吸收反射才解决。
这里给出一个我实际使用的电源和时钟分配方案表供参考:
| 信号/电源 | 来源 | 说明 |
|---|---|---|
| FPGA收发器参考时钟 | 时钟芯片专用输出 | 100MHz或156.25MHz,差分LVPECL |
| ADC器件时钟 | 同一时钟芯片的同步输出 | 频率按ADC采样率设定 |
| SYSREF | 时钟芯片的同步输出 | 与器件时钟同源,周期性脉冲或单脉冲 |
| FPGA核心电源 | 开关电源+LDO | 纹波控制在30mV以内 |
| ADC模拟电源 | LDO单独供电 | 与数字地严格分区 |
2.3 PCB布局布线经验
这部分我没法给出通用模板,因为每个板卡的层叠和布局不同,但有几个原则值得强调:首先,ADC的高速串行输出和FPGA收发器之间的走线要尽量短,换层越少越好;其次,SYSREF和器件时钟两根线的走线长度尽量一致或者做等长补偿;再次,高速差分线两侧要有足够的地孔引流,避免回流路径被割断。
这里插一句我个人的看法:JESD204B的硬件设计难度其实不太高,但坑很多很分散,每一个小问题单独看都不致命,叠加在一起就是链路死活调不通。所以硬件原理图阶段就要把留测点、留调试接口、留配置方式(SPI/I2C)这些细节都考虑进去,否则做出来一个没法诊断的黑盒子,后面调试周期会非常痛苦。
3. 协议核心概念与参数计算
3.1 JESD204B协议结构速览
JESD204B协议的层次可以简单理解成三层:物理层负责高速收发,链路层完成字对齐、加扰、ILAS对齐等,传输层则决定数据在帧和通道之间的映射关系。FPGA与ADC之间的数据交互,实际上是FPGA里的传输层根据配置参数,把链路层恢复出来的数据流还原成一个个采样点。
对于使用FPGA IP核的人来说,这三层的很多细节已经封装在IP内部了。但如果不理解协议层的概念,一旦IP配置错误或者链路异常,你根本无从下手排查。至少要知道以下几个术语:
- 帧(Frame):一个帧包含F个字节,是数据映射的基本单位。
- 多帧(Multiframe):由K个帧组成,ILAS对齐和SYSREF同步都基于多帧。
- L、M、F、K、N、N'、S、CS:这就是JESD204B的关键参数。L是链路通道数,M是转换器数量,F是每帧的字节数,K是每多帧的帧数,N是采样位宽(如14bit),N'是加填充后的位宽(通常N'=16bit),S是每个转换器在每帧内的采样数,CS是控制位宽。
参数看起来很琐碎,但这套参数完全决定了ADC数据怎么映射到FPGA侧。下一节我用实际例子带你走一遍计算逻辑。
3.2 参数换算实例:L=2、M=2、14bit、1GSPS
假设一个双通道、14bit、1GSPS的ADC,打算配置成L=2,即两条高速通道。每帧传输字节数F和采样配置S相关:取N'=16,CS=0,那么S=N'/(8×F/L×M)……这里我直接用更通用的做法——链路层所有参数必须满足一个等式:
L × F × S = M × (N' + CS)
把这个式子的物理意义简单理解为:总共的链路承载能力要刚好等于所有转换器在单位帧内的总数据量。代入已知值,M=2,N'=16,CS=0,S在绝大多数情况下取1,那就能算出来L×F=32。取L=2,则F=8。
确定F之后,K的取值一般是满足多帧字节总数(L×F×K)是某个常数的倍数(通常是2的幂)。常用的K值有16、32、64等,这个值直接影响SYSREF对齐的粒度和确定性延迟。如果你对延迟不敏感,K=16或者32都可以;如果系统对延迟要求很高,需要K取小一点,但代价是同步窗口变窄。
线速率按下面的方式估算:
线速率 = (M × N' × 采样率 × 10/8) / L
这里10/8是因为8B/10B编码额外增加了25%的开销。代入M=2、N'=16、采样率1GSPS、L=2,算出来是5Gbps。这个结果直接决定了你能不能用某个收发器,也决定了电路板的板材等级和连接器选型。
3.3 确定性延迟的来源
JESD204B最大的亮点就是确定性延迟(Deterministic Latency),也就是从ADC采样点到FPGA接收端的延迟是固定的、可重复的。但这个特性不是自动来的,需要硬件和协议配合:
- 硬件上,SYSREF信号必须与器件时钟保持确定的相位关系,且SYSREF的建立保持时间满足ADC和FPGA的要求。
- 协议上,FPGA的接收端需要在SYSREF之后对齐到一个多帧边界,这样每次上电或者重新同步时,延迟都相同。
我在实际项目里的经验是,如果SYSREF连接没问题,但每次复位后采集到的数据相位不一致,大概率是SYSREF的重复脉冲频率没有设置成多帧频率的整数倍,或者SYSREF脉冲宽度太窄导致没有满足两个器件的建立时间。解决方法是先确认多帧时钟频率,再配置时钟芯片产生相应频率的SYSREF,并在FPGA里加一个状态监测寄存器来确认同步是否完成。
4. FPGA侧配置与调试全流程
4.1 配置前的必要准备工作
拿到一块JESD204B的ADC,第一步不是打开Vivado或者Quartus连上IP核,而是先把器件手册里的寄存器表完整看一遍。特别是以下这些信息:
- ADC工作模式配置寄存器(决定采样率、通道数、N'等)。
- 加扰功能(Scrambling)的开启选项,一般默认建议开启以减少电磁干扰。
- 测试模式(比如D21.5、PRBS、斜坡信号),用于链路调试。
- 寄存器访问接口(通常通过SPI或I2C配置)。
我习惯上先把ADC放在一个简单的静态配置,比如用SPI写入工作模式参数,然后读取寄存器返回确认配置写入成功。这个环节几乎占据了调试前期一半的时间,但却是定位问题的关键——如果SPI读写都不通,后面一切调试都没有意义。
4.2 FPGA内部JESD204B IP的配置步骤
以Xilinx系列为例,在Vivado中添加JESD204B IP核,配置时主要设置以下参数:
- 收发器位置与速率:填写前面算出来的线速率,比如5Gbps,并选择对应的GT参考时钟引脚。
- 协议参数:填写L、M、F、K、N、N'、S、CS这些值,IP会根据它们自动推导出一部分内部配置。
- 确定性延迟相关:选择是否使用SYSREF,启用确定性延迟功能,以及设置SYSREF处理方式(单脉冲还是重复脉冲)。
- 缓冲模式:一般选对齐数据缓冲(Alignment Data Buffer)模式,用于补偿多通道之间的延迟差。
配置完成后,生成IP核并例化到工程里,注意连接好复位、时钟和SYSREF输入。然后写一个小模块,把IP核的状态寄存器(sync信号、错误标志、对齐状态等)接出来,便于观察。
在这里给出一个最简的Verilog例化框架,方便你对整体结构有直观概念:
jesd204b_phy u_jesd204b_phy ( .gt_rxp_in (adc_data_p), .gt_rxn_in (adc_data_n), .gt_refclk_p (refclk_p), .gt_refclk_n (refclk_n), .rx_sysref (sysref_pin), .rx_core_clk (user_clk), .rx_reset (~link_reset_n), .rx_axis_tdata (axis_data), .rx_axis_tvalid(axis_valid), .rx_axis_tready(axis_ready), .rx_sync (sync_out), .rx_status (link_status) );4.3 复位与同步时序的检查顺序
链路能否建立,关键看三个标志:同步信号sync、码组同步(CGS)、ILAS对齐。我在调试时按下面的顺序做检查,每步通过后再进入下一步:
- 检查FPGA复位是否释放,参考时钟是否存在,GT是否有输出稳定时钟。
- 检查sync信号是否拉低——JESD204B里FPGA接收端会发出同步请求,即sync_n拉低,ADC收到后开始发送K字符(代码组同步阶段)。
- 检查sync_n是否经过一段时间后回复高——这表示CGS完成,进入ILAS阶段。
- 检查IP核输出的对齐状态寄存器,确认ILAS被正确接收。
- 配置ADC进入用户数据模式,观察FPGA侧接收到的数据是否符合预期(斜坡数据或者正弦波)。
如果某一步一直没有通过,不要继续往下配置IP参数,先回到硬件层排查。常见的坑是SYSREF没有周期性触发,或者sync信号是推挽输出但接成了开漏,导致电平不对——这些都是我踩过的。
5. 数据采集实现与链路质量验证
5.1 数据通道的映射与重组
当JESD204B链路正常建立后,FPGA侧拿到的AXI-Stream数据实际是按协议帧格式排列的。通道映射关系需要自己计算清楚,否则数据顺序就是乱的。用上面的L=2、M=2、14bit例子来解释:
链路层按照字节粒度在两条通道上轮流传输数据帧,传输层负责把帧里的字节分配到对应的转换器采样值。N'=16意味着每个采样值是2个字节,S=1意味着每帧每转换器只有1个采样。那么F=8意味着一个帧里有8个字节,其中前4个字节对应转换器0的2个采样值(但M=2,所以要算上两个转换器),实际对应关系是:帧内第1~2字节是CH0采样值,第3~4字节是CH1采样值,第5~6字节是CH0采样值,第7~8字节是CH1采样值——这个具体顺序和配置的哪个参数有关,我一般不背公式,而是用ADC输出斜坡测试信号,用数据观察窗口去反推映射规则。
最简单的验证方法是配置ADC输出递增斜坡,然后在FPGA里接一个固定深度的RAM,抓一段数据用串口或者逻辑分析仪导出,看序列是否符合预期。如果波形是正弦波,也可以直接把数据导出到MATLAB或者Python里画出来。这个验证思路我每次都会用,比死记手册里的映射表靠谱得多。
5.2 链路误码率与眼图检查
链路质量直接决定长时间采集的稳定性。链路不稳定时,有时候数据前几分钟都是好的,跑久了就开始出现毛刺或者偶发的跳码。针对这种间歇性问题,我通常从三个方面排查:
第一,看GT的误码计数寄存器。Xilinx的GT有硬件误码计数器(比如PRBS错误计数),可以配置为PRBS模式后由ADC发送PRBS数据,FPGA接收端做比对。只要这个计数长期不为0,就说明物理层有问题,单纯调低速率换取稳定是治标不治本。
第二,看SYSREF与多帧边沿的余量。在FPGA内部可以用IBERT或者自定义的窗口扫描逻辑,改变SYSREF的采样时钟相位,观察同步结果是否在多个相位点保持一致。有效的余量窗口如果小于0.1个字节,说明实际硬件设计有隐患。
第三,检查电源噪底。用示波器在FPGA收发器电源管脚量测纹波,如果在高速链路运行状态下纹波超过规格书要求的范围(通常10mV以内),就需要加磁珠或者改电源布局。我用过不止一块板子,最后定位到是电源纹波导致的偶发误码。
5.3 数据采集的应用层设计
链路稳定之后,接下来的工作就是数据采集缓存和处理了。这里给出一个典型的数据采集架构:
- FPGA接收JESD204B IP输出的AXI-Stream,先通过一个异步FIFO把数据从GT用户时钟域转换到系统处理时钟域。
- 接着做抽取或者滤波,取决于后续算法需求,比如数字下变频(DDC)。
- 然后把数据写入DDR3/DDR4,或者通过以太网/PCIe上传到上位机。
- 同时可以保留一段RAM用于触发采集,便于调试时抓取固定长度的波形。
在具体的工程实现里,FIFO的深度要大于两个时钟域之间的最大延迟差,否则会出现丢数据。异步FIFO的读写指针跨时钟域问题,最好直接使用Xilinx FIFO IP核,内置了格雷码同步,不要自己去写跨时钟域逻辑,除非你对亚稳态处理很有把握。这一点我在早期吃过亏,自己写的跨时钟域代码在时序仿真没问题,上板后偶发数据错位,后来全部换成官方IP核才消停。
另外建议在处理链路的每个关键节点都加上数据计数器和状态寄存器,比如“收到JESD204B数据的总字节数”“写入DDR的字节数”“触发次数”等。这些寄存器在上位机调试界面里实时显示,一旦数据流中断就能立刻定位到丢数据发生在哪个环节。这个习惯帮我节约了大量排查时间。
6. 常见问题与排查技巧实录
6.1 链路建不起来,sync一直拉低
这是出现频率最高的问题。sync一直拉低说明CPU从未完成CGS阶段,也就是ADC没有收到有效的K字符序列。排查顺序建议如下:
- 检查FPGA复位是否释放,参考时钟是否有效。用眼图观测GT参考时钟引脚的波形,或者用Vivado/Vitis里的调试工具读取GT的时钟状态寄存器。
- 检查ADC的SPI配置是否生效。特别注意N'、L、F等参数是否和FPGA侧一致。FPGA侧配置错误,接收端读到的是乱码,自然无法完成码组同步。
- 检查SYSREF信号是否到达FPGA引脚。有时候SYSREF走线过孔问题或者驱动能力不足,信号到了FPGA内部已经变形。此时可以在FPGA内部连接一个简单的边沿检测模块,看是否出现符合预期的脉冲。
- 检查ADC是否进入正常工作状态,有些ADC需要额外配置一个“链路使能”位,才能开始发送K字符。
这里我遇到过最离谱的一次是,ADC手册上的寄存器地址和实际芯片Rev版本不一致,导致写入的配置根本没生效。后来靠逻辑分析仪抓SPI时序才发现地址差了一位。所以配置前一定要核对手册的勘误页和芯片丝印版本。
6.2 数据能采到,但通道顺序错乱
当链路建立后,发现CH0的数据出现在CH1的位置上,不再是链路问题,而是数据映射处理的问题。比如两片ADC通过同一链路级联,那LMFC(Local Multi-Frame Clock)的对齐关系会决定每个转换器的数据落在哪个多帧。检查步骤:
- 先让ADC输出斜坡信号,观察数据序列。
- 根据FPGA侧采到的字节序列,反推当前的映射关系。
- 修改IP中的传输层映射配置或者自己在FPGA里做通道重排。
- 如果有多片ADC级联,确认每片ADC的子类(Subclass 0/1)是否一致,SYSREF的连接是否符合级联手册要求。
小技巧:在ADC测试模式下,有些芯片支持输出固定的伪随机序列,把它和FPGA端接收到的序列比对,可以精确定位到字节级别的偏移。这个办法比人工看波形高效得多。
6.3 长时间运行后偶发数据中断
偶发中断是最烦人的问题。原因通常涉及三个方面:
| 可能原因 | 判别方法 | 处理措施 |
|---|---|---|
| 电源纹波过大 | 示波器量测收发器电源电压 | 增加滤波电容或改用LDO |
| SYSREF受干扰 | 长时间捕捉SYSREF波形毛刺 | 优化走线、加端接、远离开关电源 |
| GT收发器温度漂移 | 观察误码计数随时间变化 | 评估散热方案,必要时降速或降压 |
还有一次偶发中断,最后查到是ADC芯片内部PLL在高温下失锁,导致一段时间内输出的数据和系统时钟不同步。这种问题在FPGA侧很难看出端倪,需要借助ADC的状态寄存器来辅助判断。所以不管什么品牌的ADC,手册里关于芯片状态监测的寄存器一定要仔细读一遍,调试时用得上。
如果条件允许,我建议在工程里加入链路健康监测任务,定时(比如每1秒)轮询FPGA的JESD204B IP核状态寄存器和ADC的状态寄存器,一旦发现异常就记录时间戳并触发重新同步,这样既能及时发现问题,也能在事后分析时留下有效线索。
6.4 调试工具与手段
工欲善其事,必先利其器。JESD204B调试必备的工具包括:
- 示波器(至少500MHz带宽,1GHz以上最好),用于观测SYSREF、参考时钟、电源纹波。
- 逻辑分析仪,用于抓取SPI配置时序。
- IBERT(Xilinx内置的高速链路测试工具),可以直接在Vivado里调用,进行眼图扫描和误码测试,不需要写额外代码。
- 串口或者JTAG调试,用于读取FPGA内部状态寄存器和数据RAM。
另外,不要忽视仿真。JESD204B IP核自带行为级仿真模型,可以先在仿真环境里验证配置参数的正确性,把SPI写入的寄存器和FPGA的响应都跑通了再上板,节省的调试时间远比多花的那一两天多。
7. 工程落地的一些补充建议
7.1 代码结构规划
承接JESD204B的FPGA工程,建议把代码按功能模块划分,至少包括:IP例化模块、时钟管理模块、寄存器配置模块、数据缓存模块、状态监测模块、上位机通信模块。每个模块之间用标准接口(AXI-Stream、AXI-Lite)连接,便于后续维护和复用。
我第一次做JESD204B的时候,偷懒把所有逻辑都堆在顶层文件里,结果调试时改一处就引入新问题,后来花了半天时间做模块拆分才好转。现在我的习惯是,任何一个外部接口都有独立的封装模块,内部逻辑通过信号连到顶层,关键信号都加上调试标记(mark_debug),方便实机调试时用Vivado的逻辑分析仪抓取。
7.2 从开发板到自研板卡的平滑迁移
如果你是从官方开发板起步,换到自己设计的板卡时,有很大概率遇到参数一模一样但链路不通的情况。这是因为开发板上的时钟和SYSREF路径经过了精心设计和验证,而自研板卡的时钟树和电源域策略不一定完全等效。迁移时建议这样做:
- 先按开发板原封不动的配置参数,确认自研板卡能在低速率下建立链路。
- 再把线速率逐步提升,每次只改一个变量。
- 最后检查接收端的眼图质量和误码余量,确认系统余量充足再投入正式应用。
这个过程不能急。我见过有人为了赶进度,直接在自研板卡上使用官方demo的全部配置,结果上电后链路从未建立成功,最后只能从头排查,反而浪费了更多时间。
7.3 与上位机的数据交互模式
JESD204B系统最终一定涉及大数据量传输。常见方案有PCIe、万兆以太网、USB 3.0等。选择哪种方案取决于数据速率和用户上位机软件架构。这里我只有一点经验之谈:无论走哪种接口,上位机软件和FPGA固件一定要提前约定好数据帧格式、时间戳机制和错误重传机制,否则联调阶段会成为整个项目最痛苦的环节。
可以在FPGA内部为每一帧数据打上单调递增的序号,上位机检测到序号不连续时主动请求重传或者标记数据异常。这套机制看似简单,但对排查链路偶发问题和后续算法调试都有巨大帮助。我们团队现在所有的采集板卡都默认集成这个功能,调试效率提升了很多。
8. 最后说几句实在话
JESD204B这个接口给人的第一印象总是复杂难懂,参数多、时序难、协议分层多,仿佛只有资深专家才能玩得转。但把整个链路走通之后回头看,它其实就是一套规定得非常仔细的心跳和握手流程,每一步都有明确的检查点,关键是你要对协议本身有足够的耐心和敬畏。
我个人的体会是,JESD204B系统的成功率七成取决于硬件设计阶段对时钟和电源的重视程度,剩下两成靠协议参数的理解,最后一成才是调试手段和经验。如果你在硬件设计时就留下充分的调试接口和测试点,后面的软件调试其实是很顺畅的。
如果你正在被JESD204B困扰,不妨把我的调试顺序抄下来,一步一步做排除;如果试完了还卡住,把你的配置参数、现象和已经排除的内容整理出来,大概率很快能找到突破口。
做硬件就是这样,功夫都在你看不见的地方。