
最近在给一套4通道相控阵接收前端做通道校准折腾了一周最磨人的不是射频链路本身而是两片AD9361之间的相位关系。刚接触SDR那会儿我也以为只要把两片AD9361的REF_CLK接到同一个晶振上采样率和中心频率配置成一样的它们自然就同步了。被现实教育过几次之后才明白AD9361的多芯片同步远不是“同频”两个字能概括的SYNC信号、BBPLL相位、RF PLL分频器、TDD切换时刻每一个环节都可能让你采集到的IQ数据相位漂得莫名其妙。这篇文章把整个同步过程从原理到实战捋一遍包括硬件连线、软件流程、实测方法以及我踩过的那些坑。1. 问题本质为什么两片AD9361即使共用一颗晶振相位依然各走各的1.1 AD9361内部时钟链路拆解AD9361虽然是高度集成的射频收发器但它的核心时钟生成链路和分立器件方案在本质上没有区别。每片AD9361内部有两条独立的锁相环PLL链路参考时钟REF_CLK进来之后通常会先经过一个片上时钟缓冲器再送入射频本振PLLRF PLL和基带/数据时钟PLLBB PLL。RF PLL负责产生射频本振信号用来做混频器激励也就是LO信号。BB PLL负责产生ADC/DAC的采样时钟同时也会派生出发送数据时钟、接收数据时钟以及FPGA接口用的逻辑时钟。问题就出在这里两片AD9361即使从同一颗晶振取REF_CLK也仅仅是“标称频率一致”因为每片芯片内部的PLL压控振荡器VCO起始频率、环路滤波器充放电状态、分频器初始位置都是独立随机启动的。PLL的锁定本质上是一个反馈收敛过程它保证的是“输出频率无限接近目标值”但输出信号的绝对相位与启动时刻的VCO自由振荡相位强相关。这就好比两个人用同一块母钟对好了手表但母钟本身不是内置到每块手表里的而是每块手表内部石英振荡器各自起振、各自锁频。最终两兄弟报时都能报出一样的“几时几分”但秒针指向的位置可能完全不同。1.2 “同频”与“同相”的差距以及它会毁掉什么应用如果你的应用只是单通道收信、看频谱、解个FM那么芯片间相位不一致根本无所谓。但一旦涉及下面这些场景问题立刻放大MIMO通信空时编码、空间复用都需要多通道之间的相对相位可预测。波束成形各天线通道的相位关系直接决定了波束指向。每片AD9361的LO相位差一个θ最终波束就想偏一个方向偏。干涉测向 / 到达角估计通道间相位差是估值的基础输入相位漂移等于给测向结果注入巨大偏差。灵巧干扰 / 抗干扰阵列需要精确控制任意阵元信号的相位和幅度。在这些应用里“同频”只是底线的底线。不同芯片之间哪怕只差一个本振周期的零点几几%经过混频后就会在IQ数据里表现为一个恒定的通道间相位差如果每次上电这个相位差还是随机的那你的校准工作就永远不能收敛。2. 多芯片同步要管的三个层面采样时钟、本振相位与数据接口2.1 采样时钟对齐让所有ADC在同一时刻采样第一个要做的是采样时钟对齐。AD9361每个芯片的BB PLL会以REF_CLK为参考产生一个高频时钟然后经分频得到ADC采样时钟。由于两片芯片的BB PLL分频链起点随机即使频率完全一致两片ADC的采样时刻也会差一个固定的、可能高达几百皮秒到纳秒级的时间。这个时间差在射频链路里意味着什么假设中心频率2.4GHz信号周期约0.42ns如果两片ADC采样时刻差0.2ns基带IQ数据的相位差就是2π×0.2/0.42≈171度接近反相了。这显然是不可接受的。AD9361为此设计了SYNC_IN/SYNC_OUT引脚。当所有芯片的BB PLL都锁定后往SYNC_IN引脚上送一个脉冲芯片内部会把BB PLL输出的分频链复位到一个已知状态从而让所有芯片从同一个相位基准开始输出采样时钟。这个过程在多芯片同步术语里常称为“MCS”Multi-Chip Synchronization。2.2 本振相位对齐射频链路的基准必须统一采样时钟对齐解决的是“基带离散时间轴上各通道采样点对齐”但射频本振的相位也必须对齐否则即使ADC采样时刻完全一致各通道混频器的载波相位也会不同。AD9361的RF PLL输出通常要经过射频分频器才能得到LO信号。射频分频器本身也是数字分频链它的初始状态是上电随机的。这就是为什么即使你强制两片芯片输出完全同相的采样时钟LO相位仍可能差一个不确定的分频相位。解决思路和BB PLL一致在RF PLL锁定完成后用同一个SYNC脉冲去复位射频分频链。AD9361内部清楚这一点所以它的同步机制并不是只对齐一个点而是把BB PLL分频链、射频分频链以及TX/RX数据路径全部放在同一个同步事件里统一复位。有一点必须注意RF PLL从VCO锁定到分频链复位稳定需要时间SYNC脉冲不能给得太早。建议在软件里确认PLL锁定指示通常读寄存器再延后几十微秒触发SYNC。具体延后量参考AD9361官方参考手册里Multi-Chip Synchronization一章的时序图。2.3 数据接口对齐从射频到FPGA的最后一公里前两层都搞定了最后还差数据接口。AD9361通过LVDS或CMOS并口把ADC数据和TX数据送到FPGA。多片AD9361的数据线最终会汇聚进FPGA内部的总线如果不同芯片的数据到达FPGA的时间不一致即使前端采样时钟和LO都对齐了FPGA内部恢复出来的多通道数据流依然存在lane间偏斜。实际工程中数据接口对齐通常分两步先依靠FPGA内部的IO Delay和Bitslip逻辑把从各片AD9361进来的并行数据各自调整到正确的字边界。再通过HDL工程里的一套校准状态机利用AD9361输出的测试图形把所有通道的数据用同一个帧头对齐。AD9361支持在MCS后强制输出一段固定的测试数据FPGA可以据此调整内部FIFO读指针把多通道的数据统一对齐到同一个时钟沿上。这一步在FMCOMMS5官方HDL参考设计里已经有现成实现。如果你完全自己写Verilog/状态机最容易漏的就是这一层最后表现出来是相位测试时IQ数据正弦波很干净但不同通道间总是差那么一两个采样点。3. 硬件连线与同步拓扑一块板卡上的4路收发是怎么布出来的3.1 参考时钟扇出全系统抖动最低的一根线参考时钟的质量决定了整个系统的底噪和同步上限。如果参考时钟的抖动太大PLL的锁定相位噪声就会恶化多芯片的相位稳定性也跟着变差。我这次做的4通道接收前端用的是两片AD9361参考时钟选择了10MHz。布线方案如下10MHz参考源选用低抖动TCXO/OCXO先经过一级时钟扇出缓冲器分成两路低抖动时钟再分别送入两片AD9361的REF_CLK引脚。时钟扇出缓冲器优先选择专门的时钟分配芯片而不是用普通逻辑门分路。普通逻辑门的传播延迟、输出上升沿抖动脉冲都会直接叠加到参考时钟上。两路REF_CLK走线在PCB上尽量等长至少保证误差在几十mil以内。10MHz的波长很长走线长度差带来的相位差相对较小但仍会转化为初始相位差的一部分。如果你用的是40MHz参考时钟注意不要直接拿FPGA的通用IO输出给两片AD9361除非你对时钟扇出能力很有把握。实测中FPGA普通IO直驱两片AD9361的REF_CLK在2.4GHz频段会额外引入约几十皮秒的有效抖动对高要求场景并不合适。参考时钟源方案抖动水平经验值适用场景晶振直连单芯片最低单芯片系统晶振经时钟缓冲器扇出到多芯片低多芯片同步推荐FPGA普通IO直驱偏高仅在低速/非敏感应用中使用3.2 SYNC信号广播用FPGA统一触发所有芯片同步信号的拓扑有两种常见选择一种是级联主芯片SYNC_OUT接到从芯片SYNC_IN另一种是广播FPGA的一个GPIO同时接所有芯片的SYNC_IN。我早期在FMCOMMS5参考设计上用的级联方式理由是官方评估板就这么干的后面自己布板就偷懒直接搬。结果发现级联链的传播延迟比较大主芯片的SYNC_OUT经过板级缓冲再进从芯片到达时间比直接要慢如果时序裕量处理不好高低温下容易偶尔失步。这次我改成了广播方式FPGA内部用一个专用的同步状态机在合适的时刻往所有AD9361的SYNC_IN引脚同时打一个满足参考手册时序要求的脉冲。脉冲宽度要用BB_CLK域寄存打拍确保信号相对所有芯片的时钟域都有充足建立保持时间。SYNC信号建议走HSTL/LVCMOS缓冲器扇出且各路之间的skew尽量控制在200ps以内。实际测量中如果两片AD9361的SYNC_IN引脚之间存在明显走线长度差或经过不同路径的缓冲器同步后通道间相位差会偏大且不稳定。3.3 SPI总线与每个芯片的身份识别每片AD9361控制接口都是SPI多片使用同一个SPI总线时用片选CS区分。我的习惯是SCLK/SDI/SDO共用CS0/CS1分别接两片AD9361CS由FPGA逻辑控制。这里有个容易被忽略的小坑SPI总线的工作频率不能太高否则在长线上反射严重而片选信号又受同步状态机控制很容易出现“寄存器写一半断流”的情况。建议SPI时钟控制在20MHz以内必要时在FPGA侧对SPI输入信号做IO下降沿采样。另外上电时序上必须保证两片AD9361的RESET释放时间差不能太大。我一般让FPGA在系统上电后先把两片RESET同时拉低再统一释放释放后至少延时100ms再开始配置寄存器。这样可以尽量让两片芯片的初始状态接近虽然MCS会最终对齐相位但初始状态接近也能降低个别板卡同步失败的机率。4. 软件侧同步流程从IIO设备到MCS动作的完整链路4.1 驱动与设备树里的双AD9361实例linux系统下调试AD9361最简单的方式是用ADI官方的libiio环境。两片AD9361在设备树里表现为两个独立的IIO设备分别占用不同的SPI片选。驱动起来后通过命令行或C API就可以分别读写每个实例的属性。如果你是自己写裸机驱动或FPGA状态机控制核心思路是一致的把每片AD9361当成一个独立对象按固定顺序做“配置频率→等待PLL锁定→统一触发SYNC→校验收敛”。特别提醒一下千万不要在MCS过程中交叉读写两片芯片的SPI容易把同步时序搞乱。建议的做法是先依次把每片AD9361配置到目标频率并确认各自PLL锁定完成然后暂停SPI操作专门发SYNC信号SYNC后再恢复对每片芯片的读操作。4.2 同步执行顺序为什么必须“先频率、后触发”拿我这次2.4GHz载波、30.72MSPS采样率的配置为例多芯片同步的软件执行流程是暂停所有通道的数据采集确保MCS期间不产生无效干扰。对两片AD9361做完整的初始化包括SPI接口、数字接口模式LVDS还是CMOS、滤波器配置。先后配置两片芯片的LO频率和采样率确保两者配置完全相同。读PLL锁定指示寄存器确认两片都已锁定。延时一段时间我通常给500us到1ms依据参考手册和实测效果调整确保内部模拟校准完成。由FPGA控制GPIO发出SYNC脉冲同时送入两片AD9361。等待同步完成通常需要几十毫秒量级然后读相关寄存器确认同步状态。对每片重新执行必要的RX/TX校准因为MCS会复位部分数字链路。第5步容易被忽略。有些工程师直接发完频率就在几十微秒内打SYNC结果发现相位差好的时候很好差的时候乱七八糟概率大概两三天出现一次。这往往就是没等PLL和内部校准链路完全稳定。4.3 重同步策略与TDD模式下的选择多芯片同步不能做成“只在上电跑一次”。射频系统长期运行会产生温升PLL控制电压、滤波器的群延迟、PCB板材的介电常数都会随温度缓慢变化通道间相位也会跟着漂移。如果你做的是连续波或长时测量建议每运行一段时间就做一次MCS重同步。TDD模式下问题更突出。因为每次收发切换AD9361的LO都会被power down再重新上电。不同step切换之间LO重新锁定后的初始相位未必完全重现之前的相位关系这就导致通道间相位差在每一次TDD切换后都可能跳变。比较实用的应对方案如果系统允许在每次TDD切换后做一个快速同步动作。如果不允许频繁同步用AD9361支持的fastlock profile机制把某一次成功锁定后的状态保存下来后续切换直接调用同一个profile。这样每次切换时LO重锁定的过程完全一样相位可重复性会好很多。实测下来fastlock profile对多芯片相位稳定性的提升非常明显但前提是profile保存的是“已经做过同步”的状态而不是随便某次的锁定状态。5. 实测验证怎样证明两片AD9361真的同步了5.1 用CW单音信号测通道间相位差软件跑完MCS后必须用实测验证不能只看状态寄存器就说“同步成功”。我的做法是用射频信号源输出一个连续波CW单音信号经功分器同时送到两片AD9361的RX端口信号源和AD9361的10MHz参考时钟用同一个源这样可以排除因参考源不一致而导致的天然频差。然后FPGA同时采集两个通道的IQ数据各取64K点用FFT或者直接对单点复数信号求相角。计算两个通道初相之差单音频率最好落在通道带内偏中心一些的位置避免直流附近和通带边缘的失真。重复测量20次以上观察相位差是否恒定。稳定的相位差应该是固定值通常小于1度如果每次测试结果乱跳说明同步链路没做好。我还做过一个更极端的实验连续下电再上电多个循环每次都等系统完全重启动再执行MCS记录每次通道间相位差。因为MCS本身应该消除上电随机相位所以这个统计值应该非常集中。如果每次上电机后相位差都在一个很小的范围内重复说明MCS流程可靠。5.2 长时间观测相位稳定性与温度漂移同步瞬间相位对齐了不意味着永远对齐。一个更严格的方法是长时间采集数据比如每小时记录一次相位差连续观测十几小时再和板卡工作温度对照。在我这次实测中MCS刚完成时两通道相位差大约0.1度连续工作4小时后由于功放、电源等发热区域影响两片AD9361的温度不对称通道间相位差慢慢漂到了0.4度左右。这个漂移量值和PCB布局、系统通风密切相关但只要漂移是缓慢的、连续的通常可以通过周期性MCS重同步来修正。如果发现相位差不是缓慢漂移而是每隔几分钟就跳变一次那基本不是热漂移问题而是某些数字分频器或数据接口偶尔失锁。这种情况需要回到信号完整性和时序上排查比如SYNC信号的信噪比、LVDS数据线的差分匹配、FPGA内部FIFO溢出等。5.3 同步失败的快速判断方法平时调试不一定要每次都上信号源。我自己习惯用一个很简单的快速探测方法把两片AD9361的发射通道都设置为输出一个已知单音信号比如2.4GHz连续波再用宽带接收通道自环采集这个信号。如果多芯片同步正常采集到的IQ数据相位差随时间是一条直线如果同步丢失就能看到相位差发生明显台阶式跳变。这个方法能在不出门、不用额外仪器的情况下快速验证同步稳定性也适合做成自动化测试脚本观察几十个小时。另外libiio环境里可以直接查看LO频率锁定状态、RSSI等属性。虽然RSSI不直接反映相位但RSSI突跳往往伴随着同步异常可以作为第一级告警信号。6. 实战中踩过的坑与注意事项6.1 只接REF_CLK不接SYNC的“假同步”我最初给两片AD9361铺好共享REF_CLK后系统确实能工作频谱、解调都正常唯独测通道相位差时发现每次上电结果都不一样。后来定位到原因我并没有真正执行MCS两片芯片的PLL分频链完全是各跑各的所谓“同步”只是表面上的频率一致。很多刚开始做MIMO的人都会掉进这个坑。判断方法很简单把系统断电重新上电几次如果每次测出的通道间相位差都不一样基本可以断定SYNC没起作用。6.2 SYNC脉冲时序不足时的偶发失步另一个很折腾的问题是MCS流程看起来执行了状态也正常但连续大批量测试中偶尔有一片板卡相位差偏大4050度。后来查了时序才发现SYNC脉冲的宽度和建立时间裕量不足。AD9361参考手册对SYNC_IN相对于内部时钟的建立/保持时间有明确定义如果直接用FPGA IO打一个几十ns的脉冲而不经过任何同步处理在温度和电压变化时就可能落入亚稳态区域导致某一颗芯片没有正确响应。解决办法SYNC信号在FPGA内部用BB_CLK域打两拍再输出输出端再加一个专门驱动缓冲器同时把脉冲宽度留足手册要求值的1.5倍以上。改完这版后几十块板卡连续重复测试失步概率降到零。6.3 复位顺序与重启后的重新同步多芯片系统里任何一片AD9361的复位都会破坏全局同步状态。实际工程中有人为了调其他功能单独复位了其中一片AD9361然后其他通道继续工作结果收发数据全部错乱还找不到原因。记住一个原则只要动过任意一片AD9361的电源、复位、重新配置或PLL重锁就必须重新执行一次完整的MCS流程。还要注意执行MCS前不要同时开启所有通道的数据流。建议先关接收数据流做完MCS再打开。否则同步动作可能被总线上的数据干扰状态寄存器虽然显示同步完成但后续数据流里依然存在残留的相位错位。最后再说一点经验多芯片同步是系统工程硬件、软件、时序、热设计、测试方法是一环扣一环的。如果你在设计初期就把参考时钟扇出、SYNC广播、MCS状态机当成和滤波器一样的基本模块来对待后面调试会顺很多如果等到板卡回来才发现多芯片相位对不齐那就只能像我一开始那样拿着示波器万用表在暗无天日的调试台上慢慢折腾了。希望这篇记录能让你少走这段弯路。