RNM与Verilog-on-Top:混合信号验证MSDV的工程实践指南

RNM与Verilog-on-Top:混合信号验证MSDV的工程实践指南 做混合信号验证的兄弟十有八九都被同一件事折磨过数字仿真跑着跑着模拟模块闹脾气要么收敛不了要么 negdelay 满天飞反过来把整个 SoC 都扔进 SPICE 里精仿别说仿真时间光内存就能把服务器拖垮。MSDVMixed-Signal Design Verification解决的就是这个撕裂感——它不要求你在全仿真和纯建模之间二选一而是用 RNM 抽象把模拟行为拿到数字事件驱动域里跑再通过 Verilog-on-Top 的架构把验证重心放在数字侧最后让模型像一颗正经 IP 那样落成一份仿真网表进 regression、进 sign-off。这篇东西没有教科书腔全是我自己从项目里磨出来的思路和坑适合刚接触数模混合验证的 DV也适合想给模拟模型找一个工程化出口的 AMS 工程师。先说结论RNM 不是“用 Verilog 写个大概”而是要同时满足三件事——行为足够准、事件足够密但别爆、格式足够标准能进别人家的流程。做不到第三点前面两点都白干因为模型落不了网表就进不了 SoC 级仿真价值直接清零。1. 一块数模混合芯片的验证困境1.1 传统流程卡在哪数模混合芯片的验证过去基本是两条线并行模拟团队用 SPICE 把每个模块抠到晶体管级数字团队用 SystemVerilog/UVM 把门级网表跑到千百万 cycle。问题出在两个世界的交界处——模数转换器输入抖动、电源域下电顺序、ESD 保护管的漏电、LDO 启动时序……这些东西既不在模拟团队的纯 SPICE 模型里也不在数字团队的纯逻辑模型里结果就是每次 tapeout 前的 full-chip 仿真总有人在手动拼网表拼到凌晨三点。我见过最经典的一回模拟团队交付了一个带 10 个工艺角的锁相环模型数字团队直接把 .scs 文件往 VCS 里一丢原因也不看跑出来一堆V(a,b)未定义信号。两边互骂三天最后发现是模型里模拟电压域和数字逻辑域没有做转换层。这种问题不是某个人水平不行而是流程上压根没有定义“混合域的模型该长什么样”。MSDV 的思路是把这件事从“临时对接”变成“标准接口”。它要求你建立一套能让模拟行为在数字事件驱动环境里被认可的表达方式同时保留必要的精度信息。RNM 就是这套表达方式的地基。1.2 MSDV 到底改变了什么MSDV 不是工具也不是某一种语言而是一套验证方法论。它有几个核心主张第一验证场景必须以数字系统的视角来定义因为最终流片回来跑软件的是数字系统模拟模块只是外设第二模拟模块在 SoC 级仿真里不应该用 SPICE 全保真而应该用抽象模型替代这个模型要能表达关键电气行为第三抽象模型必须能无缝进入数字仿真器和 UVM 的 sequence、scoreboard、覆盖率模型一起工作。这套方法论最大的改变是把“模拟模型验证”从模拟工程师的私活变成了团队共享资产。模拟工程师写一个 RNM 模型不只是给自己做行为 sanity check而是要给数字验证团队当 VIP 用DUT 是数字逻辑模拟模块就是 stimulus driver也是 checker。你要让一个数字 DV 愿意用你的模拟模型唯一的方法就是让它像数字 IP 一样好用——有清晰接口、有参数、有波形能查、有问题能定位。1.3 RNM 为什么是这一切的基石RNMReal Number Modeling的核心理念是用 real 类型变量表达连续信号用事件驱动的方式近似模拟域行为。它和 SPICE 的最大区别是SPICE 在每个时间步都要解非线性微分方程而 RNM 只在特定事件发生时更新值计算复杂度降了几个数量级。举个例子一个上电复位POR模块SPICE 模型要仿真电源电压从 0 到 0.8V 的整个斜坡收敛步长可能小到纳秒。RNM 模型只需要在电压穿越阈值的那一个点产生一次事件告诉数字侧“我现在拉高复位信号”。这个事件驱动的抽象正是数字仿真器最擅长处理的模式。但“real 变量事件驱动”听着简单写起来全是细节。阈值点怎么算、迟滞怎么加、时钟与电压采样的对齐、更新间隔怎么控制这些直接决定模型能不能和数字逻辑协同仿真。下一节我把 RNM 建模的完整思路和示例扒开讲。2. RNM 建模该从哪里下手2.1 wreal 与 real 类型的正确姿势RNM 建模第一件事是在 Verilog-AMS 或 SV 里选对数据类型。real可以声明变量和线网但不同仿真器对 real 的 event 调度支持不一样wreal是更贴近模拟语义的 net type专门用来在数字环境里表示连续值信号。wreal 的好处是它天然有“小步长更新”的语义当上游电压变化时wreal 会触发下游的 always 块不用你手动造事件。我建议你在模块边界上用 wreal在模块内部计算时随便用 real。比如一个比较器的 RNM 模型可以这样写module comp_rnm ( input wreal vin_p, input wreal vin_n, output logic vout ); parameter real vth 0.5; parameter real tpd 5n; // 传播延迟 real vdiff; always (vin_p or vin_n) begin vdiff vin_p - vin_n; if (vdiff vth) vout #tpd 1b1; else vout #tpd 1b0; end endmodule这里有几个细节值得注意。(vin_p or vin_n)的敏感列表依赖 wreal 信号变化事件但实际电压缓慢变化时事件密度可能不够导致阈值穿越时刻被延迟。解决办法是引入$bound_step控制最大步长或者在模拟块里用cross函数做精确阈值检测。此外#tpd的延迟只是数字惯性延迟它不考虑转换时间slew rate如果后续模块对边沿斜率敏感仅仅这样会有误差。一个我在项目里吃过亏的点wreal 在 initial 仿真开始前一般为 0。如果你的模型里输入电压是 0输出却不该是“逻辑 0”就会出现启动时的错误复位或错误中断。解决办法是在 initial 块里根据稳态工作点给输出赋初值或者在验证环境里显式初始化模拟电源。2.2 从模拟单元到 RNM 模型的拆分思路不要把整个锁相环写成一个巨大 always 块那是灾难。正确做法是照模拟拓扑拆每个功能单元一个模型单元之间用 wreal 连接行为分两层表达——稳态方程和瞬态事件。以低压差线性稳压器LDO为例我会把它拆成三个部分参考电压源、误差放大器带增益和带宽限制、输出功率管带压降和限流。RNM 模型里用 real 算电压module ldo_rnm ( input wreal vin, input wreal vref, output wreal vout ); parameter real vdrop 0.3; parameter real gain 1000; parameter real bandwidth 100k; // 一个简化的带宽折算 real vout_val; // 内部计算值 real vout_filt; always (vin or vref) begin vout_val (vin - vdrop vref * gain) ? (vref * gain) : (vin - vdrop); // 这里用一阶低通近似带宽有限效应实际里再按离散周期处理 vout_filt vout_filt (vout_val - vout_filt) * bandwidth * 1n; vout vout_filt; end endmodule注意上面这段代码里我用了带隐含时间步1n的近似滤波这在纯事件驱动环境里其实有点取巧、不够严谨真正的实现通常要配合$time做离散化。我要强调的策略是稳态方程决定精度瞬态事件决定时序。你首先用数学公式把稳态输出对上再用事件去处理上电、下电、负载跳变这些瞬态场景最后用 SPICE 跑几个典型 corner 做校准把参数调到误差可接受。2.3 模型精度与仿真速度的平衡术RNM 建模最大的误导是“越精确越好”。真不是。你要根据验证目标选精度等级我习惯分三档精度档位表达方式适用范围速度损耗行为级阈值延迟高低电平功能验证、软件协同极小应用级加噪声、加精度误差、加温度漂移算法验证、系统性能中等校准级追 SPICE 曲线、带非理想效应电源域验证、时序签核大一个团队如果所有模型都做到校准级RNM 就失去意义了它跑得比 SPICE 也就快个 2 到 3 倍还要花大量时间做校准。真正的产出比是80% 的模块用行为级15% 用应用级只有电源管理和高精度参考源这类关键单元上校准级。我这几年摸索出来的节奏是第一版 RNM 只做行为级目的是把数字侧的 keep-up 流程打通等验证环境稳定了再针对覆盖率缺口或 bug 区域升级模型精度。不要试图一步到位否则进度会被模型的打磨周期拖死。3. Verilog-on-Top把模拟 IP 请进数字验证里3.1 架构选择为什么是 Verilog-on-Top 而不是 Analog-on-Top混合信号仿真环境顶层拓扑的选择会决定整个验证效率。Analog-on-Top 的语言是 Spice 或 Verilog-AMS模拟模块放 top数字模块挂下面适合模拟模块间耦合深、数字只是陪衬的场景。但 MSDV 的核心目标是验证数字系统与模拟模块的交互所以我强烈建议用 Verilog-on-TopVoT。VoT 的含义是仿真顶层用 SystemVerilog 搭DUT 是数字逻辑模拟模块以单元实例的方式挂在数字层里它们通过连接模块connect module或接口元素做实数域与逻辑域的转换。这样做有三个直接收益UVM 的驱动和检查机制可以直接作用于模拟接口不需要额外写模拟激励断言和覆盖率模型可以同时在数字和模拟边界上工作回归测试的支持性最好因为整个环境跑在数字仿真器里不需要动不动叫起一个 SPICE 引擎。选 VoT 还有一个容易被忽略的原因它可以沿用数字验证里成熟的“平台化”思路。你搭好一套带有标准 AMS 接口的验证平台之后任何新的模拟 IP 进来只要写好它的 RNM modelplatform 就能直接复用不用每颗芯片都重写一套模拟验证环境。这在项目周期以季度计算的行业里是真正的救命稻草。3.2 接口剪裁与混合仿真边界处理VoT 环境里最高的技术含量体现在数字与模拟的边界处理。你不可能把所有模拟信号都引到数字顶层那样不仅命名混乱事件密度也会失控。我一般遵循三个原则只引功能接口不引内部测试点模拟输出到数字的信号全部走专用连接模块端口的命名和方向在顶层统一管理防止数字团队和模拟团队各起一套名字。连接模块是混合仿真里的关键角色。它的活儿是完成“模拟实数域 ↔ 数字逻辑域”的转换。最简单的形式是一个用wreal做输入、logic做输出的模块内部做阈值判断和延迟处理module wreal_to_logic ( input wreal vin, output logic vout ); parameter real vlogic_high 0.66; parameter real vlogic_low 0.33; always (vin) begin if (vin vlogic_high) vout 1b1; else if (vin vlogic_low) vout 1b0; else vout vout; // 滞回区内保持原值 end endmodule反过来数字logic信号驱动模拟输入时需要把 0/1 映射成模拟电压。这里最容易出的错是模拟模块期望的电压参考和数字逻辑电源域不一致——数字域 1 是 1.2V模拟模型里却按 1.8V 算整个功能都对不上。我的习惯是连接模块里不放硬编码电压全部做成参数在顶层的 config 里按电源域统一例化。在边界处理上我还有一个实践建议把边界上的所有信号都做成一个“边界包”interface bundle用 interface 类管理同时声明断言。这样如果你在上电时序、复位释放这些节点上漏了时序关系仿真跑不下去就能立刻暴露而不是等到数据比对阶段才被 scoreboard 追出来。3.3 从 RNM 模型到可复用 VIP 的工程收口写好一个 RNM 模型只是第一步要让它成为工程资产必须收口成 VIP、有能力被多项目复用。我给内部团队定的交付清单是模型代码、参数说明文档、校准报告对过哪些 SPICE corner、使用示例和已知限制。其中参数说明文档最重要很多工程师写模型只给一行 parameter 定义连范围都不标下游用的人完全不敢碰。工程收口的另一个要点是版本管理。RNM 模型要跟着 SPICE 模型的迭代走但不能每改一版就强制全项目同步。我的做法是为每个模拟 IP 维护一套模拟视图单元analog view libraryRNM 模型作为其中一个 sim view 独立于 SPICE 视图config 里指定使用哪个视图。这样模拟团队更新 SPICE 模型不影响数字侧仿真数字侧想用 RNM 的新参数也只需要更新 sim view 版本两边互锁但互不阻塞。再一个容易踩的坑是 RNM 模型的time scale和精度设置。有人在 model 里写了timescale 1ns/1ps但顶层验证环境的精度是 1ps 或更细两个精度混用时延迟计算和事件排序会出现奇怪偏差。建议所有 RNM 模型统一用比系统精度低一个数量级的时间精度防止事件被截断。4. 把模型落到一份能跑的网表4.1 视图管理sim view 与 layout view 的差别前面提了视图管理这里展开说。很多刚做 MSDV 的人以为“落地成网表”就是把 RNM 模型写出来就完事其实不是。混合信号流程里模拟 IP 会有多个视图schematic view、layout view、extracted view、sim view。RNM 模型对应的就是 sim view它和 layout view 的差距非常大。layout view 是物理网表包含晶体管、寄生 RC、器件尺寸它的仿真精度最高但速度最慢。sim view 是抽象行为视图在 Verilog 或 Verilog-AMS 里表达速度快上百倍。MSDV 的底层逻辑就是系统级仿真用 sim view只有局部微调和最终 sign-off 才用 extracted view。落地成网表的“网表”并不是说要你自己去写 Spice 网表。实际动作是把 sim view 编译/打包成当前验证工具链能识别、能例化、能接到数字网表上的单元。这个过程涉及的工具链依赖很重Cadence 系irun/xrun有 AMS Designer 和 ade 的配置体系Synopsys 系VCS AMS有 ams.cfg 和 config 文件层级Mentor/Siemens 系Questa也有对应的设置。4.2 从模块级到 SoC 级网表落地操作路径我总结了一个可复制的落地路径分五步走第一步建模验证。在模块级验证环境里单独跑 RNM 模型的行为确认它和 SPICE golden model 在目标场景下误差可以接受。这个阶段要把校准报告做扎实否则后面每级集成都会放大误差。第二步生成仿真网表。把 RNM 模型和外围的数字逻辑一起通过综合/编译工具吐出一份真网表。这里的“真网表”对数字侧是门级网表对模拟侧是 sim view 实例两者通过 config 绑定工具生成一个混合网表文件。第三步配置视图映射。在混合仿真的 config 里指定模拟 IP 的 sim view、数字模块对应的库视图并定义模拟与数字的边界元素。这一步最繁琐容易错的地方是视图名和库名不一致或者某个 IP 的 config 没指定导致工具 fallback 到默认视图。第四步做连接性检查。工具会自动做 LVS 的一部分但你要额外检查到每一根边界信号。我常用的招数是写一个小的 SystemVerilog 断言模块在仿真开始时打印出连接矩阵里每个跨域信号对应的源模块、目标模块和转换模块。第五步回归集成。把混合网表跑进带时序注释的数字 regression 套件里观察是否有新的事件风暴和时序违例。这时候如果出现“模拟输出一直 x”的问题多半是 sim view 的端口方向定义和 SPICE 模型不一致或者是 wreal 信号在某个电源域里没有初始化。整个流程里有一个工具层面的经验我想特别提醒不同工具导出的网表格式不同export netlist和import netlist这两件事在 EDA 工具里看起来只是菜单上的两个选项实际上坑全在细节上。比如在板级/系统级工具链里OrCAD 导出网表再拿到 Allegro 导入时pin 顺序、网络命名、电源网络带的反斜杠转义任何一个不一致都会让你在后续仿真里到处找 net name mismatch。混合信号流程里的 netlist 落地也是同一个逻辑名字、方向、宽容差三点对齐后面才顺。4.3 跨工具落地导出、导入与 RC 反标模拟和数字的网表在工具链里往往是“两种语言”。数字网表是 VERILOG/VHDL 的 module 例化串模拟网表是 SPICE 格式的器件连接串。混合仿真器需要在同一进程里能同时解析两种格式并且知道在边界上怎么互相映射。Cadence 的实现是在 config 里列 cellview 映射Synopsys 则会在 compile 时插入 interface element。实际项目里我经常遇到“RNM 模型验证通过但一集成到 SoC 级网表就出问题”的情况最后定位到的原因往往是 RC 反标信息缺失。模拟 IP 的 sim view 里只有行为参数没有 layout 的寄生 RC。当上层 SoC 网表做了寄生参数反标时RC 数值无法反向映射进模拟 IP 内部工具要么忽略要么报 warning。要处理好这个问题你需要提前给模拟 IP 的行为模型预留 RC 参数的接口在 config 里加上反标文件让工具能正确地把提取的 RC 输入到模型内部的关键节点上。反标这件事很多验证工程师嫌烦但它恰恰是 RNM 模型能不能在 sign-off 阶段被承认的关键。如果你想让模型“能跑”只是第一步想让它“跑得让人信服”就必须把 PVT 和 RC 的影响全部显式表达出来而不是默认行为。5. 让 MSDV 真正跑起来的配套工程要点5.1 事件风暴与性能抖动RNM 模型最常见的“翻车现场”是事件风暴。字面上看是某个 wreal 信号在极短时间内产生大量事件把数字仿真器的事件队列打爆回归速度指数级下降。我见过一个电压参考源模型在输入电压接近阈值区时进入震荡状态每次震荡都产生上百个事件整个仿真时间从 40 分钟膨胀到 11 个小时。处理事件风暴有几招。第一招是加迟滞把单阈值改成双阈值模型不该翻转的时候就不翻转。第二招是加最小更新间隔一个 wreal 信号在 1ns 内只允许更新一次这样即便内部逻辑抖对外表现也是平滑的。第三招是用$fatal或断言盯住异常高频事件在调试验证阶段及时发现震荡源。我现在的习惯是任何 RNM 模型里都必须看到“防抖”的代码痕迹否则 review 不通过。另一个性能问题是“慢斜坡模拟”。有些模型为了追求精度会把电压斜坡切成几千个小步长事件。这样确实精确但在 SoC 级没必要。我建议对系统级仿真设一个“最小有意义电压变化量”阈值低于阈值的电压变化不产生事件。这个阈值通常取数字电源电压的 1/100 就够用。5.2 与 PVT 和工艺角相关的风险RNM 模型最容易被挑战的就是“这是 ideal model没有 PVT”。做 MSDV 要正面回应这个问题。我的方案是“不提全 PVT而是提目标 PVT”。先定义清楚这个模型在哪些电压、温度范围内有效在 config 里显式传递工艺角参数。比如一个带隙基准源你不用建三阶温度曲线但你要保证模型在 -40 ℃ 到 125 ℃ 范围内都能给出有效的输出值。具体的做法是把温度和视角作为模型的参数在验证环境中遍历参数用断言检查输出是否落在规格范围内。这个“模型带角带温”的策略比“一个参数走天下”要严谨得多又比全 SPICE 仿真快得多。我在实际项目里还吃过“corner 组合爆炸”的亏模型把 5 个模拟模块各 3 个 corner 全组合起来结果验证矩阵直接爆炸。后来改成只对最关键的电源模块做全组合 corner其他模块用典型角或边角包络矩阵规模才回到可控范围。5.3 团队协作与流程规范MSDV 落地到最后真正考验的是流程规范。我见过不止一个项目RNM 模型写得很好但因为没有明确的交付标准和 review 机制模型更新之后没人知道数字验证团队跑的还是老版本结果花了几周时间查一个已经修掉的 bug。我的建议是建立三层流程模型入库评审、集成验证报告、回归看护。模型入库评审管“模型符合不符合规范”包括精度是否校准过、参数是否带范围说明、端口命名是否符合命名规范集成验证报告管“模型在模块级环境里能不能跑通”要有波形截图、覆盖率摘要、已知问题清单回归看护管“模型升级没有破坏既有用例”通过 nightly regression 自动发现回归。这个流程不必做得很重关键是有个“模型负责人”角色。这个人不一定是模拟工程师但必须懂模拟行为和数字仿真的交互他有权限决定模型的视图切换和参数变更。有了这个明确的 ownerMSDV 的很多协作问题都能在源头解决。最后分享几个我踩过坑之后养成的实操习惯希望对你有帮助。第一写 RNM 模型之前先写一页“模型规格说明书”列清楚输入输出、功能行为、参数清单、已知近似再动手写代码。这个习惯帮我在很多项目里避免了“模型写完了但验证目标不清楚”的尴尬。第二Model 里的时间参数统一用localparam或 package 声明不要散落在各种魔数里。否则你后期想统一改精度或者调事件阈值会改到怀疑人生。第三搭 config 环境时留一只眼盯“视图 fallback”。只要你发现某个模拟模块在仿真里报出和 sim view 不匹配的信息立刻查 config 是不是被工具偷偷换成了默认 schematic view。第四不要为了性能和精度跟工具死磕。RNM 模型最大的价值不是把 SPICE 替换掉而是让混合信号验证能在数字仿真环境里被看见、被测量、被回归。把这一点想清楚很多建模取舍就自然有答案了。