
1. 芯片概览与接口设计的第一步先分清三个时钟域我最近在调一块基于AD9122的高速DAC板卡这颗芯片在ADI的TxDAC系列里属于常青树级别16位分辨率最大采样率可以到1.2GSPS量级常用于基站发射通道、仪器仪表任意波形发生、雷达信号模拟这些场景。第一次接触这颗芯片的人往往不是被模拟输出部分难住而是被它的数字接口配置绕晕。AD9122的输入数据是通过LVDS差分对进来的配置寄存器走SPI两者看起来各自独立实际调试时却互相牵扯哪一个没弄对DAC输出都是白噪或者干脆没有波形。先别急着写寄存器我强烈建议先把AD9122的三个时钟域理清楚。第一个是DAC采样时钟也就是最终决定模拟输出采样率的那个时钟通常由外部高质量时钟源或者锁相环提供比如用AD9528这类芯片来产生。第二个是数据输入速率FPGA往DAC发送数据的字速率这个速率等于DAC采样率除以插值倍数。第三个是DCI时钟也就是LVDS接口的DDR时钟由FPGA提供给AD9122用来在双沿锁存数据。很多人一开始会把DAC采样时钟、数据速率、DCI频率混为一谈其实它们之间差着插值倍数、Lane数和DDR双沿这三层关系。举个例子如果DAC采样率是1.2GSPS配置2倍插值那么FPGA侧的数据字速率就是600MSPS。再假设LVDS配置成4 Lane、16bit位宽DCI因为双沿采样频率等于数据位宽乘以字速率再除以两倍的Lane数算出来是1.2GHz。这个频率并不低所以实际项目里通常会靠提高插值倍数、增加Lane数来把DCI压到FPGA能轻松处理的范围内。有一个比较容易忽略的点AD9122内部还有可选的PLL可以把外部低频参考时钟倍频到DAC采样频率。如果用了PLL那数据手册里的锁定时间、环路带宽这些参数都要注意尤其在做信号发生器类项目时PLL的相位噪声会直接影响输出信号的频谱纯度。我的习惯是先把这一串频率画成一张表格贴在调试笔记最前面每改一个配置都回头看一眼这张表能省掉后面大量的排查时间。2. SPI配置实操寄存器地图、写时序与推荐初始化序列SPI是AD9122的配置入口虽然寄存器数量不算少但实际项目里经常用到的就那十几个。芯片的SPI接口支持三线制和四线制三线制只有CSB、SCLK、SDIO三个引脚四线制多了一个SDO用于读回。我的建议是能用三线就不用四线省IO读回功能SDIO在写指令里切换方向也能做。AD9122的SPI写时序有个特点每次传输先发一个8位指令字包含读写标志、字节数和6位寄存器地址后面再跟数据字节。所有数据都是MSB在前SCLK空闲时为低电平数据在上升沿被DAC锁存。用FPGA实现这个时序很简单状态机分IDLE、CMD、DATA三步就行。如果用STM32这类MCU做主控需要特别注意SPI外设的CPOL和CPHA配置实测下来CPOL0、CPHA1最稳妥也就是空闲低电平、第二个边沿采样。初始化序列的顺序比具体寄存器值更重要。我习惯按这个顺序来先软件复位确认芯片ID能读回来再配时钟、插值、LVDS接口最后配输出电流并使能DAC。下面的伪代码是当前项目里验证过的流程具体数值在不同版本芯片上可能有差异但顺序基本通用。// 1. 软件复位并等待稳定 spi_write(0x00, 0x02); // 软件复位 delay_ms(10); spi_write(0x00, 0x00); // 清除复位状态 // 2. 确认SPI通信正常 uint8_t chip_id spi_read(0x02); // 读芯片ID if (chip_id ! 0x82) { // 具体ID以手册为准 // 通信异常检查时序和电平 } // 3. 配置时钟相关寄存器 spi_write(0x10, 0x01); // 使能DCI时钟等 // 如果使用内部PLL这里继续配置分频比和锁定阈值 // 4. 配置插值倍数与数字滤波器 spi_write(0x20, 0x01); // 设置2x插值具体位域查手册 // 5. 配置LVDS输入 spi_write(0x1E, 0x41); // 4-Lane、16bit、LVDS使能 // 6. 配置数据格式与输出电流 spi_write(0x2F, 0x01); // 选择二进制补码输入格式 spi_write(0x25, 0x1F); // 设置满量程输出电流 // 7. 使能DAC输出 spi_write(0x2A, 0x01);为什么第一步就要读芯片ID因为SPI通信不正常时后面写什么都白搭而ID读回是最快的自检方式。调SPI的时候逻辑分析仪比示波器好用得多直接抓CSB、SCLK、SDIO三根线对照手册时序图看指令字和数据字节。我遇到过几次“寄存器写不进去”的问题最后都是因为主机在SCLK下降沿附近改变SDIO导致DAC采样到不稳定电平把数据改成在上升沿稳定之后就好了。还有一个细节AD9122里有些寄存器是带锁存性质的写入之后不一定立即生效需要按手册要求触发一次更新。不同批次的芯片在这一点上可能有细微差别所以每改一个关键寄存器我建议都读回一次确认尤其是LVDS配置和输出电流这两个区域。3. LVDS数据输入设计Lane模式、DDR时序与FPGA约束思路AD9122的LVDS输入是整个接口设计里最容易出问题的地方。它的数据线有D0P/N到D15P/N总共16对还有一个DCI差分时钟对由FPGA输出给DAC。FPGA端的LVDS输出电平要和AD9122输入的电平规范匹配大多数FPGA的HP Bank在1.2V共模下可以兼容但别想当然上板前最好确认一下FPGA选用的IOSTANDARD和DAC输入共模范围。Lane模式和位宽的配置是一组联动参数。AD9122支持1、2、4条Lane位宽支持8bit和16bit。以16bit位宽、4-Lane模式为例数据线D0P/N到D3P/N负责第一个4bit切片D4P/N到D7P/N负责第二个切片依此类推。DCI是双沿采样每个时钟周期上升沿和下降沿各锁存一次所以4条Lane在一个DCI周期内可以锁存8bit一个16bit的字需要两个DCI周期传完。这也是DCI频率等于字速率两倍的原因。DCI与数据之间的相位关系是整个接口设计的核心。AD9122手册里会给相对DCI建立时间和保持时间的要求FPGA输出数据时要保证在DCI边沿到来之前信号已经稳定并且稳定一段时间。实际项目中我们一般先用FPGA的ODDR原语把数据和DCI同步输出然后在硬件上通过DCI delay寄存器微调DCI相位找到最佳的采样窗口。如果相位偏了症状就是DAC输出噪声底抬升、波形杂乱甚至完全无输出但用示波器看单端波形又觉得数据是对的。// Xilinx 7系列中的ODDR输出示例产生DCI和数据 ODDR #( .DDR_CLK_EDGE(SAME_EDGE), .INIT(1b0), .SRTYPE(SYNC) ) dci_oddr ( .Q(dci_p), .D1(1b1), // DCI在上升沿后为高 .D2(1b0), // 下降沿后为低 .C(dci_clk), .CE(1b1), .R(1b0), .S(1b0) ); ODDR #( .DDR_CLK_EDGE(SAME_EDGE), .INIT(1b0), .SRTYPE(SYNC) ) data_oddr_inst ( .Q(data_p[0]), .D1(tx_data[0]), .D2(tx_data[1]), .C(dci_clk), .CE(1b1), .R(1b0), .S(1b0) );FPGA约束里有一项容易漏掉LVDS差分对的等长约束。PCB上对内等长要控制在5mil以内DCI时钟到各数据lane的等长控制在50mil以内。有人会觉得5mil太苛刻但对于600Mbps以上的LVDS信号这个要求其实很合理。等长控制不好数据和DCI之间的相位差会在不同通道之间变化结果就是某些bit误码率特别高而且这种问题用示波表在板子上很难抓因为波形宏观上看起来是好的。另外每条LVDS差分对在接收端都要加100Ω终端电阻靠近DAC的输入引脚放置。这个终端电阻一是匹配传输线阻抗二是给LVDS接收器提供直流工作点。有些FPGA内部可配置差分终端但如果经过连接器或者较长的走线我倾向于在DAC侧外部再放一个电器上更可靠。4. 从FPGA到DAC输出一次完整的调通流程与验证手段把SPI和LVDS分开看都不难难在把它们串起来调通。我的调通流程是固定的每次都有效。第一步上电后先不写任何寄存器直接读芯片ID确认SPI物理链路OK。第二步配置时钟和插值先不使能DAC输出只把FPGA到DAC的LVDS链路打通。第三步FPGA发送斜坡数据DAC配置成输出数据直通模式用示波器看模拟输出是不是一个干净的正向斜坡。第四步换成正弦波查找表用频谱仪看单音频谱质量。FPGA内部的数据生成建议先用斜坡而不是正弦因为斜坡能直观反映数据位有没有错乱。如果LVDS Lane映射或位序错了斜坡会变成乱序跳变示波器上一眼就能看出来。正弦波如果位序错误看起来可能还是正弦但频谱上会有大量杂散反而不容易定位。等斜坡完全正常了再切到正弦做频谱指标验证。AD9122的数据格式也值得多说一句。它支持二进制补码和偏移二进制两种输入格式配置错了最典型的症状是输出波形整体偏置或者看起来像削波。比如你发一个满幅正弦的补码数据但寄存器里设成了偏移二进制DAC的输出会在零点和满幅之间上下跳动而不是对称的正弦。这个问题在寄存器配置阶段就能规避但很多人没注意浪费了不少时间。验证手段方面示波器看时域频谱仪看频域两者缺一不可。时域上看的是波形形状、幅度、是否有毛刺频域上看的是基波、谐波、杂散尤其是SFDR和无杂散动态范围。DAC输出是差分电流接法一般是经过变压器转成单端再进频谱仪或者直接跨接电阻用差分探头测。如果用变压器要注意变压器的带宽是否覆盖目标信号频率很多低频测试用的小变压器在几百兆赫兹就衰减得很厉害。AD9122还内置了一些数字测试模式可以在不依赖FPGA数据的情况下让DAC输出固定的测试码型比如全0、全1、交替码、伪随机码等。调试时先把这些内置模式跑一遍能快速确认DAC本身的数据通路和模拟输出是不是好的再把问题范围缩小到FPGA到DAC的LVDS接口上。这个思路和排查通信链路时先做自环测试是一样的逻辑。5. 高速接口的布线与电源细节高不成低不就的坑都在这SPI和LVDS配置层面都搞定之后如果输出频谱不好看大概率问题在布线和电源上。高速DAC对电源噪声极其敏感尤其是模拟电源。AD9122内部有数字、模拟、时钟等多个电源域PCB设计时最好每个电源域都单独用磁珠或LDO隔离去耦电容按照手册要求放在对应的电源引脚附近。时钟质量对DAC输出频谱的影响往往被低估。DAC采样时钟上的抖动会直接调制到输出信号上表现为近端相噪恶化。所以给AD9122的采样时钟一般不建议直接从普通晶振接过来而是用专门的时钟发生器或PLL芯片产生低抖动时钟。我自己踩过一回用了一颗FPGA内部PLL分出来的时钟当DAC采样时钟结果输出信号的相噪明显很差换成独立时钟源后立刻改善。模拟输出部分的布局同样关键。AD9122的输出是差分电流通常通过变压器或差分放大器转成单端信号。变压器下方的地层要完整次级侧的50Ω走线要短尽量直接进连接器。如果走线太长高频信号的插损和反射都会影响平坦度频谱仪上看到的就是高频段滚降严重。LVDS数据线的走线尽量放在内层靠近完整的地平面避免跨分割。差分对内等长前面说过了还有一个容易忽略的是组间等长也就是DCI时钟与所有数据线之间的长度差。这个偏差会转换成DCI与数据的相位差直接影响建立保持时间裕量。做板时如果发现长度差的余量不够优先保证DCI到每条数据线的一致性其次再照顾数据线之间的相对偏差。电源去耦的位置也很讲究。数字电源引脚附近的去耦电容可以用0402封装尽量靠近引脚模拟电源和时钟电源的去耦要综合考虑电源完整性。有条件的话在原理图阶段就给每个电源域留好测试点调试时用示波器量纹波能快速判断噪声是否来自电源。我见过不少DAC输出杂散异常的案例最后都是电源纹波超标导致的。6. 实际项目中踩过的几个坑与最终的稳定配置参考调试这几个月有几个坑印象特别深。第一个坑是SPI读回不一致。代码看起来写对了逻辑分析仪抓波形也正常但读回来的ID偶尔是错误值。后来发现是SPI的时钟线在PCB上走得太长SCLK信号发生了振铃上升沿附近有毛刺导致DAC偶尔多采一个时钟。解决办法是在SPI时钟线上串了一个22Ω电阻抑制过冲现象立刻消失。所以SPI这种低速接口在高速电路板上也不能掉以轻心。第二个坑是DAC输出固定在一半满幅附近上电后无论FPGA发什么数据都没反应。查了一圈发现是LVDS的DCI时钟没配置使能AD9122没有DCI就锁存不到数据自然没有输出。这类问题说穿了很简单但排查时容易绕远路。现在我每次初始化完成后都会读一遍关键寄存器确认DCI使能位确实置上了不靠肉眼猜。第三个坑是数据错位。用斜坡测试时波形看起来像锯齿但顺序不对一段上升一段跳变。原因是FPGA内部的数据位序和AD9122期望的Lane映射不一致。D0P/N接到FPGA的哪个引脚软件里对应的bit又是哪一位这三者必须一一对应。我后来专门画了一张引脚映射表从FPGA顶层端口到物理引脚再到DAC引脚号一张表对照着填再也没出过这类问题。稳定配置的参考值如下表适合通用的单音正弦输出测试具体项目请以手册为准调整功能寄存器地址示例配置值示例说明芯片ID0x02读回0x82验证SPI通信时钟使能0x100x01使能DCI插值倍数0x200x012x插值LVDS配置0x1E0x414-Lane、16bit数据格式0x2F0x01二进制补码输出电流0x250x1F最大满量程DAC使能0x2A0x01开启输出根据我个人经验调AD9122最忌讳一上来就堆配置代码。先把时钟频率表格画出来再确认SPI物理链路然后LVDS数据格式和时序最后才是模拟输出和频谱指标。每个阶段都留好验证点出了问题能快速定位到某个层面。这套方法论不仅适用于AD9122其他高速DAC或者高速ADC的调试基本也能套用。