☰
CST导出SPICE模型全攻略:txt转cir网表实战与常见坑
2026/10/7 9:20:11 网站建设 项目流程

搞CST仿真的朋友,大概率都遇到过这个尴尬:场仿真算得再漂亮,到了系统级联仿,手里的模型却带不过去。CST把结构、边界、网格全算完了,但下游的LTspice、ADS、HSPICE只认SPICE模型,不认CST工程文件。这时候最高效的办法,就是把CST里提取的等效电路数据导出来,转成标准的.cir网表。这活儿看着不起眼,但做不好,一个端口顺序反了、一个单位差了三个数量级,整个联仿就得从头跑。

这篇东西我用人话给你讲清楚:CST软件里怎么导出SPICE模型相关的txt数据、txt和cir到底差在哪、以及我实测下来最快的转换流程。适合刚接触CST联合仿真的天线/RF工程师,也适合被模型转换折腾过的SI/PI工程师用来查漏补缺。整个思路不依赖特定CST版本,重点放在“拿到txt之后怎么变成能跑的cir”,这套流程我在几个项目里反复用过,照着做基本不会卡壳。

1. 这个需求从哪来:CST与SPICE模型的“最后一公里”

1.1 为什么非要导出SPICE模型

CST本身是三维场仿真工具,算的是Maxwell方程层面的事情,剖分网格、求解本征模、跑瞬态,输出的是S参数、场分布、电流密度这些结果。可一旦落到系统设计里,事情就变了,你要做的不再是“看这个天线方向图行不行”,而是“这节传输线放到整个射频链路里,和功放、滤波器、ADC摆在一起跑扫频,系统的增益和驻波还压不压得住”。

这种系统级仿真,主流工具还是SPICE类的电路仿真器。LTspice免费好用,ADS是射频圈标配,HSPICE在芯片封装仿真里地位很高,但它们都不认识CST的工程文件。所以你必须把CST里的东西“翻译”成电路仿真器能读的语言,也就是SPICE网表。SPICE模型的导出与转换,本质上是把场仿真结果压缩成一个由R、L、C、K(耦合系数)组成的等效电路,这个等效电路在关心的频带内能复现原结构的端口特性,然后交给电路仿真器去跑,这就是我常说的“最后一公里”。

不做这一步,你的CST模型就永远只能孤立在电磁仿真软件里,进不了完整的系统设计链路。尤其是做连接器、封装、PCB过孔、天线匹配这些方向的人,几乎天天和这件事打交道。

1.2 txt和cir到底差在哪

很多人一看到“txt转cir”就以为只是个改后缀的操作,实际完全不是一回事。txt在这里是CST导出的文本数据,绝大多数情况下它有两种常见形态:

一种是S参数文本。CST后处理时把S参数矩阵按ASCII格式导出来,数据可能是“频率 + Re(S11) + Im(S11)”这种逐行排布,也可能是Touchstone的.s2p文件本质也是纯文本。这种数据描述的是端口响应,不包含任何电路拓扑。

另一种是等效电路元件列表。部分CST模块或宏在提取SPICE模型后,会把结果写成一个文本文件,里面是已经整理好的电容、电感、电阻和耦合系数,比如“C_1 n1 0 2.4e-12”这种行。这种离cir就更近一步,但还需要做语法整理、节点编号映射、子电路封装。

cir文件则是SPICE仿真器直接读取的网表格式,它有明确语法:第一行通常是注释或标题,电路主体由元件行组成,每个元件行以元件字母开头,节点号必须是纯数字或合法字符串,还要有.subckt和.ends包成子电路,最后一行是.end。换句话说,cir是“给仿真器看的标准格式”,txt是“给眼睛看的临时格式”。转换的核心工作就是解析txt里的数据,按SPICE语法重新组织。

1.3 三种导出路径怎么选

我自己用过三条路,各有适用场景,列个表看得清楚:

