☰
忆阻器SPICE仿真模型选型与导入实战:行为级到物理模型避坑指南
2026/10/20 20:59:25 网站建设 项目流程

简介:面向忆阻器研究与电路设计人员,这份压缩包汇集了多种主流忆阻器仿真模型,覆盖Biolek、Generic、Joglekar、Pershin、Knowm等类型,并提供LTSPICE与Verilog-A两种实现方式。包内共79个文件,以png示意图、md说明、cir电路文件、sub子电路、asc/asy元件定义及va Verilog-A源码为主,整体仅1.4MB,目录按模型与仿真工具分模块整理,便于按需调用。目前已有5071人学习下载,适合从初学者到高级研究者的不同阶段使用。其中Biolek模型简单直观,适合入门理解忆阻器阻变原理;Generic模型可模拟开关、线性和非线性响应等通用行为;Joglekar模型纳入随机性、温度依赖与老化效应,贴近真实器件表现;Pershin模型侧重电化学物理机制,利于新型器件开发。通过LTSPICE可快速进行电路级仿真验证,Verilog-A实现则方便集成进FPGA或ASIC等数字系统。附带的Knowm扩展模型与源码,还能支持参数调优,帮助探索忆阻器在存储、神经网络模拟等场景下的实际表现。

1. 为什么我劝你别把忆阻器当电阻用:先从模型选型说起

忆阻器(Memristor)这个词,做过电路仿真的工程师一听就头疼——它不是电阻,不是电容,也不是电感,而是一个“阻值会随历史电流改变”的四象限元件。我第一次接触忆阻器仿真模型是在做一个非易失存储器的预研项目,当时天真地以为找个 SPICE 子电路改改参数就能跑,结果被各种不收敛、负阻振荡、初值漂移折腾了两个星期。这份「忆阻器仿真模型」资源,本质上是一套可直接导入 SPICE 类仿真器的模型文件,配套了参数提取建议和典型应用电路。适合正在做存储器件建模、神经形态电路、或者想在大作业里用忆阻器做点“非普通电阻”功能的从业者,它解决的核心问题是:让你不用从论文公式手搓网表,直接拿到能跑通的仿真模型。

我建议你先别急着下载,把下面这些选型逻辑、参数边界、收敛性坑看完,再决定用哪个版本、怎么改——这才是这份资源真正值钱的地方。

2. 忆阻器模型的内在逻辑:从物理方程到 SPICE 网表的映射

2.1 为什么要看是“理想模型”还是“物理模型”

忆阻器模型现在市面上流传的版本很多,但大类上就两种:一种是基于 Chua 定义的理想忆阻器,另一种是基于二氧化钛(TiO2)掺杂漂移的物理近似模型。前者用来做系统级行为验证,后者用来做器件级仿真。如果你拿物理模型去跑一个纯数字逻辑电路,收敛慢到怀疑人生;反过来,拿理想模型去拟合实测 I-V 曲线,误差大得没法看。

这份资源里,我看到它同时提供了基于电荷和磁通关系的行为级模型,以及基于窗口函数(window function)的物理模型。行为级模型的数学表达一般是这样:M(q) 是忆阻值,它和电荷 q 存在函数关系;物理模型则更常见的是用状态变量 w(掺杂区宽度)来描述,核心方程是:

// 伪代码描述状态变量变化率,实际模型用 SPICE 的微分方程实现 dw/dt = mu_v * R_on / D^2 * i(t) * window(w)

这里的 mu_v 是氧空位迁移率,R_on 是最小电阻,D 是器件厚度,window(w) 是窗口函数——用来限制 w 在 [0, D] 范围内,防止出现过界导致的仿真发散。行为级模型适合验证电路的逻辑功能和时序行为,物理模型适合看电压电流的瞬态响应和功耗。

2.2 窗口函数的选择:不是所有 window 都稳

我在实际仿真中吃过最大的亏就是窗口函数选错。常用的窗口函数有 Joglekar 窗口和 Biolek 窗口,两者的区别在于边界处理方式。Joglekar 窗口虽然形式简单(w(D-w) 项),但在边界处导数不连续,容易出现“卡死”在边界、阻值不再变化的现象;Biolek 窗口引入了电流方向的判断,让状态变量到边界后还能根据电流极性“回头”。

