1. 从一次PLL失锁说起:为什么AC/STB仿真总在关键时刻掉链子
做模拟IC这行的,估计没人没被Cadence的仿真坑过。尤其是当你辛辛苦苦搭好一个PLL,跑完瞬态发现锁定时间对不上,或者环路滤波器输出一直在那抖,回头去查AC和STB仿真,结果发现相位裕度看着有60度,实际流片回来就是振。这种“仿真通过、实测翻车”的事,我踩过的坑比走过的路还多。
这篇笔记不打算给你讲教科书上的稳定性判据,那些东西随便翻本Razavi或者Allen的书都比我说得全。我想聊的是:在Cadence Virtuoso + Spectre这套环境里,做AC/STB仿真时那些工具本身给你埋的雷,以及PLL调试中死区、鉴相器非线性这些让人头大的问题,到底怎么一步步定位和解决。关键词就几个:Cadence、AC/STB、PLL、Spectre、蒙特卡洛。适合已经能跑通基本仿真、但结果总跟预期对不上的朋友。如果你还在纠结怎么装Cadence,那这篇可能不太适合你,建议先去找吴川斌的博客补补课。
先说说为什么AC和STB仿真在PLL里这么容易出问题。PLL本质上是个离散采样系统,鉴相器(PFD)在每个参考时钟周期才比较一次相位,但你在Cadence里跑AC仿真时,Spectre默认把它当连续时间系统处理。这就好比你用分析水管流量的方法去分析一个每秒开关一次的水阀,模型本身就不对。STB仿真虽然专门为环路稳定性设计,但它依赖你正确断开环路、正确设置probe,稍有不慎得到的结果就是错的。更麻烦的是,很多时候仿真报错不收敛,你根本不知道是电路问题还是设置问题。
我见过太多人,STB仿真跑出来相位裕度70度,高兴得不行,结果流片回来PLL直接自激。后来一查,probe放错位置了,断在了参考时钟路径上而不是反馈路径上。这种错误Cadence不会给你任何警告,它只会老老实实按你给的断点算,算出一个漂亮但毫无意义的结果。所以这篇笔记的第一部分,我想先把AC/STB仿真中那些“看起来对但实际错”的设置讲清楚。
2. AC/STB仿真设置里的那些隐形陷阱
2.1 为什么你的AC仿真结果和STB对不上
先问一个问题:你在PLL里跑AC仿真时,输入源加在哪?很多人习惯性地在参考输入端加一个acm=1的电压源,然后看输出。但PLL的AC响应跟普通放大器完全不是一回事。普通放大器的AC响应是开环增益随频率变化,而PLL的AC响应取决于你断环的位置和方式。如果你在闭环状态下直接加AC源,得到的是闭环响应,那个东西看相位裕度是没有意义的。
STB仿真之所以更靠谱,是因为它用了Middlebrook的双注入法或者单注入法,在环路内部注入小信号,然后计算环路增益T(s)。但这里有个关键:probe必须放在信号单向流动的地方。什么叫单向流动?就是信号从A到B,不会从B倒流回A。在PLL里,参考时钟路径和反馈路径在PFD处汇合,PFD的输出是单向的,所以probe应该放在PFD输出到电荷泵之间,或者电荷泵输出到环路滤波器之间。如果你把probe放在VCO输出到分频器之间,那也能用,但要注意分频器是数字电路,Spectre在处理时可能会引入额外的延迟。
我个人的习惯是:STB probe放在电荷泵输出和环路滤波器输入之间。这个位置信号是电流形式,单向性最好,而且环路滤波器是线性网络,Spectre算起来最准。具体操作是在Virtuoso原理图里,在电荷泵输出和环路滤波器之间插入一个iprobe(来自analogLib库),然后STB仿真设置里选这个iprobe作为probe。注意iprobe的方向,箭头要从电荷泵指向环路滤波器,反了的话相位会差180度,你看到的相位裕度就完全错了。
注意:iprobe插入后,直流工作点会受影响。因为iprobe在DC时相当于短路,所以DC分析没问题。但如果你用的是vprobe,DC时相当于开路,工作点就全乱了。所以STB仿真一律用iprobe,别用vprobe。
2.2 STB仿真参数设置:别让默认值骗了你
STB仿真在Cadence ADE里的设置项不多,但每一个都关键。打开ADE,选Analyses -> stb,你会看到几个参数:Start Frequency、Stop Frequency、Sweep Type、Points Per Decade。默认值通常是1Hz到1GHz,每十倍频程10个点。对于PLL来说,这个默认值完全不够用。
PLL的环路带宽通常在几十kHz到几MHz之间,相位裕度最关心的频段就在环路带宽附近。如果你每十倍频程只取10个点,在100kHz到1MHz之间只有10个点,根本看不出相位曲线的细节。我的习惯是:Start Frequency设10Hz,Stop Frequency设100MHz,Points Per Decade设100。这样在关键频段有足够的采样点,相位裕度的读数才准。代价是仿真时间变长,但STB是频域仿真,多几百个点也就多几秒,完全值得。
还有一个参数叫“Sweep Type”,默认是Logarithmic。这个别动,PLL的环路增益本来就是按对数频率轴看的。如果你改成Linear,在低频段点太密、高频段点太疏,结果没法看。
另外,STB仿真需要正确的DC工作点。如果DC不收敛,STB直接报错。PLL的DC收敛问题通常出在电荷泵和环路滤波器上。电荷泵的上下电流源如果匹配不好,DC时输出电流不为零,环路滤波器就会一直积分,导致VCO控制电压跑到电源轨。这时候Spectre会报“DC convergence failed”。解决办法是在环路滤波器节点加一个很大的电阻(比如1G欧姆)到地,给DC提供一条泄放路径。这个电阻对AC响应的影响可以忽略,因为它的阻抗远大于环路滤波器本身的阻抗。
2.3 AC仿真在PLL里的正确打开方式
虽然STB更准,但AC仿真也不是不能用。关键是你得知道自己在看什么。在PLL里跑AC,通常是为了看闭环传递函数,比如参考时钟到输出的传递函数,或者VCO控制电压上的噪声传递函数。这时候输入源要加在参考输入端,输出看VCO输出或者分频器输出。
但这里有个坑:PLL的AC响应是调制响应,不是简单的线性放大。参考时钟频率变化时,PFD输出的相位差是积分关系,所以整个环路的传递函数里有一个1/s因子。如果你在AC仿真里直接看增益曲线,会发现低频增益是无穷大(因为积分器),这跟普通放大器完全不一样。所以看AC结果时,别去读相位裕度,那个东西在闭环AC里没有意义。要看的是闭环带宽、峰值增益、以及在不同频率下的抑制能力。
我一般用AC仿真来验证环路滤波器的参数是否合理。比如,把环路滤波器单独拿出来跑AC,看它的零极点位置对不对。然后再把整个PLL闭环跑AC,看闭环带宽是不是跟设计值一致。如果闭环带宽比设计值大很多,说明环路增益太高,可能需要调电荷泵电流或者分频比。
实操心得:AC仿真时,把VCO当成一个压控振荡器模型来用,别用实际电路。实际VCO的AC响应很复杂,而且Spectre在AC分析时会把VCO当成一个非线性器件线性化,结果可能不准。用behavioral model或者Verilog-A写的VCO,AC结果更干净,也更容易收敛。
3. PLL死区调试:从波形上看出问题
3.1 死区到底是什么,为什么它让PLL输出抖动变大
PLL里的死区,指的是PFD(鉴频鉴相器)在输入相位差很小时,输出脉冲宽度太窄,导致电荷泵的开关来不及完全打开或关闭,实际注入环路滤波器的电荷量与理论值不符。这个现象在CMOS工艺里特别常见,因为电荷泵的开关管有寄生电容,驱动能力也有限。当PFD输出的UP和DOWN脉冲窄到几百皮秒甚至几十皮秒时,电荷泵的电流可能只流了一部分,甚至根本没流。
死区的直接后果是:PLL在锁定状态下,相位误差会在零附近来回晃,但PFD有时候输出脉冲、有时候不输出,导致环路增益在零点附近变得非线性。表现出来就是VCO控制电压上有低频抖动,频谱上出现参考杂散和相位噪声恶化。更严重的是,如果死区太大,PLL可能根本锁不住,或者锁定时间变得很长。
在Cadence里怎么看死区?最直接的方法是跑瞬态仿真,看PFD的UP和DOWN信号,以及电荷泵输出电流。把时间轴放大到参考时钟周期级别,看UP和DOWN脉冲的宽度。如果脉冲宽度小于电荷泵开关的响应时间(通常看电荷泵输出电流的上升/下降时间),那就是死区了。
我一般会做一个简单的测试:在PLL锁定后,用Cadence的calculator或者WaveScan,测量UP和DOWN脉冲的宽度,然后跟电荷泵的开关时间对比。如果UP脉冲宽度只有200ps,而电荷泵的开关时间是500ps,那死区肯定存在。这时候要么加大PFD的输出脉冲宽度(比如加延迟单元),要么提高电荷泵的开关速度。
3.2 用瞬态仿真定位死区的具体步骤
第一步,搭好PLL的瞬态仿真环境。参考时钟用vpulse,频率设成你实际用的值,比如10MHz。VCO用behavioral model,输出频率设成比如2.4GHz。分频比设成240。环路滤波器用实际电路,电荷泵也用实际电路。
第二步,设置瞬态仿真参数。Stop Time要足够长,让PLL锁定。通常锁定时间是环路带宽倒数的几十倍。如果环路带宽是100kHz,锁定时间大概几十微秒,Stop Time设1ms足够了。但要注意,瞬态仿真的步长要足够小,才能看到PFD的脉冲。Maxstep设成参考时钟周期的1/100,比如10MHz参考时钟周期是100ns,Maxstep设1ns。这样UP和DOWN脉冲的宽度才能看清楚。
第三步,跑完仿真后,在WaveScan里看UP和DOWN信号。把时间轴缩放到锁定后的几个参考周期,比如从900us到901us。你会看到UP和DOWN脉冲交替出现。测量每个脉冲的宽度,特别是当相位误差很小时的脉冲宽度。
第四步,同时看电荷泵的输出电流。如果UP脉冲宽度是200ps,但电荷泵输出电流的上升时间是500ps,那实际注入的电荷量只有理论值的40%左右。这就是死区的证据。
第五步,如果确认有死区,可以尝试在PFD输出加延迟单元。具体做法是在UP和DOWN路径上各加两个反相器,调整反相器的尺寸来改变延迟。延迟增加后,PFD的输出脉冲宽度变大,电荷泵有足够时间完全打开。但延迟也不能太大,否则会引入额外的相位误差,甚至导致PLL不稳定。一般延迟设在电荷泵开关时间的1.5到2倍比较合适。
注意:加延迟单元后,要重新跑STB仿真,确认相位裕度没有恶化。因为延迟单元会引入额外的极点,可能影响环路稳定性。
3.3 死区调试中的常见误区
很多人一看到PLL输出抖动大,就以为是死区,然后拼命加延迟。结果延迟加太多,PLL反而振了。其实抖动大不一定就是死区,也可能是环路滤波器参数不对、电荷泵电流失配、或者VCO本身的相位噪声大。怎么区分?看抖动频谱。死区引起的抖动通常集中在参考频率的整数倍附近,表现为参考杂散。而环路滤波器问题引起的抖动是宽带的,频谱上是一个隆起的包。VCO相位噪声引起的抖动在高频段更明显。
还有一个误区是:以为死区只在锁定后才出现。实际上,在锁定过程中,相位误差大的时候,PFD输出脉冲很宽,没有死区问题。死区只在相位误差接近零时才显现。所以如果你在锁定过程中看波形,可能看不到死区。必须等PLL完全锁定后,再看UP和DOWN脉冲。
另外,有些人用AC仿真去看死区,这是不对的。死区是非线性效应,AC仿真基于线性化模型,根本看不到。必须用瞬态仿真,而且要看时域波形。
4. Spectre收敛问题与蒙特卡洛分析实战
4.1 瞬态仿真不收敛的排查思路
Cadence瞬态仿真不收敛,是仅次于安装问题的第二大坑。报错信息通常是“Trouble with node XXX”或者“Time step too small”。PLL里最容易出问题的节点是VCO控制电压和电荷泵输出节点。原因通常是:节点上有很大的电容和很小的电阻,导致时间常数极大;或者节点上有非线性器件,工作点跳变。
排查思路是这样的:先看报错信息里提到的节点,在原理图里找到它,看它连接了什么。如果是VCO控制电压节点,检查环路滤波器的电阻电容值。如果电阻是1M欧姆,电容是1nF,时间常数是1ms,而你的仿真Stop Time是1us,那Spectre会一直用小步长去追这个慢变节点,导致仿真时间极长甚至不收敛。解决办法是:要么减小电阻电容值(但会改变环路带宽),要么在仿真设置里加初始条件。用ic语句给VCO控制电压设一个初始值,比如设成VDD/2,这样Spectre不用从零开始慢慢爬。
如果是电荷泵输出节点,检查电荷泵的上下电流源是否匹配。如果DC时输出电流不为零,节点电压会一直积分到电源轨,Spectre在电源轨附近找不到收敛点。解决办法是在节点上加一个大的电阻到地,给DC提供泄放路径。或者用Spectre的“gmin stepping”选项,让Spectre在DC分析时先加一个大的并联电导,然后逐步减小到零。
还有一个常见原因是:仿真精度设得太高。ADE里默认的reltol是1e-3,abstol是1e-12。对于PLL这种大动态范围的电路,可以适当放宽。reltol设1e-2,abstol设1e-9,仿真速度会快很多,结果也不会差太多。但要注意,放宽精度后,小信号细节可能丢失,比如PFD的窄脉冲可能被平滑掉。所以如果是在调死区,精度不能放太宽。
实操心得:如果瞬态仿真一直不收敛,可以先用DC分析跑一下,看DC工作点是否正常。如果DC都不收敛,瞬态肯定不收敛。DC收敛了,瞬态还不收敛,再检查瞬态设置里的Maxstep和Stop Time。Maxstep太大,Spectre可能跳过关键跳变;Maxstep太小,仿真时间太长。一般Maxstep设成最小时间常数的1/10比较合适。
4.2 蒙特卡洛分析在PLL里的正确用法
蒙特卡洛分析是用来评估工艺偏差对电路性能影响的。在PLL里,最关心的偏差是:电荷泵上下电流的失配、环路滤波器电阻电容的偏差、VCO增益的偏差。这些偏差会导致环路带宽变化、相位裕度变化、锁定时间变化。
在Cadence里跑蒙特卡洛,首先要确保你的工艺库支持蒙特卡洛模型。通常PDK里会有mc或者stat的模型库。在ADE里选Tools -> Monte Carlo,然后设置采样次数。一般跑200次左右,结果就有统计意义了。采样次数太少,比如只跑10次,结果波动很大,看不出真实分布。
蒙特卡洛分析的类型有两种:工艺偏差(process)和器件匹配(mismatch)。工艺偏差是所有器件一起偏,比如所有电阻都偏大10%。器件匹配是每个器件独立偏,比如两个电阻一个偏大一个偏小。在PLL里,电荷泵的上下电流源失配主要是mismatch,环路滤波器的电阻电容偏差主要是process。所以两种都要跑。
跑完蒙特卡洛后,看结果的直方图。比如看相位裕度的分布,如果均值是60度,标准差是5度,那最差情况可能只有45度,这就危险了。如果标准差是2度,最差情况还有54度,那就比较安全。根据这个结果,你可以决定要不要加大设计余量,比如把标称相位裕度设成70度,这样即使偏了也有60度以上。
注意:蒙特卡洛分析很吃仿真时间。跑200次STB仿真,每次几秒,总共也就十几分钟。但如果跑200次瞬态仿真,每次几分钟,那就是十几个小时。所以蒙特卡洛一般只跑STB和AC,不跑瞬态。锁定时间的偏差可以用行为级模型来评估,速度快很多。
4.3 蒙特卡洛结果解读与设计余量分配
蒙特卡洛跑完后,Cadence会生成一个统计报告,里面有均值、标准差、最小值、最大值。但别只看这些数字,要看分布形状。如果分布是正态的,那均值加减三倍标准差就是99.7%的覆盖范围。如果分布是偏的,比如相位裕度的分布往低处偏,那说明有些工艺角下相位裕度特别差,需要重点关注。
我一般会把蒙特卡洛结果和工艺角仿真结合起来看。工艺角仿真跑TT、SS、FF、SF、FS五个角,蒙特卡洛跑统计分布。如果某个工艺角下相位裕度已经接近临界值,那蒙特卡洛里肯定有更差的情况。这时候就要回去改电路,比如加大电荷泵电流、调整环路滤波器零极点。
设计余量怎么分配?我的经验是:相位裕度标称值至少留10度余量,比如设计目标60度,标称值要做到70度。环路带宽的偏差控制在正负20%以内。锁定时间的偏差可以放宽到正负50%,因为锁定时间对很多应用来说不是特别关键。电荷泵电流失配控制在1%以内,这个对参考杂散影响很大。
5. 那些Cadence使用中的零碎坑
5.1 器件未定义与库设置问题
“cadence仿真器件未定义”这个报错,通常是因为原理图里用了某个器件,但仿真模型库没加载。比如你从别的项目拷贝了一个原理图,里面用了某个工艺库的MOS管,但你的ADE里没加载那个库的模型。解决办法是在ADE的Setup -> Model Libraries里,把对应的.scs或者.lib文件加进去。注意路径要写对,别用相对路径,用绝对路径最稳。
还有一种情况是:器件是behavioral model,比如Verilog-A写的,但你没编译。Verilog-A模型需要先用compiler编译成Spectre能识别的格式。在ADE里选Setup -> Simulator -> Spectre,然后选Verilog-A编译选项,把模型文件加进去编译。
另外,如果你用的是Cadence自带的analogLib库,里面的器件比如vcvs、vccs、res、cap,一般不需要额外加载模型。但如果你用了ahdlLib里的器件,可能需要加载对应的模型文件。
5.2 瞬态仿真中的初始条件设置
PLL瞬态仿真最头疼的是锁定时间太长。如果环路带宽是10kHz,锁定时间可能几百微秒,仿真起来很慢。这时候可以用初始条件来加速。在VCO控制电压节点上加一个ic语句,设成你估计的锁定电压。比如VCO调谐范围是0.5V到1.5V,锁定电压大概在1V,那就设ic=1V。这样Spectre不用从零开始积分,直接从这个电压附近开始,锁定时间大大缩短。
但要注意,ic语句只在瞬态仿真的初始时刻有效。如果设得不准,PLL还是会慢慢调到正确的锁定电压,只是快一点。如果设得太离谱,比如设成0V,而实际锁定电压是1V,那PLL还是要花时间爬上去。所以ic值要尽量准,可以通过先跑一次短时间的瞬态仿真,看控制电压大概稳定在多少,然后再设ic。
还有一个技巧是用“nodeset”而不是“ic”。nodeset是给Spectre一个初始猜测值,但不强制固定。ic是强制固定初始值。对于PLL,用nodeset更安全,因为如果猜测值不对,Spectre可以自己调整。用ic的话,如果初始值太离谱,Spectre可能报错。
5.3 铜皮优先级与版图相关仿真
“cadence铜皮优先级”这个热搜词,其实跟PLL仿真关系不大,但既然提到了,就顺带说一句。在版图里铺铜时,不同网络的铜皮优先级会影响寄生电容。电源和地的铜皮优先级最高,信号线次之。如果信号线的铜皮优先级设得太高,可能会跟电源铜皮重叠,导致寄生电容增大。在PLL里,VCO控制电压节点对寄生电容很敏感,所以这个节点的走线要尽量短,铜皮优先级要设低,避免跟其他网络重叠。
仿真时,可以用Cadence的寄生提取工具(比如Quantus)提取版图寄生,然后反标到原理图里跑后仿。后仿的STB结果跟原理图可能差很多,因为寄生电容会改变环路滤波器的零极点。我一般会在版图完成后跑一次后仿STB,确认相位裕度还有足够余量。如果后仿相位裕度掉到50度以下,就要回去改版图,减小寄生电容。
6. 从仿真到流片:一些个人经验
PLL这个东西,仿真跑通只是第一步,流片回来能工作才是真的。我做过几个PLL项目,总结下来有几个经验:第一,STB仿真的相位裕度至少留10度余量,因为后仿和实测还会有偏差。第二,电荷泵的匹配性比什么都重要,上下电流失配超过2%,参考杂散就会很明显。第三,VCO的相位噪声在仿真里通常比实测好,因为仿真模型没包含衬底噪声和电源噪声,所以设计时要留够余量。第四,死区问题在仿真里可能看不出来,因为仿真模型太理想,实际流片后电荷泵的开关速度可能比仿真慢,死区更严重。所以PFD输出延迟要留够,宁可大一点也别小。
蒙特卡洛分析一定要跑,而且要看最差情况。我见过一个设计,标称相位裕度65度,蒙特卡洛跑出来最差只有40度,流片回来果然有几颗芯片锁不住。后来回去改电荷泵电流,把标称相位裕度提到75度,蒙特卡洛最差也有55度,流片就没问题了。
最后说一句,Cadence的仿真工具很强大,但也很容易给你假象。仿真结果漂亮不代表电路没问题,仿真报错也不代表电路一定不行。关键是要理解每个仿真设置背后的物理意义,知道自己在看什么,才能从波形里读出真正的问题。