路径适用场景优点缺点
CST自带的SPICE模型导出功能模型中等复杂度,端口数不多一次生成完整网表,省事菜单位置随版本变化大,老版本不稳定
导出S参数/Touchstone后用拟合工具转SPICE射频结构、宽带模型精度高,可控制拟合阶数需要额外拟合步骤,工具链多一环
导出txt元件列表后脚本转cir自定义程度高、模型是从宏里提取的RLC灵活,可批量处理需要自己写解析脚本

标题里说“txt到cir实战”,我默认你手里已经有CST导出的文本数据,不管是S参数还是RLC元件列表,后面的内容都会覆盖到。如果你的版本支持直接导出SPICE模型,那更要看第3章,因为直接导出的结果往往也要手动修才能用。

2. CST端导出前的准备工作与关键设置

2.1 端口设置:先把“引脚”定义清楚

SPICE模型在电路仿真器里使用的时候,就是一个黑盒子,外部只能看到端口引脚。CST里端口定义得好不好,直接决定导出的模型能不能用。我的经验是,导出前一定要把端口顺序、参考阻抗、端口类型都确认清楚。

端口类型上,高频结构建议用波端口(Waveguide Port),它能在很宽频带内保持稳定的参考面,导出后的端口阻抗一般是常数,方便后续匹配网络设计。低频电路或者结构比较紧凑的场景,用集总端口(Lumped Port)更合适,它天然就是SPICE里的那种二端子接口,导出来的模型更直接。

参考阻抗我没少踩坑。CST默认按Z0=50欧姆算反射系数,如果你的系统是75欧姆或者差分100欧姆,一定要在导出前把端口参考阻抗改掉,否则S参数没问题,但转成电路模型后端口上的电压电流关系全是错的。

导出的端口数量也有讲究。很多人为了看一个四端口结构把端口加到十几个,结果导出的SPICE模型巨大,仿真慢且容易不收敛。我建议提前想清楚:哪些端口最后真的要在电路仿真器里接东西,只保留这些端口做导出,内部不需要对外暴露的边界,在CST里合并或改成吸收边界,模型体积能小很多。

2.2 频率范围与采样点数怎么定

SPICE模型本质是对CST频响的拟合结果,所以导出前设定的频率范围就是整个模型有效的工作范围,这个范围直接决定模型精度。

两个实用建议:仿真频率范围至少覆盖你实际工作频段的3到5倍。比如做2.4GHz的WiFi天线匹配,别只扫2.4到2.5GHz,至少扫到5GHz或者更高。原因是SPICE等效电路在高频端收敛得越好,低频端的匹配也越接近原始S参数,万一后续要在系统里看谐波或者带外抑制,模型依然能用。

采样点数不要太少,也不要暴力堆满。CST的离散采样会直接影响拟合出的极点数量,点数太少,尖锐的谐振峰根本拟合不出来;点数太多,拟合算法可能过拟合,导出的模型同样失真。我一般控制在频带内每100MHz至少一个点,窄带谐振结构会加密,宽带结构则均匀采样,大致算下来几百个点足够。

2.3 导出操作:从哪里把数据拿出来

不同CST版本的菜单位置差异比较大,但大逻辑是通的。需要先明确你用的是三维微波工作室(MWS)还是Design Studio(DS)。

在MWS里做完仿真,得到S参数曲线后,通用做法是选中S参数结果,右键找到“Export”类的选项,把数据导出成Touchstone文件或者ASCII文本。Touchstone文件的扩展名是.s2p、.s4p,但本质是纯文本,你用记事本打开后另存为txt完全没问题。

如果你用的是Design Studio,这层的逻辑更像电路仿真器了。你可以在DS里插入3D模型封装好的Touchstone模块,把结构当作一个子电路放进原理图,然后在组件上找“Export SPICE Model”或者“Export Netlist”之类的功能。这类导出结果很多版本生成的就是文本网表,扩展名可能是.txt,内容已经带有RLC元件和端口网络描述,通常还需要手工整理成.cir。