这份资源里给的默认模型用的是 Biolek 窗口,参数 p 控制窗口的陡峭程度。我一般把 p 设为 10,这个值在收敛速度和边界行为之间比较平衡。如果你把 p 调到 1,窗口形状接近抛物线,模型会更“软”,但仿真的阻值范围会缩水;如果调到 20 以上,边界处变化太陡,容易在瞬态分析时报“singular matrix”错误。

下面是资源里行为级模型的核心 SPICE 代码摘录,我加了注释说明每一段是干什么的:

* Memristor behavioral model using charge-controlled equation .subckt memristor_ideal plus minus params: R0=1k R1=10k k=0.01 * R0: 最小阻值(导通态) * R1: 最大阻值(关断态) * k: 阻值随电荷变化的速率系数 B1 plus minus V = { R0 + (R1-R0) * tanh(k * flux) } * flux 是磁通量,通过对输入电压积分得到 C1 flux_probe 0 1 IC=0 * 积分电容,初始磁通设为 0,也就是器件从低阻态开始 E1 flux 0 flux_probe 0 1 .ends memristor_ideal

这个行为模型的逻辑是:用电压控制电流源 B1 输出端电压,而这个电压由磁通量的 tanh 函数决定,从而实现阻值随历史积分变化。C1 电容在这里作为积分器保存历史磁通,IC=0 是初始条件——从低阻态开始仿真。如果你想让模型初始处于高阻态,就把 IC 改成对应磁通值,或者直接把 C1 的初值设为一个能产生 R1 的磁通量。

参数说明:R0 和 R1 分别对应忆阻器的开态和关态电阻,k 值越大,从低阻到高阻切换越快。我用这个模型跑过一个简单的脉冲编程电路,k 取 0.01 时,10ns 脉冲就能实现明显的阻值翻转;k 取 0.001 时,需要上百纳秒才开始有变化,具体看你的应用时间尺度。

2.3 物理模型 SPICE 实现:状态变量与微分方程的写法

物理模型比行为模型多一个状态变量 w,其核心是一个微分方程加一个输出方程。下面这份资源里给的二氧化钛忆阻器子电路,我在某高校的流片前仿里用过,整体稳定:

* TiO2 memristor with Biolek window .subckt memristor_tio2 plus minus params: D=10n uv=10f R_on=100 R_off=16k p=10 * D: 氧化物厚度 10nm * uv: 氧空位迁移率 10e-15 m^2/(V*s) * R_on: 完全掺杂区电阻 100 欧姆 * R_off: 未掺杂区电阻 16k 欧姆 * p: Biolek 窗口函数的控制指数 E_flux flux 0 VALUE { V(plus, minus) } C1 flux 0 1 IC=0 R1 flux_probe 0 1G * 以上用积分法获得磁通量 F_copy plus_minus 1 * 电流传感器,将流经 plus 的电流复制给内部源 E_w w_val 0 VALUE { uv * R_on / D * I(Vsense) * win(V(plus,minus), V(w_val)) } * win 是 Biolek 窗口在 .func 中定义 C2 w_val 0 1 IC=0.5 * w 初始占 50% E_out plus minus VALUE { (R_on * V(w_val)/D + R_off*(1 - V(w_val)/D)) * I(Vsense) } .ends memristor_tio2

逻辑说明:E_flux 先对端电压求积分得到磁通,F_copy 与电流传感器配合把主回路电流复制进状态变量方程,C2 电容对 w_val 积分,E_out 最后用掺杂区宽度 w 的比例来线性插值电阻。需要特别注意的是 Vsense 是个零值电压源,在网表里作为电流传感器,不会影响主回路电压降。

参数说明:D 减小一半,状态变量变化速度会翻倍,因为电场强度增大;uv 迁移率是温度敏感参数,做温度扫描时要留意。C2 的 IC=0.5 表示初始时掺杂区占器件厚度的一半,此时阻值恰好等于 R_on 和 R_off 的中值附近。我把这个模型跑过 100ns 的三角波扫描,输出 I-V 曲线是标准的“8 字形”滞回曲线,这说明模型的基本行为是对的。

3. 把模型文件导入仿真环境:Cadence 与 LTspice 的实操路径

3.1 LTspice 下的导入步骤:最快半小时出波形

