简介:这份面向射频与通信电路设计者的ADS应用笔记PDF,聚焦功率放大器设计中ACPR、EVM与PAE三项关键指标的仿真评估,适合已具备一定ADS基础、需要做PA性能验证与参数取舍的工程师及高年级学生参考。压缩包仅含1个PDF文件,约1.8MB,篇幅集中,便于随查随用。已有2775人学习,说明其在PA仿真主题下具有较高关注度。文档以EDGE调制信号为例,说明如何通过Ptolemy协同仿真搭建符合规范的信号源与测量接收链路,完成邻道与次邻道功率比、误差矢量幅度、平均发射载波功率以及增益压缩等结果的获取;同时介绍自动验证建模如何用谐波平衡特征数据加速时域仿真,并通过监测偏置电压电流计算平均直流功耗与PAE。对希望把ACPR、EVM与效率联合分析,并进一步用功率扫描、参数扫描或蒙特卡洛观察统计波动的读者,这份文档提供了较完整的指标解释、仿真组织思路与结果解读框架。
1. 需求先立住:一台功放要同时过 ACPR、EVM 和 PAE 三道关
功放设计走到验收前,最容易被问住的一句话是:这组 ACPR、EVM、PAE 是在什么条件下算出来的,换个批次还成立吗。单点仿真能给出一个好看的数字,却回答不了这个问题。ADS 仿真 ACPR、EVM 计算这类活儿,难点从来不是把某个测量控件拖进原理图,而是让三项指标在同一条链路里算出来、能互相印证,还能看出统计波动。这套方案要做的就是把符合标准的调制源、待测功放子电路、规范兼容的测量 sink 串成一条协同仿真链,一次功率扫描同时拿到相邻与隔道信道功率比、误差矢量幅度、平均发射载波功率和功率附加效率,再叠加参数扫描与蒙特卡洛,看清指标的分布和真正敏感的设计变量。它适合正在做射频功放课程设计、毕业设计,或者要交付一份可复现仿真方案的人:不必在每个时间点跑完整电路级仿真,靠协同仿真加自动验证建模把速度拉回来。
2. 总体架构设计:顶层 testbench、功放子电路与控制器三层怎么分工
这套仿真最容易翻车的地方,是把所有东西堆在一张原理图里:源、功放、测量、偏置全混在一起,跑一次要几十分钟,改一个参数还得从头再来。合理的切法是三层,每层只背一个职责,层与层之间用变量和全局节点做接口约定。切分清楚之后,Fast Cosim 才有东西可表征,参数扫描和蒙特卡洛才有地方挂。
2.1 三层结构怎么切
顶层 testbench 只干三件事:提供调制激励、扫描输入功率、挂测量 sink。功放子电路只做被表征对象,里面不放源、不放扫描变量,只保留电路本身和必要的偏置。控制器挂在子电路里,负责约束时间步,让协同仿真的采样节奏和顶层源对齐。三层各司其职,改动互不牵连。
| 层级 | 主要元件 | 职责 | 改动风险 |
|---|---|---|---|
| 顶层 testbench | EDGE 源、功放子电路实例、三个测量 sink、Pin 扫描变量 | 激励、扫描、测量、数据落盘 | 改扫描范围会影响 Fast Cosim 建模范围 |
| 功放子电路 | 功放电路本体、偏置网络、CCVS、Envelope 控制器 | 被表征对象、直流功耗取样、时间步约束 | 改拓扑必须重建模型 |
| 数据展示层 | 曲线、直方图、散点相关图 | 插值、统计、敏感变量识别 | 目标功率超出范围会取端点值 |
这张表看着简单,实际项目里出问题基本都出在「跨层改动」:有人在顶层改扫描范围,忘了子电路的 Fast Cosim 建模上限还停在旧值;有人在子电路里加了一级匹配,却还用上一次的表征数据。后面避坑那章会逐条展开。
2.2 顶层信号链与测量 sink 的挂载位置
顶层的信号链是一条直线:EDGE 信号源进功放子电路,输出分三路进测量 sink。输入功率由变量 Pin 控制,扫描范围从 -20 dBm 到 +16 dBm,覆盖从线性区到明显压缩区的整段。三个 sink 的分工要记牢,答辩时被问到「这个数字从哪个控件来」要能立刻答上。
- EVM 测量 sink:算误差矢量幅度,反映调制精度。
- 四信道 ACP 测量 sink:算相邻信道和隔道信道功率比。它是在标准 EDGE 发射杂散测量控件基础上改出来的,把信道数固定成四路,专门对应本例的频谱模板。
- 本地载波功率测量 sink:算平均发射射频载波功率。这里特意做成标准控件的本地副本,目的是方便把测量的时隙数降下来。时隙数一减,仿真时间掉得很明显,这是实测出来的提速手段,不是玄学。
提示:本地副本改动的是时隙数量,不是测量算法本身。改完要拿一次全时隙结果做对照,确认均值偏差在可接受范围内,再拿它跑大批量扫描。
2.3 子电路控制器的 Step 与全局节点约定
功放子电路内部必须放一个 Envelope 或 Transient 控制器,这是协同仿真的硬性前提。这个控制器有两个参数要特别对待:Step 必须手动设,而且要和顶层 EDGE 源的时间步完全一致;Stop 在协同仿真里是被忽略的,仿真什么时候停由顶层的测量 sink 决定。很多人在这里翻车,以为设了 Stop 就能控制时长,结果跑了半小时还没结束。
我的做法是把源里定义时间步的那组方程原样复制到子电路的控制器上,让两边共用一个表达式,而不是各写一个数字。数字对数字迟早会对不上,方程对数字不会。
全局节点是另一条接口约定。协同仿真状态下,子电路内部的支路电流和节点电压不能直接引到顶层,必须先把它们变成全局节点。具体做法是在子电路里用一个电流控制电压源把偏置电流转成节点电压,再在顶层把偏置电压节点和转换后的电流节点都声明为全局节点。这两根线是后面算 PAE 的唯一通道,命名要一次定死,中途改名会连带一堆测量控件失效。
3. 测量链落地:ACPR、EVM、载波功率与 PAE 的取样路径
前三项指标的测量路径比较直:源出来进功放,输出进各自的 sink,扫描 Pin 就得到一组随输出功率变化的曲线。真正需要设计的是 PAE,因为它要的是平均直流功耗,而协同仿真恰恰不让你直接读电流。
3.1 输入功率扫描与三个 sink 的协同
扫描变量只有一个 Pin,从 -20 到 +16 dBm。每一轮扫描,三个 sink 同时出数:ACPR 给出相邻和隔道两组比值,EVM 给出一个百分比,载波功率 sink 给出平均发射功率。再配合输出功率和增益,一张图上就能同时看到增益压缩、ACPR 恶化、EVM 抬升这三件事发生的先后顺序。
这个顺序很有用。通常增益先压缩,ACPR 随后变差,EVM 最后崩掉,三者的拐点位置决定了功放的工作点该往回退多少。如果只测其中一项,你没法判断余量该留多少;三项画在一张图上,折中点是自己浮出来的,不用拍脑袋。
3.2 PAE 的直流功耗怎么取出来
PAE 的定义是输出射频功率减去输入射频功率,再除以平均直流功耗。射频那一半好办,直流那一半要绕一圈。协同仿真里读不到支路电流,所以路径设计成四步:子电路内用电流控制电压源把偏置电流转成节点电压;顶层把偏置电压和这个转换电压都设为全局节点;用输出选择控件把这两个节点只取基带分量,也就是把 OutFreq 设成低通;最后用电压电流相乘控件把两路乘起来并取平均,得到平均直流功耗。
这里有个细节容易被忽略:相乘控件算的是平均,不是瞬时。取样点选错,算出来的是某一时刻的瞬时功率,PAE 会偏得离谱。落盘用的数值 sink 还要把起止采样点设成同一个值,指向最后一个采样号,这样生成的数据集只有一行,不会把整个时间波形的数据都存下来,磁盘和内存都省。
3.3 数据落盘与三项指标的统一计算
从仿真里导出的原始列一般只有输入功率、输出功率、平均直流功耗这几项,PAE、增益、压缩量都要在后处理里算。下面这段脚本做统一换算,单位换算是这类项目里最容易写错的地方,dBm 转瓦特要先减 30 再除 10。
import csv def load_sweep(path): """读取 ADS 导出的扫描结果,列名:Pin_dBm, Pout_dBm, Pdc_W""" rows = [] with open(path, newline="") as f: for r in csv.DictReader(f): rows.append({k: float(v) for k, v in r.items()}) return rows def calc(rows): pout_max = max(r["Pout_dBm"] for r in rows) # 用于计算增益压缩量 out = [] for r in rows: pin_w = 10 ** ((r["Pin_dBm"] - 30) / 10) # dBm -> W pout_w = 10 ** ((r["Pout_dBm"] - 30) / 10) gain_db = r["Pout_dBm"] - r["Pin_dBm"] # 增益,dB pae = (pout_w - pin_w) / r["Pdc_W"] # Pdc 必须取平均值 out.append({**r, "Gain_dB": gain_db, "PAE": pae, "Pout_drop_dB": pout_max - r["Pout_dBm"]}) return out第 8 行的单位换算是固定写法,30 是 dBm 与 dBW 之间的换算常数,除以 10 是因为功率比取对数时系数是 10 而不是 20。第 11 行的 PAE 分子是净射频功率,分母是平均直流功耗,两者都必须是平均值,混入瞬时值会让效率出现大于 1 的荒谬结果。第 12 行的压缩量以本次扫描的最大输出功率为基准,用来定位 1 dB 压缩点,比手动画切线稳。
注意:如果 PAE 算出来是负数或者明显超过 1,先别怀疑公式,去查相乘控件有没有设成取平均、输出选择控件的 OutFreq 是不是低通。这两个地方错一个,结果就没法看。
4. 提速与统计:Fast Cosim 建模、参数扫描与蒙特卡洛怎么串起来
协同仿真的代价是每个时间点都要调用一次电路仿真,扫一次功率就要跑很久。自动验证建模(也叫快速协同仿真)解决的就是这个问题:仿真开始时先跑若干次谐波平衡,把功放子电路在工作范围内的响应建成一张表,真正跑协同仿真时直接查表预测,不再逐点调用电路仿真。这张表建得准不准,决定了整份数据的可信度。
4.1 Build model 与 Use previous data 的选择
控制器的快速协同仿真标签页里有两个表征选项。选建立模型,每次仿真开始都会重建一遍表征数据;选使用上次数据,就直接读上一次建好的表。
判断标准很简单:子电路里任何参数变了,就必须重建。只扫顶层输入功率、功放本身一点没动,可以放心用上次数据。反过来,扫子电路里的传输线长度、扫偏置电压、跑蒙特卡洛让器件参数按分布抽样,这些都会改变子电路的实际响应,还用旧表就是拿旧模型去预测新电路,结果整体失真,而且不报错,这种黑匣子式错误最难查。我一般会养成习惯:只要这轮仿真的变量列表里出现了子电路内部的量,表征选项一律选建立模型,宁可多花几分钟。
4.2 最大输入功率与它的外推检查
表征参数里最关键的是最大输入功率。这个值要设得足够高,高到顶层扫描到最大值时,功放的工作点仍落在表征表内部,而不是靠表外推。调制信号的峰均比越高,这个值相对顶层最大输入功率就要留越多余量,因为峰值功率远高于平均功率,表征表如果只覆盖到平均值附近,峰值那部分就是外推出来的。
| 调制信号峰均比 | 最大输入功率相对顶层最大 Pin 的余量 | 说明 |
|---|---|---|
| 较低(约 3 dB) | 3~5 dB | 包络起伏小,余量可以窄一些 |
| 中等(约 6 dB) | 6~8 dB | 多数常见调制方式的量级 |
| 较高(8 dB 以上) | 10 dB 以上 | 峰值突出,余量不足必然外推 |
这张表是经验值,不是标准答案,但方向不会错。验证方法很直接:把顶层的功率扫描关掉,把输入功率固定在扫描上限跑一次。如果表征上限不够,仿真会给出外推警告。我一般会把固定值再往上抬 1 dB 试一次,如果这个点开始报警,说明当前上限刚好卡在边界,实际交付时应该再往上留一档,因为蒙特卡洛会让参数漂移,边界点很容易被推出去。
4.3 参数扫描:把设计变量变成一条曲线族
扫子电路里的一个传输线长度,得到的是 ACPR、EVM、增益、PAE 各自随长度变化的一族曲线。这族曲线怎么读,比怎么跑更重要。
典型现象是:长度增加,ACPR 和 EVM 一起改善,增益也略有提升,但 PAE 反而变差。这不是矛盾,是匹配网络把线性度换走了效率。看到这种此消彼长,就不要指望找到一个全都最优的点,而是先确定哪项指标卡得最死,再在满足它的区间里挑效率最高的那个长度。如果三项都想要,说明这个设计变量不够用,得回到电路拓扑层面加可调量。
扫参数时还有个操作细节:扫描变量设在子电路内部,表征必须选建立模型,且每个扫描点都会重建一次表,仿真时间大致与扫描点数成正比。点数别一上来就铺很密,先用五到七个点看趋势,确认单调性之后再加密到目标区间。
4.4 蒙特卡洛:统计变量、直方图与相关性散点
统计 variation 这块,子电路里预先定义几组统计变量:一组标称值加高斯分布(相对标准差 10% 量级),偏置电压也按类似的高斯分布抽,再加一个传输线宽度。跑蒙特卡洛之后,输出的是每个响应指标的直方图,以及统计变量与响应之间的散点相关图。
散点相关图是这套流程里信息密度最高的东西。相关系数为大负值,说明该变量增大时指标变差,比如相邻信道功率比与较高电源电压之间就有明显的负相关,这符合预期:电源电压抬高,功放更容易压缩,频谱再生更严重。另一组有意思的结果是 PAE 与较低偏置电压正相关,也就是偏置压低效率更好;同时这个偏置电压与相邻信道功率比的相关性很弱。两条合起来看,结论就很清楚:这个偏置是一个可以单独往下压、用来换效率而几乎不牺牲线性度的旋钮。
后处理时把插值和统计放在一起做,能省掉大量手工对照:
import numpy as np def interpolate_swept_data(x, y, desired_x, step=0.1): """对应 ADS 的插值函数:只插值不外推,超出范围返回端点 Y 值""" x, y = np.asarray(x, float), np.asarray(y, float) order = np.argsort(x); x, y = x[order], y[order] if desired_x <= x[0]: return float(y[0]) # 低于下限,取最小 X 处 if desired_x >= x[-1]: return float(y[-1]) # 高于上限,取最大 X 处 grid = np.arange(x[0], x[-1] + step / 2, step) yi = np.interp(grid, x, y) return float(yi[int(np.argmin(np.abs(grid - desired_x)))]) def summarize(runs, keys, bins=20): """runs 为每次蒙特卡洛一行的字典列表,输出均值、分位数与直方图""" stats = {} for k in keys: v = np.array([r[k] for r in runs], float) hist, edges = np.histogram(v, bins=bins) stats[k] = {"mean": v.mean(), "std": v.std(ddof=1), "p5": np.percentile(v, 5), "p95": np.percentile(v, 95), "hist": hist, "edges": edges} return stats第一段函数的关键在第一行注释:它不做外推。目标输出功率如果超出扫描范围,返回的是端点对应的值,而不是延长的趋势线。这个行为在 ADS 里是内建的,后处理自己实现时也必须照做,否则会出现一条看起来合理、实际是凭空延长出来的曲线。第二段里的 5% 和 95% 分位数比最大最小值更值得写进报告,极值受样本数影响太大,分位数稳定得多。
5. 避坑与排查:五个最容易让仿真结果失真的点
5.1 时间步两边不一致
现象是 ACPR 整体比预期差,EVM 也偏高,但电路本身没改过。原因多半是子电路控制器的 Step 和顶层源的时间步用了两个手写数字,改了一边忘了另一边。解决办法是让两边共用一个方程表达式,改一处全生效,改完再跑一次单点对照确认。
5.2 设了 Stop 却发现仿真不受控
现象是子电路控制器里明明设了停止时间,仿真还是跑很久,或者提前结束。原因是协同仿真下停止时间由顶层测量 sink 决定,子电路的 Stop 参数被忽略。解决办法是别再指望它,把仿真时长交给顶层测量 sink 的时隙设置,子电路只保证 Step 正确。
5.3 高功率点出现外推警告
现象是扫描到最大输入功率附近,日志里冒出外推提示,曲线尾部开始不自然地变平或发散。原因是表征的最大输入功率设低了,峰值功率跑到表外。解决办法是按峰均比留足余量,并且用固定输入功率的方式实测一次边界,确认报警点出现在扫描上限之上。
5.4 扫了子电路参数却沿用旧表征
现象是参数扫描跑完了,各条曲线几乎重合,看起来像是这个参数没影响。原因是在扫子电路内部变量时表征选项还停在“使用上次数据”,所有扫描点都拿同一张旧表预测。解决办法是只要扫描变量落在子电路内部,一律改成建立模型;跑完先看曲线族有没有分开,重合就说明这一步错了。
5.5 目标输出功率超出数据范围
现象是设了一个目标输出功率,插值出来的均值与设定值差了一大截,直方图也怪。原因是目标值超出了扫描得到的输出功率上下限,插值函数只能取端点值,不会外推。解决办法是把扫描范围放宽到覆盖目标值两侧,或者在报告里明确写出目标值落在数据范围内,避免答辩时被追问。
6. 验收与答辩:怎么证明这组曲线不是跑出来好看
数据跑完只是开始,能不能站住脚要看四项自检。第一项是单点复算:关掉扫描,把输入功率固定在某个中间值,单独跑一次协同仿真,和扫描结果里对应那一点对比,偏差应该在小范围内。这一步查的是扫描过程有没有引入插值误差。第二项是边界检查:按上一章的方法确认最大输入功率足够,扫描上限处不出现外推。第三项是能量自洽:PAE 必须落在 0 到 1 之间,平均直流功耗要大于净射频输出功率,任何一条不满足都说明取样路径有问题。第四项是统计收敛:蒙特卡洛次数翻倍后,均值和分位数的变化应该明显收窄,如果还在大幅跳动,说明样本不够。
| 验收项 | 判定标准 | 不通过先查哪里 |
|---|---|---|
| 单点复算 | 与扫描对应点偏差小且方向一致 | 时间步是否一致 |
| 边界检查 | 扫描上限处无外推警告 | 表征最大输入功率 |
| 能量自洽 | 0 < PAE < 1,Pdc > 净射频功率 | 相乘控件是否取平均、输出选择是否低通 |
| 统计收敛 | 样本翻倍后均值与分位数稳定 | 蒙特卡洛次数与变量分布设置 |
答辩时的讲述顺序也有讲究。先讲链路:源是什么标准、功放子电路怎么被表征、三个 sink 各测什么。再讲每个数字的来源:ACPR 来自四信道测量控件,EVM 来自误差矢量测量控件,PAE 的分子分母分别从哪来。最后讲敏感变量:哪几个统计变量与哪项指标强相关,哪些几乎不相关。评委最容易追问的其实是第三段,因为前两段照着原理图能背下来,第三段才体现你有没有真的读过数据。
我从这个项目里留下的习惯是:任何一组要写进报告的曲线,交付前都强制走一遍单点复算和边界检查,哪怕时间再紧也不跳。这两步加起来不到十分钟,但能挡掉后面几天的返工。希望帮到你。
本文还有配套的精品资源,点击获取