需要注意,CST有些版本的导出功能隐藏在“Macros”或者自动化脚本里,如果你一时找不到,去宏列表里翻一翻“SPICE”相关的项目,大概率能找到线索。我个人的习惯是优先导出S参数触摸文件,因为它的格式最稳定,后面无论用拟合工具还是自己写脚本,可操作性都更强。

3. txt到cir转换实战:拿到文本后怎么变成网表

3.1 先看懂CST导出的txt文件结构

拿到txt别急着写脚本,第一步永远是打开文件看结构。不同导出方式产生的txt格式差别很大,但基本都能分成三类信息:文件头、数据行、注释行。

S参数形式的txt长这个样子:

# CST ASCII Export - S Parameter # Data: 201 points # Freq(GHz) Re(S11) Im(S11) Re(S21) Im(S21) Re(S12) Im(S12) Re(S22) Im(S22) 0.100000 0.821340 -0.342101 0.012340 0.000890 0.012310 0.000870 0.798120 -0.412300 0.120000 0.815200 -0.337500 0.014100 0.001020 0.014020 0.001010 0.790340 -0.407800 ...

RLC元件列表形式的txt则更直接:

C_1 n1 0 2.4e-12 L_2 n1 n2 1.8e-09 R_3 n2 0 50.0 K_2_3 n2 n3 0.72

这里每个字段的含义分别是:元件类型、元件名,然后是两个或三个节点名,最后是数值。如果是耦合电感,K后面还要带两个耦合电感的名称和耦合系数。

看文件头的时候有三个信息必须找到:单位(频率是Hz还是GHz,电容是F还是pF)、数据列的顺序、端口编号的顺序。这三个信息决定了转换脚本怎么写,漏掉任何一个后面都会出问题。

3.2 cir网表的基本语法补课

要正确转换,得先明白目标格式长什么样。一个最小的cir文件可以是:

* SPICE netlist converted from CST export .subckt my_model 1 2 3 C1 p1 0 1.2p L1 p1 p2 2.3n R1 p2 0 50 .ends my_model .end

注意几个关键点:第一行用*开头表示注释,这句不是必须的,但我强烈建议写上,至少标清楚模型来源和日期,否则三个月后你自己都看不懂这个文件是干什么的。.subckt开始定义子电路,后面跟子电路名字和外部端口节点号,这个端口顺序必须和你CST里定义的端口顺序完全一致。元件行以字母开头,R是电阻,L是电感,C是电容,K是耦合系数描述,后面的数字或字母是节点名,SPICE的节点名不能有空格,纯数字节点通常最省事。最后一定是.ends和.end。

数值部分SPICE支持工程后缀,比如1.2p表示1.2皮法,2.3n表示2.3纳亨,50表示50欧姆。如果你的txt里是用科学计数法表示的标准单位,转换时不一定非得换算成带后缀的形式,SPICE完全能读2.4e-12这种表达,但可读性会差点。我通常习惯在脚本里把科学计数法数值按量级自动加上后缀,这样生成的cir放到文本编辑器里方便人工核对。

3.3 Python脚本批量转换

搞清楚了输入输出格式,脚本就是水到渠成的事。下面这段是我常用的转换逻辑,假设输入txt每行是“元件类型 节点1 节点2 数值”的结构,适合转换CST导出的RLC列表。

