1. 从“数字”到“模拟”为什么数模混仿是芯片设计绕不开的坎如果你是一名数字芯片设计工程师或者正在学习数字前端设计那么你对VCS、Verdi这些工具一定不陌生。我们习惯了在RTL的世界里驰骋用SystemVerilog写测试平台用VCS跑仿真再用Verdi看波形、做调试。一切都那么“干净利落”信号是0和1时序是时钟沿逻辑是布尔代数。但当我们设计的芯片需要与真实世界交互时比如要接一个USB接口、驱动一个显示屏、或者处理来自麦克风的音频信号问题就来了。真实世界的信号是连续的电压和电流它们的变化是平滑的而不是在某个时钟瞬间从0跳变到1。这时候纯粹的“数字仿真”就失灵了因为它无法描述模拟电路比如一个锁相环PLL、一个数模转换器DAC、或者一个简单的RC滤波电路的行为。这就是“数模混合仿真”简称数模混仿AMS Simulation登场的时刻。简单来说数模混仿就是搭建一座桥梁让数字仿真器如VCS和模拟仿真器如SPICE或FastSPICE引擎能够协同工作。数字部分继续用Verilog/SystemVerilog描述模拟部分则用SPICE网表或Verilog-A/AMS等硬件描述语言来描述。仿真器负责在两者之间传递信号数字信号驱动模拟电路时需要转换成电压值模拟电路的输出一个连续变化的电压需要被数字电路采样时又要被量化成0或1。这个过程听起来简单但实操中充满了挑战仿真速度可能急剧下降模拟仿真比数字仿真慢几个数量级、收敛性问题模拟仿真不收敛导致仿真卡死、以及复杂的调试信号在两种域之间转换时丢失或畸变。因此理解数模混仿的基本原理和工具链对于从事复杂SoC、接口芯片、电源管理芯片等设计的工程师来说已经从“加分项”变成了“必备技能”。本文将从一个数字工程师的视角带你拆解数模混仿的入门核心聚焦于如何利用VCS、XA/VCS-MX和Verdi这套主流工具链跑通你的第一个混仿环境并避开那些新手最容易掉进去的坑。2. 核心工具链解析VCS, XA与Verdi各自扮演什么角色在进入具体操作之前我们必须先理清工具链中各个“角色”的职责。很多新手一开始就被各种工具名搞晕了VCS、VCS-MX、XA、FineSim、HSPICE、Spectre、Verdi……它们之间到底是什么关系这里我们聚焦于Synopsys新思科技的解决方案因为它在工业界应用最广也是你搜索“vcs verdi 联合仿真”时最常见的结果。### 2.1 VCS数字世界的“发动机”VCS是Synopsys的旗舰级数字逻辑仿真器。在纯数字仿真中它负责编译你的RTL代码和测试平台并执行仿真产生运行结果。在数模混仿中VCS的角色升级为“主控调度器”。它仍然是仿真的起点和总指挥。当你启动一个混仿时实际上是由VCS进程来启动的。VCS会负责管理整个仿真的时间推进、调度数字部分的进程、并通过一个标准的接口通常是VPI或DPI与模拟仿真器进行通信。你可以把它想象成电影片场的导演数字部分和模拟部分都是演员导演负责喊“开始”和“卡”并确保两边演员的戏份能接得上。### 2.2 XA 或 VCS-MX模拟世界的“解算器”这是数模混仿中的另一个核心。XA是Synopsys的一款高性能、高容量的晶体管级电路仿真器属于SPICE类仿真器。而“VCS-MX”这个名称更准确地说是VCS的一个功能模块或模式它内嵌了或能够调用像XA这样的模拟仿真引擎来进行协同仿真。在实际的项目脚本和讨论中人们常常混用这些术语。你可以这样理解当我们需要进行数模混仿时我们会使用vcs -mx或类似的选项来编译和运行这个-mx标志就是告诉VCS“这次仿真需要混合信号支持请准备好与模拟引擎如XA对话”。模拟引擎的任务是接收来自数字域的驱动信号比如一个理想方波变成了带有上升/下降时间的电压源然后求解复杂的微分方程计算出模拟电路节点上的连续电压/电流波形。这是整个仿真中最耗时、也最容易出问题的部分。### 2.3 Verdi跨越数模的“调试望远镜”Verdi是强大的调试平台。在纯数字仿真中我们用Verdi加载FSDB波形文件查看信号的跳变、追踪逻辑错误。在数模混仿中Verdi的能力得到了延伸——它不仅能显示数字信号0/1/X/Z还能显示模拟信号连续的电压、电流波形。这才是Verdi在混仿中无可替代的价值它提供了一个统一的调试窗口。你可以在同一个波形视图里看到数字控制信号“enable”拉高后模拟电源电路“vout”引脚上的电压是如何从0V缓慢上升至1.8V的你可以测量这个上升时间可以检查电压过冲可以交叉探测cross-probe从RTL代码到模拟网表再到波形。没有Verdi你就得用数字波形查看器看一部分再用像gtkwave或模拟仿真器自带的波形工具看另一部分两者时间轴可能还对不齐调试效率极低。因此在搭建混仿环境时如何正确生成和加载包含模拟信号的FSDB文件是关键一步。### 2.4 SPICE网表模拟电路的“剧本”模拟部分的行为由SPICE网表描述。它可能来自电路设计工程师提供的.sp或.ckt文件也可能是你从第三方厂商那里拿到的器件模型比如一个MOSFET的BSIM4模型。对于初学者我们常常从一个最简单的RC电路或者一个反相器inverter开始。网表中定义了元器件电阻R、电容C、晶体管M、它们的连接关系、以及电源和地。在混仿中这个网表会被模拟仿真器XA读取和求解。这里有一个关键概念接口信号。在网表中需要被数字电路驱动或驱动的那些节点即数模边界必须被正确定义。通常这通过在网表中使用一些特殊的“端口”或“器件”来实现这些端口会被混仿工具自动识别并连接到对应的数字信号上。3. 搭建你的第一个数模混仿环境从零到一的实战步骤理论讲得再多不如动手跑一遍。下面我们以一个最经典的例子——用一个数字信号控制一个模拟的RC电路——来演示完整的流程。这个例子虽小但涵盖了所有核心环节。### 3.1 准备设计文件数字部分与模拟部分首先我们需要三样东西数字测试平台、数字设计或直接由测试平台产生激励、模拟网表。数字测试平台testbench.sv我们用SystemVerilog写一个简单的测试产生一个周期性的方波信号dig_out。timescale 1ns/1ps module testbench; reg clk; wire dig_out; real ana_in; // 这是一个实数变量用于接收从模拟域转换回来的电压值 // 实例化顶层模块这里假设顶层模块叫top它内部实现了数模接口 top u_top (.clk(clk), .dig_out(dig_out), .ana_in(ana_in)); initial begin clk 0; // 控制仿真时长例如跑5个微秒 #5000 $finish; end always #5 clk ~clk; // 100MHz时钟 // 打印模拟信号的值用于简单观察 always (ana_in) begin $display([%0t] ana_in %f V, $time, ana_in); end endmodule数字设计/接口模块top.sv这个模块是关键它声明了与模拟电路连接的信号。注意驱动模拟电路的信号dig_out是wire类型而从模拟电路读回的信号ana_in需要声明为real类型。在真实的混仿中这些信号会通过特定的系统函数或模块如electrical与模拟域绑定但最常用的方式是通过一个“连接模块”Connect Module或直接在网表中定义。timescale 1ns/1ps module top (input clk, output reg dig_out, input real ana_in); // 一个简单的数字逻辑每隔一段时间翻转一次输出 integer count 0; always (posedge clk) begin count count 1; if (count 50) begin // 每50个时钟周期翻转一次 dig_out ~dig_out; count 0; end end endmodule模拟SPICE网表rc.sp这是一个简单的RC低通滤波电路。数字信号dig_out经过一个电阻给电容充电电容上的电压ana_in就是滤波后的模拟信号。注意网表中的Vdig和Eana它们是实现数模接口的关键。在实际的混仿工具中有更标准的方式如使用ahdl_interface模块或工具自动插入的接口元件但这里为了原理清晰展示一种概念性写法。实际项目中请严格遵循所用工具VCS-MX的接口规范。* Simple RC Filter for Mixed-Signal Simulation .options post2 * 数字信号驱动的电压源它的值由数字信号 dig_out 控制 * 当 dig_out1 时Vdig 输出 1.8V当 dig_out0 时输出 0V。 * 这里用了一个受控电压源实际工具中可能是通过自动插入的接口元件实现。 Vdig dig_node 0 PWL filedig_wave.txt // 示意电压值来自一个由数字仿真生成的波形文件 * RC 滤波电路 R1 dig_node ana_in 1k C1 ana_in 0 1p * 将模拟电压 ana_in 回传给数字域作为 real 信号 * 这通常也是一个由工具自动处理的接口。 .print tran v(ana_in) .tran 0.01ns 5000ns .end注意上面网表中的PWL file和接口方式是高度简化的。真实流程中VCS-MX会自动处理信号转换和传递你通常不需要手动创建这样的PWL文件。你只需要在模拟网表中将需要连接的端口用特定的子电路或器件模型如resistor、capacitor与数字接口器件相连描述清楚即可。### 3.2 关键一步编写配置文件与编译仿真纯数字仿真我们可能一个vcs -sverilog testbench.sv top.sv命令就搞定了。混仿则需要一个配置文件通常叫ams.scs或spectre.scs来告诉工具模拟部分在哪里、如何连接。创建配置文件ams.scs这个文件的内容与工具版本和具体需求强相关但基本结构如下。它主要做两件事指定模拟仿真器如XA的路径和选项定义数模边界信号connectrules的映射关系。simulator langspectre // 指定模拟仿真器为XA ahdl_include “$VCS_HOME/linux64/lib/liberal.va” // 可能需要的VA模型库路径 // 定义顶层测试平台和模拟网表 topcell testbench schematic rc.sp // 信号连接规则将数字域的“dig_out”信号连接到模拟网表中的“dig_node”节点 // 将模拟网表中的“ana_in”节点连接到数字域的“ana_in”real变量 connectrules dig_out - dig_node ana_in - ana_in end // 模拟仿真器选项 simulatorOptions options \ psfversion1 \ maxnotes5 \ maxwarns5 \ methodtrap \ reltol1e-3 \ vabstol1e-6 \ iabstol1e-12 // 分析语句已在网表中定义这里也可覆盖 tran tran stop5000ns使用VCS-MX进行编译和仿真命令变得复杂了。你需要使用vcs -mx模式并指定配置文件。# 编译阶段 vcs -mx -ams -ams_discipline logic \ -ams_config ams.scs \ -sverilog testbench.sv top.sv \ -debug_accessall -kdb -lca \ -P $VERDI_HOME/share/PLI/VCS/linux64/novas.tab \ $VERDI_HOME/share/PLI/VCS/linux64/pli.a \ -o simv_mixed # 运行仿真 ./simv_mixed -ams -ams_config ams.scs -ucli -i run.tcl命令参数拆解-mx启用混合信号仿真功能。-ams指定使用AMS仿真流程。-ams_discipline logic定义默认的信号 discipline电气规则对于数字驱动模拟的信号很重要。-ams_config ams.scs指定我们刚才编写的配置文件。-debug_accessall -kdb为了生成Verdi调试所需的KDB数据库和FSDB波形。-P ...指定Verdi的PLI库路径这是Verdi能够介入仿真、记录波形的关键。-o simv_mixed指定输出的可执行文件名。运行命令./simv_mixed通常会启动一个交互式环境或执行一个包含运行命令的Tcl脚本run.tcl。run.tcl内容可能如下# run.tcl run dump -fsdb -o mixed_signal.fsdb # 导出FSDB波形文件 quit### 3.3 使用Verdi进行联合调试仿真完成后会生成mixed_signal.fsdb和simv_mixed.kdb等文件。用Verdi打开它们你就能看到梦寐以求的数模混合波形了。verdi -dbdir simv_mixed.kdb -ssf mixed_signal.fsdb 在Verdi的波形窗口中你应该能看到testbench.clk标准的数字时钟信号只有0和1。testbench.u_top.dig_out数字输出信号也是0和1的跳变。testbench.u_top.ana_in或 在模拟网络下找到的ana_in节点这是一个模拟波形它应该是一条光滑的曲线在dig_out从0跳变到1后电压从0V开始按指数规律上升趋近于1.8V当dig_out跳回0时电压又指数下降回0V。你可以用Verdi的测量工具测量上升时间10%~90%的时间。实操心得一环境变量与License混仿对License的要求比纯数字仿真更严格。除了VCS和Verdi的License还需要AMSMX和XA的Feature。在运行前务必用lmstat命令检查License是否齐全。另外VCS_HOME、VERDI_HOME等环境变量必须正确设置否则编译时会找不到库文件报出一堆undefined reference的错误。4. 混仿中的核心挑战与调试技巧避开那些“坑”第一个例子能跑通只意味着你打开了这扇门。真正的挑战在后面的项目中。以下是几个最常见的“坑”及其应对策略。### 4.1 仿真性能从“秒级”到“小时级”的断崖这是最直观的挑战。一个纯数字仿真可能几分钟就跑完了加入一小块模拟电路后仿真时间可能变成几小时甚至几天。原因在于模拟仿真器需要求解非线性微分方程时间步长是自适应、非常细密的皮秒级而数字仿真的事件步长通常在纳秒级。应对策略划分边界最小化模拟部分仔细审视设计真的需要把整个PLL都用晶体管级仿真吗或许只有VCO核心需要而分频器可以用数字模型。使用verilogams或wrealWire-Real模型来替代部分模拟电路它们是连续时间域的数学模型仿真速度比SPICE快得多但精度足够用于系统级验证。使用FastSPICE引擎XA本身已经比传统SPICE快但对于超大模块如存储器阵列可以评估使用UltraSim、FineSim等FastSPICE工具它们在牺牲一定精度的情况下大幅提升速度。合理设置模拟仿真精度在ams.scs的simulatorOptions中reltol相对误差、abstol绝对误差不要设得过于苛刻。默认值如reltol1e-3通常已足够。过高的精度要求会急剧增加计算量。采用“分阶段仿真”策略不要一开始就跑全芯片的长时间混仿。先对模拟模块做晶体管级特性仿真提取其行为模型如Verilog-A再用这个模型与数字部分进行仿真速度会快很多。### 4.2 收敛性问题仿真卡死与“时间点重复”模拟仿真器在求解电路方程时可能因为电路状态突变、负阻、不合理的初始条件等原因无法收敛导致仿真卡在某个时间点。VCS的log里可能会出现repeating timepoint的警告然后陷入死循环。调试技巧检查初始条件.IC确保电路有合理的直流工作点。可以在SPICE网表中使用.IC语句为关键节点如电容电压设置初始值。简化模型首先用最理想的模型如开关电阻电容替换复杂的晶体管模型如BSIM4看是否能收敛。如果能问题可能出在模型本身或模型参数上。调整仿真器选项尝试更改积分方法。默认的trap梯形法稳定性好但有时gear2方法对刚性电路更有效。也可以尝试减小maxstep最大步长强制仿真器用小步长“慢慢爬”过难收敛的区域。查看模拟仿真器的独立输出在混仿出错时工具通常会生成一个独立的模拟仿真log文件如xa.log。仔细查看这个文件末尾的报错信息比看VCS的log更有用。常见的错误有“Matrix is singular”矩阵奇异可能电路没接对、“Time step too small”时间步长过小可能电路有振荡。### 4.3 信号连接与精度丢失为什么我的模拟波形是台阶状的理想情况下从数字域驱动过来的信号在模拟域应该是一个有上升/下降时间的波形。但有时你会发现这个驱动信号在模拟端看起来像一个理想的方波垂直上升或者模拟信号反馈到数字域后real变量的值变化不连续呈“台阶状”。这通常是因为接口精度设置不够。问题根因与解决ams_discipline设置不当在编译命令或配置文件中-ams_discipline定义了默认的接口电气规则。对于数字驱动模拟的信号应该使用logic或customdiscipline并确保其potential电压和transition跳变时间属性被正确定义。一个未定义或定义不当的discipline会导致工具使用默认的理想开关模型。连接模块Connect Module版本VCS-MX使用内部的连接模块来处理信号转换。确保你使用的是适合当前工艺和电压的版本。有时需要手动指定连接模块的库路径。模拟求解器输出步长Verdi中显示的模拟波形其“光滑度”取决于模拟仿真器输出的数据点密度。如果模拟仿真器的.tran语句输出步长如.tran 10ns 1000ns设得太大波形看起来就是由很粗的线段连接而成像台阶。可以减小输出步长如.tran 0.1ns 1000ns但会增大波形文件体积。更好的办法是在Verdi的波形设置中开启“模拟波形插值”显示选项让它自动光滑连接数据点。### 4.4 Verdi调试技巧让混合信号无所遁形Verdi是混仿调试的利器但要用好它需要一些技巧。信号分组与颜色区分在波形窗口将数字信号和模拟信号分别放入不同的组Group并用不同的颜色高亮。例如将所有real类型的信号设为红色曲线将所有wire/reg信号设为绿色跳变线。一目了然。使用“Analog Bus”功能如果模拟部分有总线信号比如一个8位的DAC输出Verdi可以将它们组合成一个“模拟总线”以数字值十进制或十六进制和模拟波形两种形式同时显示非常直观。交叉探测Cross-Probe的威力在波形上点击一个异常的模拟电压尖峰然后使用交叉探测功能快捷键通常是CtrlX可以直接跳转到SPICE网表中驱动这个节点的电压源或晶体管上。反之亦然从网表可以跳回波形。这是定位数模交互问题的终极法宝。保存与重调用信号Make/Verdi这是搜索热词“make verdi 查看信号保存与重调用”提到的功能。在大型仿真中我们不可能每次都把所有信号波形都dump出来FSDB文件会巨大无比。通常的做法是第一次仿真时只dump少量关键信号发现问题后通过修改dump.tcl脚本或fsdb命令添加感兴趣的信号然后不重新编译直接rerun仿真利用VCS的-ucli交互模式Verdi会自动将新旧波形合并显示。这个流程需要熟练掌握VCS的UCLI命令和Verdi的fsdb命令序列。5. 从入门到进阶工作流优化与高级话题初探当你成功运行了几个基础混仿例子后可以考虑优化工作流并了解更高级的应用场景。### 5.1 建立可复用的混仿环境框架手动敲命令效率太低。一个标准的项目应该有一个基于Makefile或Python脚本的自动化编译仿真流程。这个框架应该能自动识别设计文件.sv,.v,.sp,.scs。根据模式pure_digital,mixed_signal,full_ams选择不同的编译选项。自动生成和更新配置文件如ams.scs。管理仿真种子seed和参数化测试。自动启动Verdi并加载预设的信号分组和视图。一个简单的Makefile骨架可能是这样的TBtestbench AMS_CONFIGams.scs VCS_OPTS-mx -ams -ams_discipline logic -debug_accessall -kdb -lca VERDI_OPTS-dbdir simv_mixed.kdb -ssf waves.fsdb compile: vcs -ams_config $(AMS_CONFIG) $(VCS_OPTS) -sverilog *.sv -o simv_mixed run: ./simv_mixed -ams -ams_config $(AMS_CONFIG) -ucli -i run.tcl verdi: verdi $(VERDI_OPTS) clean: rm -rf csrc simv* *.daidir *.log *.fsdb *.key DVEfiles *.vpd novas.* ucli.key### 5.2 理解“Real Number Modeling (RNM)”与“wreal”在系统架构验证阶段使用晶体管级SPICE网表进行混仿太慢了。这时Real Number Modeling (RNM) 就派上用场了。RNM的核心是用实数real或位向量bit vector在数字仿真器中直接表示模拟量。SystemVerilog中的wrealWire-Real网络类型就是为此而生。一个wreal信号可以连续地传递一个浮点数如电压值2.75。你可以在数字测试平台里用算法直接产生一个带噪声的电压信号驱动给一个用wreal建模的ADC行为模型然后ADC模型输出数字码。整个过程都在VCS中完成速度极快非常适合算法验证和架构探索。它本质上是在数字仿真器内做模拟行为建模是纯软件行为不调用任何模拟求解器。只有当需要验证晶体管级电路是否精确实现了这个行为时才需要启动真正的数模混仿。将RNM作为混仿的前置步骤可以极大提高验证效率。### 5.3 处理复杂的混合信号模块以PLL和ADC为例对于锁相环PLL或模数转换器ADC这类经典混合信号模块混仿策略需要特别设计。PLL混仿全晶体管级的PLL仿真极其缓慢。常见的策略是分区混仿。将PLL的压控振荡器VCO和电荷泵CP用晶体管级网表而分频器Divider和相位频率检测器PFD用RTL代码。这样仿真器只在VCO和CP部分进行耗时的模拟求解整体速度可接受。关键是要在分频器数字和VCO模拟之间正确设置接口。ADC混仿通常采用“前仿后仿”结合。前端采样保持、比较器可以用晶体管级网表而后端的数字纠错逻辑如SAR逻辑用RTL。更高级的方法是使用Verilog-AMS为ADC建模在AMS仿真中模拟部分用方程描述连续时间行为数字部分用事件驱动平衡了精度和速度。### 5.4 协同仿真Co-Simulation与数模混仿的区别有时你会听到“协同仿真”这个词。它通常指两个独立的、异构的仿真器通过标准接口如SCE-MI、TLM进行通信例如用一个专用的模拟仿真器如Spectre和一个数字仿真器如VCS一起跑。而VCS-MX进行的数模混仿更像是“单内核”仿真模拟引擎XA作为插件被VCS调用和管理集成度更高数据交换效率也更高。对于芯片设计VCS-MX这种深度集成的模式是主流。协同仿真更多用于软硬件协同验证如CPU模型数字仿真器。数模混仿的门槛确实比纯数字仿真高它要求你同时理解数字设计流程和模拟电路的基本概念。但一旦掌握你就拥有了验证复杂芯片系统的关键能力。我的建议是从一个像RC电路这样微小的例子开始确保每一步都理解透彻然后逐步增加复杂度比如换成一个反相器链再换成简单的PLL子模块。过程中遇到的每一个报错和异常波形都是加深理解的绝佳机会。多查工具的官方文档Synopsys的SolvNet是一个宝库多和模拟电路同事交流你会发现自己对芯片如何工作的认知会从一个离散的、逻辑的世界拓展到一个连续的、物理的世界这种全局视角是无价的。