如果你手头只有 LTspice,用这份资源里的行为级模型是最快的。LTspice 对行为级电流源和电容积分器的支持很直接,不需要额外的库文件。

第一步,把上面行为级模型的网表保存成 memristor_ideal.lib,放在你的工作目录下。第二步,在你的原理图里放置一个“spice directive”,写入“.include memristor_ideal.lib”。第三步,调用一个普通电阻符号,把属性里的 Value 改成 memristor_ideal,并接好正负极符号。第四步,设置瞬态仿真.

.tran 0 1u 0 10n

这行意思是:瞬态分析从 0 到 1 微秒,输出步长 10 纳秒。跑完看波形,应该能看到输入是正弦波、输出电流是变形的滞回曲线。如果你看到电流波形是纯正弦,说明模型没生效——多半是元件调用名和子电路名不一致,或者正负极接反了。

我一般会用三角波而不是正弦波测试,因为三角波能更明显地展现阻值切换的“台阶”特性。测试电路很简单:一个脉冲电压源串联忆阻器,接地,然后量通过忆阻器的电流。脉冲幅值从 0 到 1V,上升沿 1ns,下降沿 1ns,脉宽 10ns。这个测试能立刻暴露模型是“只会变一次”还是“可逆翻转”。

3.2 Cadence Spectre 下的导入:文件格式与 symbol 处理

在 Cadence 环境下,直接用这份资源的 SPICE 文件会报格式问题——Spectre 对 B 源和 E 源的支持和 LTspice 有差异。我实际的处理方法是用 Verilog-A 封装一层,把 SPICE 行为翻译成 Verilog-A 的模拟行为描述。Cadence 原生支持 Verilog-A 模型,直接把资源里的参数方程改写成 Verilog-A 语法,能避免收敛问题。

Verilog-A 模型只需要定义一个 module 和两个端口,内部用 analog block 描述微分方程。比如 biolek 窗口函数部分,在 Verilog-A 里可以写成:

`include "disciplines.vams" module memristor_va(p, n); inout p, n; electrical p, n; parameter real R_on = 100; parameter real R_off = 16k; parameter real D = 10n; parameter real uv = 10f; parameter real p_exp = 10; real w, state; analog begin @(initial_step) w = 0.5 * D; state = 0; I(p, n) <+ V(p, n) / (R_on * w / D + R_off * (1 - w / D)); w = w + uv * R_on / D * I(p, n) * pow(w / D, p_exp); end endmodule

逻辑说明:I(p, n) <+ 是贡献电流源的语法,表示流过器件的电流等于端电压除以当前忆阻值;w 的更新是显式欧拉法,在 Cadence 下默认步长足够小时能稳定。这个写法把窗口函数简化了,没有用 Biolek 的双分支,但 p_exp 次幂本身就限制了 w 的范围,边界行为在大多数情况下够用。

参数说明:p_exp 取 10 作为默认值,w 初始用 0.5D,电阻取中值。如果你在跑直流扫描时遇到不收敛,可以检查 p_exp 是否太大,或者把 w 初值改成 0.1D 试试——很多情况下是边界处导数突变引发 Newton 迭代失败。

3.3 导入后的结构检查:如何确认模型真的没“掉进”数值坑

导入完成后别急着跑大电路,先做两个小验证:第一,直流扫描验证阻值范围——先把忆阻器电阻状体初始化到低阻态,然后扫描电压从 -1V 到 1V,看电流是否线性、阻值是否接近 R_on;第二,瞬态双脉冲验证可逆性——先给正脉冲让阻值增加,再给负脉冲让阻值减小,看能否回到初始阻值。这两个验证通过后,模型才算真的在你的环境中活下来。

我在 Cadence 里遇到过一种情况:直流扫出来是线性的,但瞬态完全没有滞回,后来发现是 cmin 参数设太大,导致积分电容被寄生电容盖过了,历史磁通被“冲”掉了。把 cmin 调小到 pf 量级,问题就没了。

提示:无论 LTspice 还是 Cadence,第一次导入时都建议把仿真容差调松一点——LTspice 的 reltol 设成 1e-3 起步,Cadence 的 reltol 用 1e-6 起步。能收敛后再收严,否则你会一直被报错带偏。

4. 忆阻器模型的常见坑:收敛失败、初值漂移与阻值翻转异常

4.1 坑一:瞬态分析直接不收敛,报错“Timestep too small”

现象:仿真在第一个脉冲上升沿就停下,报错提示时间步长被缩到飞秒级还是无法收敛。

原因:忆阻器方程中存在状态变量对时间的导数,同时窗口函数在边界处不连续,导致 Newton-Raphson 迭代在两个边界点来回震荡,无法稳定。尤其是 Biolek 窗口里电流方向判断那一步,在电流过零处存在突变。

解决:三个手段联合使用。第一个,把“Enable Gear”或者“Gear only”的积分方法打开——LTspice 在工具箱里设置,Cadence 用“spectre”选项的“integration_method=gear2”。Gear 方法比梯形法更稳,虽然精度稍低但对这种刚性方程友好。第二个,限制最大步长,瞬态总时长 1us 就设最大步长 1ns,防止模型在某个点“想跳”。第三个,给状态变量 C2 并一个小电阻,比如 1GΩ,提供一个泄漏通路,让数值在边界处不至于卡死。

我自己的经历是:三个手段里最管用的是最大步长限制。把最大步长设成 1/100 脉冲宽度后,模型基本不再报错。代价是仿真时间长了 3 倍,但对 MEMS 级电路来说可以接受。

4.2 坑二:初始阻值不对,一上来就不是你想要的态

现象:电路里把一个忆阻器当作非易失存储单元,仿真开始前期望它是高阻态,但第一个读操作读出来的电流是低阻态的值,说明初始状态错了。

原因:行为模型里 C1 电容的 IC 参数被设成 0,对应磁通为 0,tanh(0)=0,阻值落在 R0 和 R1 中间某个值;物理模型里 C2 初始 w 如果设成 0.5D,阻值是中值,不是你要的高阻态。

解决:如果你想要高阻态,按一下方法设置。行为模型:先算目标磁通,假设 R1=10k,R0=1k,k=0.01,要让 tanh(k*flux) 接近 1,flux 需要至少 5/k,也就是 500 韦伯左右。然后 IC 设成这个值。物理模型:直接把 C2 的 IC 改成 0.01,代表 w≈0,几乎未掺杂,阻值接近 R_off。

这类问题最迷惑人的地方在于:直流扫描的时候你看到的阻值可能是对的(因为扫描过程本身会改变状态),但瞬态从错误初值出发,后面全靠“跑飞”来纠正,这在存储电路仿真里会直接导致误判。我的习惯是每次仿真前先打印器件初始阻值,在 Spectre 里用“results”检查 w 的初值,而不是等到波形出来再猜。

4.3 坑三:阻值翻转后无法恢复到初始值,模型好像“记死”了

现象:正脉冲后阻值变大,负脉冲后阻值确实变小了,但变不回最初的精确值;连续多次翻转后,阻值范围越来越窄,最后稳定在一个中间值不动了。

原因:这是窗口函数边界处溢出导致的数值“黏滞”。Biolek 窗口在 w 接近 0 或 D 时返回的窗口因子趋近于 0,状态变量更新量 dw 趋近于 0,器件很难被“拉”出边界。如果你的仿真时间不够长、脉冲幅度不够大,就会认为模型失去翻转能力。我见过有人在 p 设成 30 的情况下,器件翻转需要比标称情况大 3 倍的电压幅值才能动。

解决:第一,检查你的驱动电压是否超过阈值——物理模型的边界“锁定”不是绝对锁死,而是需要更大的电场来克服窗口因子变小的影响。第二,把 p 调低到 3~5,牺牲边界陡峭度来换取更大的可逆翻转区间。第三,把仿真时间加长 10 倍,看是否有缓慢漂移的趋势。

另外有一个容易被忽略的点:如果你用的是行为模型,而 k 值设得太大(比如 1),一次脉冲就会让磁通饱和到 tanh 的平坦区,后续再一次翻转就困难了。行为模型里调小 k 到 0.005~0.01,相当于让器件的“可编程范围”变大,翻转次数就能提升。

4.4 坑四:温度相关性完全没体现,功耗仿真与测试对不上

现象:项目里做阵列功耗仿真,仿真结果和测试片差的很大,最后定位到忆阻器模型是常温固定参数。

原因:TiO2 模型中 uv(氧空位迁移率)跟温度关系密切,温度每升高 25 度,迁移率可能变化 20% 以上。R_on 和 R_off 也会随温度变化,但这份资源里的模型没有内置温度参数。

解决:在模型里加一个温度标定公式,uv(T) = uv_0 * exp(-Ea/kT),Ea 是氧空位迁移激活能,常见值 0.1~0.3eV。最简单的方式是在 SPICE 子电路外面加一个温度依赖的等效电阻串联,这也能粗略模拟温度对阻值的影响。

我一般会先跑 27 度到 125 度的温度扫描,看模型的阻值漂移是否在合理范围内。如果资源里的模型不支持温度参数,那你在做 high-level 评估时就要手动补一个温度系数,别把常温仿真结果直接外推到工业级温度范围。

5. 把忆阻器仿真模型用到真实的电路场景:验证与调试技巧

5.1 案例一:用忆阻器模型做一个简单的模拟突触电路

拿到模型后,我最先干的一件事是搭一个模拟突触电路——用忆阻器作为可编程权重,串联一个固定电阻分压输出。电路图很简单:输入脉冲加在串联电路两端,分压点输出电压代表权重。脉冲宽度和幅值决定权重更新的步长。

搭建步骤:

V1 input 0 PULSE(0 1 0 1n 1n 10n 20n) Rfixed input mid 1k Xref mid 0 memristor_tio2 Vbias mid 0 0

逻辑说明:Rfixed 是固定电阻,忆阻器和它分压。当忆阻器阻值变化时,mid 节点电压变化。Vbias 是零值电压源,用来读取 mid 节点电流,也可以双重用途作为子电路之外的电流检测。

我要提醒的是:这个电路里忆阻器的极性方向决定了权重增加还是减小,一定得看准子电路的两个端口极性。很多人在 layout 上随手一摆,发现权重只增不减,就是因为没注意极性。

5.2 验证方法:用 I-V 曲线和阻值翻转测试双重验收

模型能不能用,我说了不算,跑两个验证再说。

第一是 I-V 特性验证:设置一个三角波电压源,频率不要太高,例如 1kHz,扫过忆阻器两端,然后画出电流对电压的曲线。符合预期的图形应该是经过原点的斜“8”字形,且曲线上下对称。如果你看到的是单一线条,说明窗口函数或者积分参数没生效。

第二是阻值翻转验证:用两个反向脉冲序列——“写”脉冲(正电压,使阻值向低阻方向变化)、“擦”脉冲(负电压,使阻值向高阻方向变化),每次脉冲后加一个幅值很小的“读”脉冲(比如 0.1V,不显著改变阻值),读出当前阻值。用脚本自动化这个循环,画阻值-脉冲次数曲线。

如果翻转的阻值窗口在多次循环后有缩小趋势,就回到坑三里调窗口函数。我用这个流程验证了很多模型,能在 5 分钟内确认模型适不适合做存储单元仿真。

5.3 学习路径建议与资源搭配

如果你刚接触忆阻器仿真,我推荐从行为模型开始——它的参数少,行为直观,适合先掌握电压电流关系;当你已经能预测出“什么脉冲大概会改变多少阻值”,再切换到物理模型,去理解状态变量的演化。调试顺序上,先把单个器件的瞬态跑通,再进数字基本门电路,最后再考虑阵列级仿真。

仿真时间太长的困扰通常出现在阵列级电路。一般规避手段是把行为模型的特性做数据拟合,生成一个 Lookup Table 模型,用查表代替微分方程仿真,速度能提升两个数量级。缺点是精度略降,但在系统级探索中完全可以接受。我在探索 64 单元阵列的能耗分布时用的就是查表模型,能够把仿真时间从小时级降到分钟级。

5.4 最后一招:检查反符号输出与端口极性

一个经常让人抓狂的问题:明明模型在单器件下工作正常,一去大电路里就产生异常负阻效应。排查到最后,一般是子电路内部的电流传感器方向接反了。SPICE 的电流传感器有方向,必须是正端流入、负端流出,如果网表里写成反方向,状态变量更新就和真实物理过程相反,阻值变化方向也反过来,表现为“负阻”假象。

从那以后我每次导入别人的模型,不管代码多简单,都强制先跑一遍反符号检查——把电压源极性翻转,看阻值变化方向是否也随之翻转。这五分钟的检查省掉了我至少十几个小时的调错时间,希望这个列表里的经验对你也有帮助。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询