import re def suffix_convert(value): """把浮点数转成SPICE友好的工程后缀表达""" v = float(value) if abs(v) >= 1e-9 and abs(v) < 1e-6: return f"{v * 1e9:.4f}n" elif abs(v) >= 1e-12 and abs(v) < 1e-9: return f"{v * 1e12:.4f}p" elif abs(v) >= 1e-6 and abs(v) < 1e-3: return f"{v * 1e6:.4f}u" else: return f"{v:.6g}" def txt_to_cir(src_file, dst_file, subckt_name="CST_MODEL"): # 0必须保留给地,CST里常见的GND也映射过来 node_map = {"GND": "0", "gnd": "0"} node_counter = 1 def map_node(node): nonlocal node_counter if node in node_map: return node_map[node] # 如果节点名是纯数字,直接用 if node.isdigit(): return node # 其他文本节点,按出现顺序映射成数字 node_map[node] = str(node_counter) node_counter += 1 return node_map[node] with open(src_file, "r", encoding="utf-8") as f: lines = f.readlines() out = [] out.append(f"* SPICE netlist converted from {src_file}") out.append(f".subckt {subckt_name} ") port_nodes = [] # 先把端口列出来,这里假设端口在txt里能识别 parsed = [] for raw in lines: line = raw.strip() if not line or line.startswith(("#", "!", "*", "//")): continue parts = line.replace(",", " ").split() if len(parts) < 3: continue kind = parts[0][0].upper() if kind not in ("R", "L", "C", "K"): continue if kind == "K": # 耦合元件格式: K_name L1 L2 coefficient mapped = [parts[0], parts[1], parts[2], parts[3]] parsed.append(" ".join(mapped)) else: node1 = map_node(parts[1]) node2 = map_node(parts[2]) val = suffix_convert(parts[3]) element = f"{parts[0]} {node1} {node2} {val}" parsed.append(element) # 端口映射完后,把用到的外部节点作为子电路端口,按升序排列 ext_nodes = sorted(set(map_node(p) for p in node_map.values() if p != "0")) out[1] = f".subckt {subckt_name} " + " ".join(ext_nodes) out.extend(parsed) out.append(".ends " + subckt_name) out.append(".end") with open(dst_file, "w", encoding="utf-8") as f: f.write("\n".join(out) + "\n") if __name__ == "__main__": txt_to_cir("cst_export.txt", "converted.cir", "ANT_DP")

这段脚本处理CST导出的RLC列表很够用。关键点都在:跳过注释行,兼容逗号和空格分隔,自动把文本节点名映射成数字,0节点保留给地,生成完整的子电路闭环。用的时候你只需要根据自己txt实际的分隔符微调split那部分。

如果你的输入是S参数文本,流程会多一步拟合,脚本不会这么简单。这种情况通常先把S参数交给矢量拟合工具处理,得到极点留数后,再按有理函数展开成的RLC等效网络写cir。理论上能手动算,但工程上没必要,各大厂商的拟合工具比自己折腾快得多。

3.4 转换后的验证流程

转换完不是直接丢给仿真器就完事,验证是必须的,否则你根本不知道转换过程有没有引入错误。

最简单的验证方法:把生成的cir放到LTspice里,搭一个测试电路,加一个交流电压源,在端口上扫频,然后导出S参数和CST原始结果对比。手写一个测试网表:

* Test bench for converted model .include converted.cir V1 in 0 AC 1 Rsrc in node1 50 X1 node1 node2 0 CST_MODEL Rload node2 0 50 .ac lin 500 100k 5G .plot db(v(node1)) .end

如果输入是单端口模型,V1和Rsrc直接接X1的端口1,Rload接端口2(或者按你的端口定义接匹配负载)。跑完AC扫描,看节点1处的电压驻波或者反射系数,和CST导出的S11曲线对比,重点看谐振频率位置和深度是否一致。偏差在百分之几以内基本可用,如果你发现谐振频率整体偏移,说明节点映射或者元件数值出了问题,回去查txt解析。

4. 一路踩过来的坑:常见问题与排查技巧

4.1 单位错误,结果瞬间差出几个数量级

这个问题是我自己踩过最深的坑。CST导出选项里有个单位设置,很多版本默认输出国际单位,但某些宏或者旧版本模板会把电容导成皮法、电感导成纳亨,而你脚本里可能全按标准单位解析。一混,谐振点直接偏出十万八千里。

