AD9253这款片子,我是做采集板卡的时候第一次深磕的。当时要求是105MSPS采样率,14位精度,输出选LVDS,后级接一颗Artix-7做数据接收和处理。本来以为不就是个ADC送数据、FPGA收数据嘛,结果从DCO时钟分频设置、数据相位对齐,到FCO帧时钟处理,再到FPGA端时序约束,几乎每个环节都踩了坑。尤其是LVDS输出的接法,数据手册上时序图画得很清楚,但实际一上板子就是不对,我相信很多朋友在AD9253或者同类ADC(AD9649、AD9254这些)上都有类似体验。这篇就把我整个调通过程中整理的思路、配置、FPGA端代码写法和避坑点全部抖出来,特别是时钟分频和数据对齐这两块,基本是完整版操作指南,适合正在调AD9253 LVDS接口、或者准备用FPGA收高速ADC数据的工程师参考。
1. AD9253的LVDS接口到底长什么样
1.1 管脚构成:14对数据、DCO、FCO一个都不能少
AD9253的LVDS输出,也就是它工作在LVDS模式时,对外是一组差分对和一条SPI配置总线。很多新手拿到板子先找数据输出,结果打开原理图发现引脚名字是D0P/D0N、D1P/D1N这种,十几对线看着头大。实际上AD9253在LVDS输出模式下,数据口是14对差分数据线(D0~D13),外加一对数据时钟DCO(Data Clock Output)和一对帧时钟FCO(Frame Clock Output)。另外还有一个很重要的特征:它不是固定全并行14线输出的,还支持位串(Bit Serial)模式,这跟你后面SPI里配置的分频比直接相关。
我第一次画板子的时候,就把DCO和FCO当成了普通信号处理,结果采样数据一直错。后来查手册才反应过来,DCO是给FPGA做随路时钟用的,FCO是用于确定每一帧数据边界的,这两个信号在LVDS接收链路里的地位,比数据线本身还关键。只要是AD9253的LVDS应用,连接关系必须保证:FPGA端接收DCO、FCO和14对数据,且DCO和FCO的PCB走线长度要尽量和数据线等长,否则高速下相位差会吃掉你的时序裕量。
另外要注意,AD9253的LVDS模式是包含多种输出速率的,数据手册里有“1x”“2x”“4x”的说法,这里的x指的是DCO频率相对于采样率的倍数。比如你采样率是105MSPS,那么1x模式下DCO就是105MHz,14根线并行输出14bit;2x模式下DCO变成210MHz,但数据线可以减半到7对;4x模式则进一步减少通道数。很多工程为了省FPGA引脚,会在带宽允许时选2x或4x模式,但代价是布线难度和数据重组复杂度会提高。我们的板子最终用的是1x全并行模式,最稳,尤其第一版调试不推荐直接上2x/4x。
1.2 硬件连接和FPGA电平标准选择
AD9253的LVDS输出是标准LVDS电平,约3.5mA电流源,共模电压大约1.2V,差分摆幅在350mV左右。FPGA端对接时最省事的是选择支持LVDS电平标准的bank,并且建议在引脚约束里把差分端接DIFF_TERM打开,也就是内部100Ω差分终端电阻。很多人忽略这个内部端接,结果信号反射严重、眼图很差,其实在Vivado或Quartus里设置一下IO标准为LVDS_25并打开DIFF_TERM,大多数情况不需要再外部贴电阻。
在Xilinx 7系列FPGA上,我推荐把AD9253的LVDS输出接到HP(High Performance)bank,VCCO设置为2.5V,这样LVDS_25电平标准直接可用。Artix-7的bank类型要注意,有些是HR(High Range)bank,虽然也能支持2.5V,但信号质量和IO速率上限相比HP bank会差一些。接AD9253这种105MSPS~125MSPS级别的数据,HP bank更稳妥。
走线方面,LVDS差分对要求100Ω差分阻抗,对内等长控制在±5mil以内,对与对之间最好保持一定间距减少串扰。FCO和DCO这两对线长度尽量与最长的数据线对齐,或者至少让DCO相对数据线不要过早到达FPGA,否则会恶化采样窗。我后来改版把DCO走线做了蛇形等长补偿,眼图和误码率改善很明显。
1.3 SPI先把输出模式定下来
硬件连接正确只是第一步,AD9253上电默认状态不一定是你想要的输出模式,需要通过SPI接口把输出模式寄存器、测试模式、数据格式这些配置好。AD9253的SPI是标准的4线接口(SCLK、SDIO、CSB),时序兼容大多数FPGA实现的SPI主机。
关键配置点有这么几个:一是选择CMOS还是LVDS输出,二是选择DCO分频比(1x、2x、4x),三是选择数据格式(偏移二进制还是二进制补码),四是可选的输出测试码型。这些通常在输出模式寄存器(类似0x14)、输出测试寄存器(类似0x19)里设置。注意,芯片上电后还需要等一小段时间内部初始化完成再写SPI,不然寄存器写不进去。写完之后最好回读校验一次,确保配置真的生效。
我当时遇到的一个坑是:SPI写进去之后DCO始终没有时钟输出,排查了半天发现是电源时序问题,AVDD和DVDD上电顺序不对导致芯片没有正常启动。后来在SPI配置前加了一个延时并重新初始化,问题就消失了。所以拿到板子先别急着调逻辑,先确认SPI能正常写入和回读,这是所有问题定位的基础。
2. 时钟分频:为什么DCO的频率和相位都重要
2.1 分频比1x/2x/4x与通道数的取舍
AD9253的时钟分频设置,直接影响DCO输出频率和有效数据通道数,这也是很多人最容易绕晕的地方。在LVDS模式下,它的内部会把采样时钟经过分频器产生DCO。1x模式对应的就是14对数据线全部使用,每个采样周期14个bit并行输出,DCO频率等于采样率;2x模式是7对数据线,每个DCO周期传输2个bit,DCO频率等于2倍采样率;4x模式进一步压缩到4对线左右。
从FPGA接收的角度看,1x模式最直观:DCO的每个上升沿对应一个完整的14bit数据,甚至不需要DDR接收。但通道数多,FPGA引脚占用多,而且14对数据线等长布线也很麻烦。2x模式则省一半引脚,但DCO频率翻倍,数据在DCO双沿都有效,意味着FPGA端要做DDR采样,复杂度明显上升。4x模式基本只适合高速率(125MSPS)且FPGA引脚极度紧张的情况,不建议新手碰。
我在项目里最终选1x模式还有一个原因:我们的采样率是105MSPS,1x时DCO只有105MHz,在Artix-7上用普通IO+逻辑就能可靠接收,而2x模式DCO到210MHz,虽然也不高,但DDR数据的相位裕量和布线要求一下子严格了很多。如果你的板子已经画好、走线定型,建议优先用1x。如果引脚实在不够,再考虑2x,但一定要在PCB阶段就把等长控制做好。
2.2 DCO与数据的相位关系:边沿对齐还是中心对齐
拿到AD9253,配好输出模式,用示波器看DCO和数据线,你会发现DCO的翻转沿和数据线的跳变沿几乎是对齐的——这就是边沿对齐(edge-aligned)输出。这种时序最坑人,因为如果你在FPGA端直接用DCO边沿去采数据,采到的全是数据跳变过程中的中间态,根本采不稳。
很多第一次调ADC的朋友都会栽在这:DCO明明有,数据线也明显在跳,可FPGA收进来的数据就是乱的,或者只有一部分bit稳定。原因就是DCO和数据边沿是对齐的,你的采样时刻落在了数据不确定区。解决办法有两个方向:一是利用AD9253内部的可编程DCO延时,把DCO输出相位往后推,让它的跳变沿落到数据眼图中心;二是在FPGA端用PLL/MMCM对DCO做相移,或者用IDELAY把数据延时,但这样会增加调试复杂度。
推荐的做法是优先调整AD9253片内DCO延时。数据手册里DCO delay寄存器就是干这个的,它内部有可编程延迟链,能够把DCO的输出相位搬移。具体配置值需要根据采样率和PCB走线长度测量来定,不要一刀切。正常情况调节范围是能覆盖整个UI(Unit Interval,一个数据位的时间宽度)的,调整目标是在FPGA接收端看,DCO的边沿落在数据的正中间。
2.3 DCO延时寄存器:把采样点挪到数据眼图中间
我实际调试AD9253时,第一步是用示波器观察DCO和数据线的相位关系,确认大体对齐之后,用SPI往DCO延时寄存器里写值。这个寄存器通常有几个bit用于控制延迟大小,越大的值代表DCO相对数据延后越多。因为环路延迟还受走线长度影响,所以每块板子可能都不一样,不能照搬参考设计的数值。
调试方法是:FPGA端写一个简单的采集逻辑,把DCO采到的数据实时通过串口或JTAG读出来,然后把DCO延时寄存器从小到大扫一遍,记录每个配置值下采到的数据是否正确。画一条“配置值-数据正确率”的曲线,你会看到一个明显的平台区,那就是最佳工作点。选取平台区中间偏左的配置值,留一点裕量给温度漂移。
我在这块踩过一个具体的坑:一开始按照参考设计写死了一个延时值,常温下数据完全正常,结果设备放到高低温箱里,数据开始偶发错位,后来把DCO延时值加到平台区中央,高低温下就稳了。这说明DCO延时不能只满足常温,要在整个工作温度范围内都落在数据的稳定区间内。这也是我后来坚持要做SPI可配置DCO延时的原因,而不是把寄存器值写死在初始化代码里。
还有一个和DCO相位相关的点:如果你的FPGA内部用了PLL把DCO倍频或者移相,那么PLL的输入频率范围需要满足要求。比如1x模式下DCO是105MHz,直接用BUFG进逻辑采样就够了,不需要PLL;但如果你改用2x甚至4x模式,DCO频率升高,建议把DCO先BUFG再送逻辑,避免全局时钟网络上的抖动影响时序收敛。
3. 数据对齐:FCO、帧边界与码型验证
3.1 FCO帧时钟的真实作用
FCO(Frame Clock Output)官方叫法有很多,数据手册里它被用来指示采样帧的起始位置。在1x全并行模式下,FCO频率和DCO一样,都是采样率,每个DCO周期对应一帧数据,FCO的上升沿表示新一帧数据开始。在2x/4x模式下,FCO频率是DCO频率的1/2或1/4,用来告诉接收端哪一组DCO边沿对应一个采样周期内的第一个bit。
很多工程师容易忽略FCO,觉得只要DCO和数据对齐了,按bit顺序拼数据就行。可实际上,AD9253在2x/4x模式下,同一帧数据的多个bit是分时在几条数据线上传输的,如果你不知道帧边界在哪儿,很可能把相邻两个采样周期的数据拼错,出现“整体错位”的现象。
FCO的正确用法是这样的:在FPGA端先把FCO的上升沿检测出来,用它作为一组数据重组的起点,然后在DCO的边沿按顺序采样所有数据通道。也就是说,FCO给你的是“时序锚点”,而DCO给你的是“数据节奏”。只有双时钟配合,才能把并行的bit还原成一个个完整的采样样本。
3.2 基于FCO的数据重组流程
我第一次把AD9253的LVDS输出接FPGA时,因为用的是1x模式,一开始没管FCO,直接把每个DCO上升沿采到的14bit当作一帧,结果发现数据在特定值附近会偶发抖动。后来查了手册才意识到,1x模式下也要用FCO做确认,尤其当你想做多片同步或者后续扩展2x模式时,FCO一定是数据链路的起点。
数据重组流程可以这样理解:FCO上升沿后的第一个DCO边沿采样得到的是帧内bit[0]~bit[12](或bit[0]~bit[13],取决于你的映射),随后每个DCO边沿依次更新,直到下一个FCO上升沿到来表示新的一帧开始。工程实现时,我习惯在FPGA里用一个状态机:IDLE状态下等待FCO上升沿,一旦到来就进入采数状态,每来一个DCO上升沿就把当前数据线电平锁存到对应bit位,直到FCO再次拉高,一帧数据组装完成,给后级模块一个valid标志。
在2x模式下,一个FCO周期内会有两个DCO边沿(上升沿和下降沿),对应两批bit,需要分别用DDR采样逻辑捕获,再按FCO边界合并成完整14bit。这个合并逻辑的时序余量分析要比1x模式复杂,所以如果是第一版调板子,我真的建议用1x全并行,后面稳定后再优化通道数。
3.3 测试码型:0x555/0xAAA、RAMP和用户自定义码
数据对齐调没调好,不能靠肉眼盯波形,必须借助AD9253内置的测试码型功能。通过SPI写入测试模式寄存器,ADC会把正常转换数据旁路,直接输出固定的数字码型到LVDS端口。常见的几种测试码型包括:全0、全1、交替码(0x555和0xAAA互补)、递增RAMP码、伪随机码等。
其中0x555/0xAAA交替模式在检查bit连接错位时特别好用。0x555二进制是01010101010101,0xAAA是10101010101010,这两个码型在每个bit上都呈现出明确的0/1变化。如果你在FPGA端收到的数据不是预想交替关系,而是差了一个bit或者整体反转,说明要么是某根data线接反了,要么是数据映射顺序搞错了。
RAMP码则适合检查字节/字对齐和帧边界。RAMP码是依次递增的数据,如0x0000、0x0001、0x0002……如果你能看到递增序列,但起始值不对,说明帧起点偏了;如果能递增但中间有跳变,说明某根线接触不良或者时序不稳定。后来我做产线测试时,还自定义了一组测试码,比如让所有bit的值和位置强相关,这样抓出的错误可以直接对应到物理通道号,定位问题特别快。
使用测试码型时要注意:写测试模式寄存器后,ADC的输出是测试码,不是真实采样数据,所以调完对齐后记得恢复为正常模式。我当时就干过这种傻事,测试码型调通了但忘记关,结果上位机看数据全是锯齿波,还以为模拟前端出了问题。
4. FPGA端接收:原语、拼接逻辑与时序约束
4.1 SDR vs DDR接收:FDCE还是IDDR
AD9253的LVDS输出,在1x模式下,DCO频率等于采样率,且数据宽度是14bit,这种场景在FPGA端做SDR接收就够了:用BUFG把DCO接到全局时钟网络,然后用D触发器(FDRE/FDCE)在DCO上升沿锁存14bit数据线即可。
但要注意一个陷阱:即使DCO延时调整好了,DCO到达FPGA的延时和数据线到达FPGA的延时仍然可能存在微小差异,IBUFDS引入的延时也不一样。所以建议不要直接把DCO拿来当全局时钟用,而是先经过BUFG再送入逻辑时钟网络,同时在时序约束里把DCO和数据之间的相对延时约束清楚。
2x模式则必须用DDR接收,需要IDDR或者ISERDESE2。IDDR在7系列里可以直接捕获DCO上升沿和下降沿上的数据,分别输出到两个寄存器,每个DCO周期得到2个bit。如果要配合bitslip做通道对齐,那么ISERDESE2是更好的选择,因为它的BITSLIP接口可以灵活调整数据串行边界。
我建议如果你的工程以后还可能升级为更高采样率或者多片同步,最好一开始就用ISERDESE2+DDR模式接收,而不是用IDDR+手动交错逻辑。ISERDESE2在Xilinx 7系列里是专门为高速源同步接口设计的,内部自带串并转换、bitslip和对齐逻辑,时序控制更加可控。
4.2 2x模式下的14bit拼接逻辑
2x模式接收时,同一个采样周期的14bit数据被拆成两组,分别在DCO上升沿和下降沿输出到7条数据线上。FPGA里需要用ISERDESE2在每个DCO边沿接收7bit,然后按照FCO的帧边界把两组7bit拼装成14bit。
具体做法是:ISERDESE2配置成DDR模式,data_width可以设为2,这样每一个DCO周期得到两个7bit数据,分别记为p_data(上升沿采样)和n_data(下降沿采样)。然后用FCO的上升沿做帧同步:当检测到FCO上升沿时,把当前p_data作为采样样本的低7位(或高7位,视映射而定),把上一周期的n_data作为另一个7位,拼接成一个14bit数据。这个拼接的先后顺序必须和数据手册的时序图一致,否则数据会左右颠倒。
这段逻辑看似简单,但最容易出错的地方在于FCO和DCO的相位关系不总是绝对固定。AD9253数据手册里的时序图会给出FCO跳变相对DCO的位置,一般来说FCO沿和DCO沿之间的距离不是整数个DCO周期,这时拼接逻辑必须以DCO边沿为基准计数,而不是以FCO沿直接对齐数据。
我在调试2x模式时用过一个很实用的方式:先用0x555/0xAAA测试码抓数据,观察拼接后bit顺序是不是对的。如果0x555变成了0x2AA或者0x555但bit反转,那基本可以肯定是p/n数据拼反了或者FCO边界偏了。把测试码跑对,再上真实数据,省下的时间远大于调拼接逻辑花的时间。
4.3 时序约束怎么写才稳
LVDS接口能否稳定,跟时序约束关系极大。AD9253这类ADC的LVDS输出是源同步接口,FPGA接收时需要在约束里定义DCO是数据随路时钟,然后约束数据相对DCO的setup/hold时间。以一个典型1x模式的工程为例,约束文件里至少要包含这几类约束。
DCO时钟定义一般用create_generated_clock,因为DCO来自ADC内部,由采样时钟分频而来,它的源时钟是PCB上送到AD9253的采样时钟。在FPGA顶层约束里,可以先把采样时钟输入端定义为主时钟,再把DCO定义为基于采样时钟的生成时钟,相位关系按0.5个周期或者实际测量值设置。这样后级逻辑关于DCO的所有时序分析都能落到真实的时钟树上。
数据约束用set_input_delay。ADC数据手册会给出DCO到数据的输出延时范围(tPD_DCO、tPD_data),比如DCO输出延时和数据输出延时有差异,这个差异就是FPGA端要吃的裕量。把最坏情况下的max delay和min delay分别约束上,分析工具才能评估DCO采数据是否满足FPGA内部触发器的建立保持时间。
如果你用的是DDR模式,还要注意数据在DCO上升沿和下降沿分别有效,set_input_delay要分别约束两个边沿;ISERDESE2内部的时序分析对input delay最为敏感,建议前仿真时就把这部分跑通,别只做静态时序分析。我见过几个工程综合布线都不报错,但一上板子数据就错,就是因为input delay约束没写对,时序分析结果虚高。
4.4 对齐状态机:FCO丢失怎么办
在实测中,FCO信号本身也可能受干扰或者偶发抖动,尤其电源纹波大时,FCO的上升沿会出现毛刺。如果你只靠FCO上升沿触发重组,一旦毛刺误触发,整帧数据就错位了,而且不容易恢复。
稳健的做法是加入对齐状态机:平时处于LOCK状态,每个FCO上升沿都校准一次重组位置;如果检测到连续几帧数据校验失败(比如测试码型不对或者数据超出有效范围),就进入RE-ALIGN状态,重新等待FCO上升沿并复位拼接计数器。这样即使中间发生毛刺或者丢帧,系统也能在下一次FCO有效的周期内自动恢复。
这个状态机的实现不复杂,但它决定了整个采集链路的鲁棒性。尤其在工业现场环境里,时钟抖动和电源噪声不可避免,没有这个自动恢复机制,系统跑十几个小时以后数据突然错乱,只能在FPGA里做软复位,这是很被动的。
5. 常见问题排查与避坑清单速查
5.1 现象到原因的排查表
我在调AD9253过程中,把能遇到的典型现象基本都碰了一遍。下面这个排查表里列出的对应关系,是我自己实际验证过的,可以作为快速定位的参考。
| 现象 | 可能原因 | 检查方向 |
|---|---|---|
| DCO无输出 | 芯片没启动或SPI配置未生效 | 检查电源时序、SPI回读 |
| FCO无输出 | 输出模式配置错误 | 确认输出模式寄存器已正确写入 |
| 数据全为0或全为1 | 数据线接反或LVDS端接没开 | 检查差分极性、DIFF_TERM配置 |
| 数据有一半bit不变 | 数据线虚焊或走线断裂 | 用万用表/示波器逐根量 |
| 数据乱码但DCO正常 | DCO相位没对准数据眼中心 | 调整DCO延时寄存器 |
| 时序上电正常,高低温漂移后错 | DCO延时裕量不足 | 延时值设置在平台区中央 |
| 固定图样错位 | FCO帧边界没对齐 | 用测试码型校验帧起点 |
| 偶发跳变,重启后恢复 | 电源噪声或FCO毛刺 | 增加去耦、对齐状态机重同步 |
表格里这些现象,大部分都能在半小时内定位。最难的是那种“时好时坏”的问题,这种基本都指向时序裕量不足或者电源噪声,不是单纯逻辑改改就能解决的。
5.2 几条调试顺序上的经验
把整个调板经历复盘下来,我觉得最有价值的不是某个具体寄存器的值,而是一套靠谱的调试顺序。如果按照这个顺序来,能少走很多弯路。
第一步先确认SPI通信。不管LVDS出不出数据,SPI先读回芯片ID,这一步过了才说明芯片活着、电源和时序没问题。第二步配置固定测试码型,不要上来就采真实信号。用测试码型把整个数字链路打通,这时候FCO、DCO、data线有没有接错、相位对不对,全部能暴露出来。第三步才是把测试码型关掉,接真实模拟输入信号,观察采样波形是否正确。
另外,板子上最好不要把AD9253和FPGA之间的LVDS线设计成可拔插的排线。我第一版为了测试方便用了排线连接,结果排线带来的反射和串扰把眼图搞得一塌糊涂,数据怎么调都有跳变。后来改成直接PCB走线,问题立刻消失。高速LVDS信号真的不适合飞线,哪怕是短距离排线也不行。
最后再说一点:AD9253的LVDS输出需要和接收端共地,而且模拟地和数字地的分割要遵循数据手册的散热焊盘和引脚建议。我遇到过两次因为地分割不合理导致LVDS输出抖动的情况,最后都是通过调整接地策略和电源去耦解决的。调试高速ADC,硬件基础不打牢,后面软件时序调得再好都白搭。