射频电路PSS仿真:谐波平衡与射击法原理及收敛避坑指南 简介这份PDF资料聚焦集成电路电路仿真中的周期性稳态PSS分析面向具备一定仿真基础、熟悉Spectre工具的研发人员与技术专家。内容系统讲解谐波平衡HB与shooting两种方法在频域、时域中求解周期性稳态响应的原理与差异并覆盖受驱动电路放大器、滤波器、混频器与自治电路振荡器两类场景的配置要点。资源包共1个PDF文件约623KB篇幅紧凑便于随查随用。文档围绕初始瞬态与稳态求解两阶段展开逐一说明仿真区间、时间步长、初始条件、收敛及输出等参数并给出errpreset、cmin、autostab、oscic等关键选项的调优建议帮助读者平衡仿真速度与精度、改善强非线性或快速跳变电路的收敛性。已有461人学习适合需要掌握PSS参数配置、提升仿真效率与收敛成功率的工程师参考。1. 周期性稳态分析射频电路设计里绕不开的那道坎做射频集成电路的人迟早会撞上同一个问题一个混频器或者振荡器输入是周期性的但电路里存在非线性输出信号的周期可能和输入完全不同。你没法用普通的直流工作点分析也没法用瞬态仿真跑到底——因为要跑到稳态可能需要几万个周期时间成本根本扛不住。周期性稳态响应分析就是干这个的它直接在频域里求解电路的稳态周期解不需要等瞬态衰减完一次求解就能拿到稳态波形和频谱。PSSPeriodic Steady-State分析是这类方法里最常用的引擎配合PAC、PNoise、PSP 这些后续分析能覆盖从混频器转换增益到振荡器相位噪声的完整链路。如果你正在做射频前端、锁相环或者开关电容电路的仿真验证这套方法基本是必修课。2. PSS 的底层逻辑为什么不能直接用瞬态仿真替代2.1 周期稳态的数学定义与求解思路周期性稳态的本质是电路在周期激励下经过足够长时间后所有节点电压和支路电流都变成时间的周期函数周期为 T。数学上写成 x(tT) x(t)。瞬态仿真当然也能跑到这个状态但问题是收敛速度——如果电路 Q 值很高或者时间常数很大衰减到稳态可能需要几百上千个周期仿真时间直接爆炸。PSS 的做法是把问题转化到频域。它假设稳态解可以展开成傅里叶级数然后用谐波平衡Harmonic Balance或者射击法Shooting Method来求解。谐波平衡法把时域的非线性方程变换到频域用牛顿迭代求解各次谐波的系数射击法则在时域里迭代但只关注一个周期内的状态变化通过灵敏度矩阵加速收敛。两种方法各有适用场景后面会细说。关键参数是谐波次数Number of Harmonics。你选的谐波次数决定了能捕捉到多少次谐波分量。如果选少了高频谐波被截断波形失真后续的 PAC 和 PNoise 结果全错。选多了计算量指数上升。常见做法是先跑一个瞬态仿真看看波形大概包含几次谐波再据此设定。2.2 谐波平衡 vs 射击法选哪个更稳谐波平衡法适合强非线性电路比如混频器、倍频器因为它在频域里处理非线性项比较自然。但它的矩阵规模随谐波次数增长很快谐波次数一高内存和求解时间都吃不消。射击法适合弱非线性但时间常数大的电路比如振荡器、开关电容滤波器它在时域里迭代矩阵规模只和节点数有关但需要计算状态转移矩阵对刚性电路可能不稳定。实际工程里很多仿真器会自动选择或者让用户指定。我一般会先试谐波平衡如果收敛困难或者谐波次数需要设到 20 以上再换射击法。另外如果电路里有很窄的脉冲波形射击法通常更靠谱因为时域采样能更好地捕捉边沿。2.3 用 Python 搭一个最小 PSS 验证框架光讲理论不够直观下面用 Python 写一个简化的谐波平衡求解器针对一个二极管整流电路做 PSS 分析。这个例子不依赖任何商业仿真器目的是让你看清 PSS 的迭代逻辑。import numpy as np # 电路参数二极管整流输入正弦输出接 RC 负载 Vin_amp 1.0 # 输入幅度 freq 1e6 # 输入频率 1MHz R 1000.0 # 负载电阻 C 1e-9 # 负载电容 Is 1e-12 # 二极管饱和电流 Vt 0.026 # 热电压 # PSS 参数 N_harm 5 # 谐波次数 N_time 64 # 时域采样点数 T 1.0 / freq # 周期 # 时域网格 t np.linspace(0, T, N_time, endpointFalse) omega 2 * np.pi * freq # 初始猜测所有谐波系数为 0直流分量为 0.5V V_dc 0.5 V_harm np.zeros(N_harm, dtypecomplex) def diode_current(v): 二极管指数模型 return Is * (np.exp(v / Vt) - 1) def build_voltage(t, V_dc, V_harm): 根据谐波系数重构时域电压 v np.full_like(t, V_dc) for k in range(1, N_harm 1): v 2 * np.real(V_harm[k-1] * np.exp(1j * k * omega * t)) return v def residual(V_dc, V_harm): 谐波平衡残差电路方程在频域的投影 v build_voltage(t, V_dc, V_harm) i_d diode_current(v) # 电阻电流 i_r v / R # 电容电流C * dv/dt在频域里就是 j*k*omega*C*V_k # 总电流残差在时域 i_total i_d i_r # 对电容电流直接在频域处理 # 将时域总电流变换到频域 I_total_fft np.fft.fft(i_total) / N_time # 电容电流的频域贡献 I_cap np.zeros(N_harm 1, dtypecomplex) for k in range(1, N_harm 1): I_cap[k] 1j * k * omega * C * V_harm[k-1] # 残差总电流 电容电流 0KCL res np.zeros(N_harm 1, dtypecomplex) res[0] I_total_fft[0].real for k in range(1, N_harm 1): res[k] I_total_fft[k] I_cap[k] return res # 牛顿迭代求解 for iteration in range(50): res residual(V_dc, V_harm) err np.linalg.norm(res) if err 1e-10: print(f收敛于第 {iteration} 次迭代误差 {err:.2e}) break # 数值雅可比简化版实际应用用解析雅可比 eps 1e-6 J np.zeros((N_harm 1, N_harm 1), dtypecomplex) for j in range(N_harm 1): if j 0: V_dc_p V_dc eps res_p residual(V_dc_p, V_harm) J[:, j] (res_p - res) / eps else: V_harm_p V_harm.copy() V_harm_p[j-1] eps res_p residual(V_dc, V_harm_p) J[:, j] (res_p - res) / eps # 求解线性系统 delta np.linalg.solve(J, -res) V_dc delta[0].real for k in range(1, N_harm 1): V_harm[k-1] delta[k] # 输出稳态波形 v_steady build_voltage(t, V_dc, V_harm) print(稳态电压直流分量:, V_dc) print(前 5 次谐波幅度:, np.abs(V_harm))这段代码的核心逻辑是用谐波系数表示稳态解构造电路方程的频域残差然后用牛顿迭代把残差压到零。residual函数里时域非线性电流通过 FFT 变换到频域线性电容电流直接在频域计算两者相加就是 KCL 的频域形式。雅可比矩阵用数值差分近似实际商业仿真器会用解析导数加速。参数说明N_harm决定谐波次数这里取 5 是为了演示实际整流电路可能需要 10 次以上才能准确捕捉二极管导通角。N_time是时域采样点数至少要大于 2 倍谐波次数通常取 4 倍以上避免混叠。V_dc和V_harm的初始猜测很关键直流分量猜 0.5V 是因为二极管导通后输出大概在输入峰值附近。跑完这个例子你会看到直流分量收敛到大约 0.7V 左右二次和三次谐波幅度明显。如果增大N_harm到 10波形会更平滑但迭代次数也会增加。这就是 PSS 的典型权衡。3. 在仿真器里跑通 PSS从参数设置到收敛调试3.1 谐波次数和基频怎么定基频Fundamental Frequency是 PSS 分析的核心参数。它必须设成电路里最低的周期性频率分量。比如一个混频器RF 和 LO 两个输入基频应该设成 LO 频率因为 LO 通常是最低的那个。如果设错了PSS 会试图在一个错误的周期里找稳态解结果要么不收敛要么收敛到错误的解。谐波次数Number of Harmonics的设定有个经验公式先跑瞬态仿真看稳态波形里最高次谐波的幅度降到基波幅度的 -40dB 以下那个次数就是下限。实际工程里我一般会在这个基础上再加 2 到 3 次作为余量。比如瞬态波形里 7 次谐波已经很小了PSS 就设 10 次。还有一个参数叫Max Order或者Oversample Factor控制时域采样密度。射击法里这个参数直接影响精度一般设成谐波次数的 4 到 8 倍。谐波平衡法里这个参数影响 FFT 的精度设成 2 的幂次比较高效。3.2 收敛失败的四个常见原因和排查顺序PSS 不收敛是家常便饭尤其是振荡器和强非线性电路。按下面这个顺序排查能省不少时间。第一检查基频是否设对。如果电路里有多个周期信号基频应该是它们的最大公约数对应的频率。比如一个电路同时有 1MHz 和 3MHz 的信号基频应该设 1MHz谐波次数要覆盖到 3MHz 的 3 次谐波。第二检查初始条件。PSS 对初始猜测很敏感。很多仿真器支持从瞬态仿真的最后一个点加载初始条件这个功能一定要用。如果瞬态仿真能跑到接近稳态PSS 的收敛会快很多。第三检查谐波次数是否足够。谐波次数太少残差里被截断的高频分量会干扰迭代。试着把谐波次数翻倍如果收敛了说明之前设少了。第四检查电路里有没有悬空节点或者高阻抗节点。这些节点在频域里容易导致矩阵奇异。加一个大电阻到地或者用仿真器的Nodeset功能给一个初始电压。3.3 用 PSS 结果驱动 PAC 和 PNoise 的配置要点PSS 本身只给出稳态波形和频谱真正有价值的是它作为后续分析的起点。PACPeriodic AC分析在 PSS 的基础上做小信号交流分析能给出混频器的转换增益、隔离度这些指标。PNoisePeriodic Noise分析则计算周期稳态下的噪声性能对振荡器相位噪声和混频器噪声系数至关重要。配置 PAC 时关键参数是输入频率和输出频率的映射关系。因为 PSS 已经把电路线性化到周期工作点PAC 会自动处理频率转换。你只需要指定输入端的交流源频率PAC 会输出所有谐波频率上的响应。注意Sideband参数它决定考虑多少次频率转换边带一般设成和 PSS 谐波次数一样。PNoise 的配置更复杂一些。需要指定噪声源、输出节点、以及Integrate的频率范围。对于振荡器还要用Oscillator模式让 PNoise 自己计算相位噪声。这里有个坑PNoise 的结果对 PSS 的收敛精度非常敏感如果 PSS 残差没压到 1e-10 以下PNoise 的噪声底会明显偏高。4. 避坑指南PSS 仿真里那些让人翻车的细节4.1 坑一基频设成信号频率而不是电路固有频率现象一个振荡器电路PSS 死活不收敛报错说“无法找到周期稳态解”。原因基频被设成了外部注入信号的频率但振荡器的实际振荡频率和注入信号不同。PSS 试图在错误的周期里找稳态自然找不到。解决对于振荡器先用瞬态仿真或者Oscillator分析找到自由振荡频率再把 PSS 的基频设成这个频率。有些仿真器支持Auto模式让 PSS 自己搜索基频但搜索范围要设对否则会搜到谐波上。4.2 坑二谐波次数设太少导致 PAC 增益虚高现象混频器的转换增益仿真结果比预期高 3dB 以上但瞬态仿真验证又对不上。原因PSS 谐波次数设了 3 次但混频器产生的互调分量到了 5 次以上。PAC 分析时高频边带被截断能量被错误地折叠回低频导致增益虚高。解决把 PSS 谐波次数加到至少能覆盖所有重要互调分量。混频器一般设 7 到 15 次具体看 LO 的谐波含量。跑完 PSS 后检查频谱里最高次谐波的幅度如果没降到 -60dB 以下继续加次数。4.3 坑三初始条件从零开始导致迭代发散现象PSS 第一次迭代残差就很大牛顿迭代直接发散仿真器报“Singular matrix”或者“Step too large”。原因所有节点初始电压设成 0但电路实际工作点可能在电源电压附近。牛顿迭代从零开始第一步跨太大直接跑飞。解决用Nodeset给关键节点设初始电压或者先跑一个直流分析把直流解作为 PSS 的初始条件。更稳妥的做法是先跑几个周期的瞬态仿真把最后一个时刻的节点电压存下来作为 PSS 的初始猜测。4.4 坑四PNoise 结果对 PSS 收敛精度太敏感现象PSS 看起来收敛了残差在 1e-6 量级但 PNoise 跑出来的噪声系数比预期高 10dB 以上。原因PNoise 在 PSS 线性化的工作点上计算噪声传递函数。如果 PSS 残差没压到足够小线性化点有偏差噪声传递函数就会出错。尤其是振荡器相位噪声对工作点的微小偏差极其敏感。解决把 PSS 的收敛容差Reltol和Abstol调紧Reltol设到 1e-8 以下Abstol设到 1e-14。如果还是不行增加谐波次数和时域采样点数让 PSS 的解更精确。4.5 坑五射击法在刚性电路里步长失控现象用射击法跑 PSS迭代过程中步长越来越小最后卡死仿真时间无限拉长。原因电路里有很宽的时间常数分布比如同时有纳秒级的开关和微秒级的滤波。射击法在时域里迭代刚性导致状态转移矩阵条件数极差步长控制失效。解决换谐波平衡法。谐波平衡法在频域里处理不受时域刚性影响。如果必须用射击法试试减小Max Step或者增加Oversample Factor但效果有限。最根本的办法还是换方法。5. 进阶技巧用 PSS 扫频和参数扫描做设计空间探索5.1 用 PSS 扫频验证混频器带宽PSS 本身是单频点分析但很多仿真器支持Sweep功能让 PSS 在一个频率范围内自动跑多次。对混频器来说固定 LO 频率扫 RF 频率每次 PSS 收敛后跑 PAC就能得到转换增益随 RF 频率的变化曲线。这个曲线就是混频器的射频带宽。配置时注意每次扫频的 PSS 初始条件可以从上一个频点的解继承这样收敛快很多。仿真器里一般有个Inherit或者Continue选项勾上就行。扫频范围要覆盖 RF 的整个工作频段步长至少每倍频程 10 个点否则带宽边缘的细节会漏掉。5.2 参数扫描找最优偏置点PSS 配合参数扫描Parametric Sweep能快速找到电路的最优偏置。比如一个混频器偏置电流影响转换增益和噪声系数你可以让偏置电流从 1mA 扫到 10mA每个点跑一次 PSSPACPNoise然后画增益和噪声系数随偏置电流的变化。这里有个效率技巧先用较粗的步长扫一遍找到增益峰值和噪声谷值的大致范围再在这个范围里用细步长扫。PSS 的初始条件同样可以继承但偏置电流变化大时继承可能反而导致不收敛这时候就老老实实从直流解开始。5.3 用 PSS 结果做振荡器相位噪声的快速估算振荡器的相位噪声通常用 PNoise 的Oscillator模式算但那个模式跑起来很慢。一个快速估算方法是从 PSS 结果里提取振荡波形的谐波幅度用 Leeson 模型近似计算相位噪声。虽然精度不如 PNoise但能在设计初期快速比较不同拓扑的优劣。具体做法PSS 跑完后导出基波和谐波幅度计算有载 Q 值可以从谐波幅度比推算然后套 Leeson 公式。这个估算的误差在 3 到 5dB 以内对于选型足够用了。等拓扑定下来再用 PNoise 精确验证。5.4 一个我常犯的错误忽略 PSS 的频域截断对噪声折叠的影响早期做混频器噪声分析时我习惯把 PSS 谐波次数设成 5觉得够用了。结果 PNoise 跑出来的噪声系数总是比实测高 2 到 3dB。后来才发现混频器的噪声折叠来自所有谐波边带5 次谐波只覆盖了前 5 个边带高频边带的噪声被截断后错误地折叠回中频。把谐波次数加到 15 次噪声系数立刻对上了。这个教训让我养成了一个习惯每次跑 PNoise 之前先把 PSS 谐波次数翻倍跑一遍对比噪声结果。如果差异超过 0.5dB说明谐波次数不够。这个检查多花几分钟但能避免流片后的惊喜。希望帮到你。本文还有配套的精品资源点击获取