排查技巧很简单:转换前先看txt里有没有单位说明行,比如“Unit: pF”这种,有就按说明来。没有说明的话,从量级上判断,微带走线宽度的等效电容一般在0.1到5pF之间,天线匹配电感通常在1到20nH之间。如果你解析出的数值在0.1e-9这个量级,又明显不符合物理直觉,基本可以断定单位没换算对。

4.2 节点命名非法,SPICE仿真器直接罢工

CST导出的节点名有时候带着括号、逗号、井号,比如“n1(int1)”。这些字符在SPICE里未必合法,导入LTspice可能直接报错“Unknown node name”。现象就是仿真器疯狂刷红字,你还找不到是哪一个元件的错。

处理办法就是脚本里的“节点映射”机制,不要原封不动地把节点名写进cir,全部按出现顺序重编号成纯数字。注意保留公共地节点为0,其他内部节点重新从1开始排。映射表最好同时输出一份备注文件,不然以后你想把SPICE仿真结果对应回CST端口,会查得头皮发麻。

4.3 模型不收敛与精度不足

转换出的模型在LTspice里不收敛,是另一个高频问题。表现是直流工作点计算失败,或者时域仿真步长越跑越小最后卡死。

多数原因是等效电路里有纯电感环路或者节点之间只有电容悬空,SPICE做直流分析时找不到直流通路。解决办法是在模型里加一个巨大的电阻(比如1G欧姆)到地,给悬空节点提供直流泄放路径。另一个常用技巧是给耦合电感稍微串一点点电阻,比如0.001欧姆,能明显改善时域求解器的收敛性,对正常频率响应的影响基本可以忽略。

如果模型精度不足,典型表现是通带纹波和CST原始S参数对不上,尤其在高频端。这种时候先看拟合阶数够不够,CST的等效电路提取通常会给出模型阶数选项,试着提高一阶。如果还不行,多半是CST端频率范围设窄了,把你关心的频段加宽,重新提取再导一次。

4.4 不同CST版本带来的格式差异

CST版本更新很快,不同版本导出的txt兼容性并不一致。我遇到过2019版本导出的S参数文本用空格分隔,2021版本改成逗号分隔,文件头还多了几行说明。你要是拿老脚本去解析新文件,第一行就会出错。

我的习惯是转换脚本里把分隔符检测做进去,读取文件头后先判断行里逗号和空格的数量,自动选择split策略。另外,新版本导出SPICE模型的选项路径也有变化,网上搜教程时一定把版本号带进去,别拿旧教程硬套。

下面这个速查表是我整理的实际排查记录,碰到类似问题可以对着看:

现象可能原因处理办法
谐振频率整体偏移元件单位没换算查txt文件头单位说明,和物理量级对比
仿真器报未知节点节点名含非法字符脚本中做节点名映射,全部重编号
DC工作点不收敛悬空节点无直流通路加1G欧姆对地电阻,给耦合电感串小电阻
高频段S参数对不上拟合阶数不足或频率范围太窄提高模型阶数,加宽CST导出频段后重新提取
脚本解析报错分隔符或表头不兼容检测逗号/空格分隔,按行自适应解析
端口顺序错乱导出时端口顺序没记录导出前截屏保存端口列表,转换后按节点映射核对

我个人在实际操作中最深的体会是,转换这条链路里,脚本反而是最简单的部分,真正费时间的永远是前期的端口定义和事后的结果验证。第一次做转换时,我建议别急着自动化,先手动转换一个双端口或者单端口的小模型,把整个链路跑通一遍,摸清楚你手里CST版本导出的txt长什么样,再去写批量脚本。直接上手复杂模型,出问题都不知道该怀疑CST还是怀疑脚本。

另外一个小技巧,转换完的cir文件开头一定要写清楚端口定义和原始S参数文件路径,这个文件过几个月再翻出来,这些备注能帮你省下一整个下午的回忆时间。CST版本升级以后,旧模型重新导出时,一定要重新核对一遍端口顺序和参考阻抗,别以为上次能导这次就一定能导。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询