尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

忆阻器与MATLAB仿真:从HP模型到滞后回线复现

忆阻器与MATLAB仿真:从HP模型到滞后回线复现 简介忆阻器作为一种具有非易失性记忆功能的电子元件其电阻值会随历史电流变化并保持这种特性使其在数据存储、神经网络模拟与高速计算领域潜力巨大。这份MATLAB仿真资料面向电子工程、微电子及AI方向的初学者和研究者旨在帮助理解忆阻器工作原理与V-I特性快速上手仿真分析。包内共2个文件包含1个PDF文档和1个MATLAB脚本PDF系统讲解忆阻器的物理机制与数学模型脚本可直接运行以绘制忆阻器V-I曲线压缩包仅1.17MB轻量便携。已有1999人学习下载适合配套学习。通过该资料读者可掌握电导突变材料的基本原理、电压-电流关系式的建模方法了解阈值电压等关键参数的影响并借助仿真代码观察线性区与非线性区的曲线差异为后续探索ReRAM、忆阻计算或神经网络模拟奠定基础。1. 忆阻器与MATLAB仿真先跑出一条滞后回线再说忆阻器Memristor是1971年蔡少棠从电路变量对称性出发补全的第四种基本元件直到2008年惠普实验室用TiO2薄膜做出实物才算真正落地。这些年它频繁出现在ReRAM存储、神经形态计算和可编程射频设计里但很多人第一次接触都卡在同一件事上原理看得懂一写仿真就翻车。这篇笔记就是来拆这个问题的。我基于一个可直接运行的MATLAB建模包从HP模型的物理方程讲起把状态变量微分方程、窗口函数、正弦激励参数、串并联电路和参数拟合全部跑通最终目标是让你亲手复现一条压着原点、方向正确的I-V滞后回线。适合要做忆阻器课题的在校生、ReRAM预研工程师以及想用MATLAB把论文结果复现一遍的从业者。全文脚本不需要额外工具箱R2019b之后的版本直接跑。2. 忆阻器工作原理与数学模型从Chua缺失论到HP状态方程2.1 Chua的对称论证电路里一直缺一个元件电路理论里有四个基本变量电压v、电流i、电荷q、磁通φ。四个变量两两组合理论上可以得到六种关系。电阻、电容、电感分别覆盖了其中三种剩下三种里有两个是定义性的——v和q的关系、i和φ的关系其实可以从其他式子推出来真正缺的只有电荷q与磁通φ之间的约束。Chua在1971年那篇《Memristor - The Missing Circuit Element》里的核心论证就是这个既然dqdφ这种组合方式在物理上没有被禁止那必然存在一个二端元件它的阻值不是常量而是由过去流经它的电荷总量决定这就是忆阻器。这个元件的定义式很干净荷控型满足φ(t)f(q(t))磁控型满足q(t)g(φ(t))。如果写成电压电流形式端电压v M(q)·i其中M(q)dφ/dq单位是欧姆但M随时间变化变化的驱动力是电荷的历史积分。注意这跟普通可变电阻有本质区别可变电阻由外部信号控制忆阻器的阻值由自身流过的电荷历史决定而且断电后这个阻值会保持住——这是后来ReRAM能当非易失存储用的物理基础。我看过不少初学者在这里被绕进去觉得不就是一个受控电阻吗。其实关键差异在于状态变量。忆阻器内部天然带一个记忆变量这个变量不能由当前时刻的电压电流直接解出必须靠微分方程累积。你在SPICE里搭个JFET也能模拟可变电阻但要复现断电保持阻值和压点回线这两个特征拉扎维书上那套小信号模型做不到。所以搞清楚状态变量这个思路比背定义重要得多。2.2 HP TiO2模型一个状态变量x就够了2008年HP实验室的器件结构可以简化为三层铂电极、掺杂区TiO2-x、未掺杂区TiO2中间夹着氧空位。掺杂区因为氧空位浓度高电阻率低未掺杂区接近绝缘体电阻率高。整个器件等效成两个电阻串联而掺杂区的厚度w会随流过电流移动。建模时用x表示掺杂区厚度占器件总厚度的比例xw/D取值范围[0,1]。总电阻写成R(x) Ron·x Roff·(1-x)x0时器件处于高阻态阻值Roffx1时处于低阻态阻值Ron。两端电压和电流的关系就是v R(x)·i看起来像欧姆定律但R(x)会动。状态演化方程是HP模型的核心dx/dt μv·Ron/D² · i(t) · f(x)其中μv是氧空位迁移率单位m²/(V·s)它的物理含义是氧空位在电场下的漂移速度Ron/D²把迁移率换算成对掺杂区边界移动的驱动强度i(t)是流过器件的电流f(x)是窗口函数负责把x的演化约束在[0,1]区间内。这个方程的形式很直观电流越大边界移动越快x越接近边界窗口函数压得越狠移动越慢。这个模型的妙处在于它把复杂的离子迁移物理全部压缩成一个一阶常微分方程。你不用解泊松方程不用管温度场只要给定初始x0和外部激励就能算出任意时刻的阻值和端电压。代价是精度有限HP模型在x接近边界时和实测偏差较大但作为教学和预研仿真完全够用。参数取值方面HP论文里的标称值大概是Ron100ΩRoff16kΩD10nmμv≈1e-14 m²/(V·s)。算一下状态方程增益kμv·Ron/D²≈1e4 A⁻¹s⁻¹这个量级下器件在纳秒级就能完成状态翻转。做物理仿真没问题但如果你想在MATLAB里用秒级正弦激励画一条漂亮的滞后回线这个k值会让你什么都看不见——一个1mA的正弦电流x在几毫秒内就冲到边界锁死了。所以我在下面的仿真里把μv缩放到1e-15k变为1000 A⁻¹s⁻¹这是教学演示里最常见的做法工作机制完全保留只是时间尺度放慢了。2.3 窗口函数边界护栏也最容易埋坑窗口函数f(x)不是物理必然是为了数值稳定和保护边界引入的数学约束。没有它x的微分方程会直接把x推出[0,1]得到负电阻或者超过物理极限的阻值仿真结果直接废掉。常见的有三种窗口函数表达式特点边界行为Strukovf(x) x(1-x)形式最简单x0.5时f最大x到0或1时f0状态锁死Joglekarf(x) 1-(2x-1)^(2p)p控制平台宽度p越大中间越平坦x到边界时f0同样会锁死Biolekf(x) 1-(x-stp(-i))^(2p)带电流方向符号边界可逆电流反向时能从边界拉回来三种窗口我都在MATLAB里跑过对比。Strukov窗口写起来就一行x(1-x)我第3章的入门仿真默认用它因为它能让回线形状最干净。但它有个致命问题x一旦撞到0或1f(x)0状态导数变零之后无论电流方向怎么变x都死死的钉在边界上不回来。这在物理上说不通——真实器件的氧空位是可以被反向电场拉回去的。Joglekar窗口做了平滑处理但边界锁死问题依然存在。Biolek窗口引入了电流方向的符号项x在边界时如果电流方向是往内的f会重新大于零状态能恢复。根据你实际用的模型选窗口我的经验是做机理演示用Strukov够了做脉冲编程和擦除循环必须用Biolek否则擦除操作在x接近0或1时完全失效做定量参数标定建议直接跳过窗口函数用带边界约束的数值方法处理后面第5章会展开讲这个坑。3. MATLAB建模实操ODE45复现HP模型并画出滞后回线3.1 主脚本与状态函数十来行代码跑通单器件仿真我习惯把模型参数、激励信号、求解器三件事分开写。模型参数单独放在主脚本顶部激励信号用匿名函数传给ODE45状态方程写成一个独立的函数文件这样后面换参数、换激励、并联多个器件时都不用改函数本身。% memristor_hp_demo.m HP忆阻器单器件仿真 % MATLAB R2019b及以上可直接运行无需额外工具箱 clear; clc; close all; % ---------- 器件参数 ---------- Ron 100; % 低阻态电阻单位欧姆 Roff 16000; % 高阻态电阻单位欧姆 D 10e-9; % 器件厚度单位米 muV 1e-15; % 缩放后的氧空位迁移率m^2/(V*s) k muV * Ron / D^2; % 状态方程增益约1000 A^-1 s^-1 x0 0.5; % 掺杂区初始占比取中间值避免边界锁死 % ---------- 正弦电流激励 ---------- Amp 1e-4; % 电流幅值 0.1mA freq 1; % 激励频率 1Hz tspan [0 2]; % 仿真2秒跑两个完整周期 % ---------- 求解状态变量 ---------- [t, x] ode45((t,x) hp_strukov_rhs(t, x, k, Amp, freq), tspan, x0); % ---------- 由状态计算电压电流 ---------- i Amp * sin(2*pi*freq*t); R Ron * x Roff * (1 - x); % 时变电阻 v R .* i; % 端电压 % ---------- 绘图 ---------- figure(Color,w,Position,[100 100 800 900]); subplot(3,1,1); plot(t, x, LineWidth, 1.5); ylabel(x w/D); grid on; title(状态变量随时间演化); subplot(3,1,2); plot(t, R, LineWidth, 1.5); ylabel(R (ohm)); grid on; title(忆阻值随电荷历史变化); subplot(3,1,3); plot(v, i*1000, LineWidth, 1.5); xlabel(电压 (V)); ylabel(电流 (mA)); grid on; title(I-V 滞后回线 (pinched hysteresis loop));function dx hp_strukov_rhs(t, x, k, Amp, freq) % HP模型状态方程Strukov窗口 % t: 时间x: 掺杂区占比k: 状态方程增益 % Amp, freq: 正弦电流源的幅值与频率 i Amp * sin(2*pi*freq*t); f x * (1 - x); % Strukov窗口函数 dx k * i * f; end代码逻辑分三层第一层是参数定义Ron和Roff决定阻值范围muV决定状态演化速度x0必须取中间值原因下面讲第二层是ODE45求解状态变量注意匿名函数把k、Amp、freq三个参数直接捕获进函数句柄没有用全局变量这是MATLAB推荐的参数传递方式也是后面换参数不出玄学问题的关键第三层是后处理用x算R用R算v然后画图。跑完这个脚本你会看到第三张图是一条过原点、关于原点对称的滞后回线这就是忆阻器区别于普通电阻的最重要特征。如果回线没有闭合检查tspan是不是整数倍周期如果回线变成一条直线检查Amp和k的量级下面3.2专门讲这个。3.2 激励信号怎么选频率和幅值决定回线胖瘦状态方程dx/dtk·i·f(x)说明x的变化量本质上是电流对时间的积分。频率越高每个周期内注入的电荷越少x的波动幅度就越小回线就越窄。我在2.2参数表里算过k1000时0.1mA、1Hz的正弦激励下x在每个周期的摆幅大约0.03两个周期累计0.06左右回线宽度刚好肉眼可见。频率的选择有一个粗略估算公式Δx≈k·Amp/(π·freq)。注意这个式子是忽略窗口函数非线性后的一阶近似只适合用来估算量级。如果Δx算出来小于0.01回线窄得几乎贴着一条直线视觉上跟线性电阻没区别如果Δx大于0.5x会频繁撞边界回线顶部和底部变成平头形状失真。激励频率Δx估算预期回线形态0.2 Hz0.16回线较宽x摆幅大接近边界1 Hz0.032回线清晰形状规整5 Hz0.006回线很窄接近直线20 Hz0.0015几乎看不见滞回幅值的作用类似Amp越大速度越快但撞边界的概率也越高。我的习惯是先定频率再调Amp保证Δx落在0.03到0.15之间然后跑一遍看x(t)的曲线如果x的极值接近0.05或者0.95就把Amp减半再试。硬要记住一句话回线的面积和形状本质上是激励与状态方程之间的时间常数匹配问题跟你在示波器上看到的真实忆阻器行为是一致的。3.3 三张图一起看状态、电阻与回线要相互印证很多人在第3.1节跑出滞后回线就收工了这是不够的。I-V回线只能告诉你有滞回但没法告诉你x有没有撞边界、Roff和Ron有没有被完全扫描到。所以我把三张图放在同一个figure里第一张看x(t)的演化轨迹确认始终在(0,1)区间内第二张看R(t)确认阻值在Ron和Roff之间平滑变化第三张才看I-V回线确认压点、对称、环的方向。第三张图的方向判断有个技巧看回线是顺时针还是逆时针缠绕。正向扫描时如果电流增大但电压比下降支路低说明阻值在变小状态演化方向正确如果方向反了多半是状态方程里符号写错或者电流源极性定义反了。这个问题我在第5章的5.5条详细讲。提示如果跑出来回线关于原点对称、穿过原点、闭合良好并且x(t)始终在(0,1)内这次仿真基本可信。三个条件缺一个先查激励再查窗口函数最后查k的符号。4. 从单器件走向电路串并联等效、脉冲编程与状态读取4.1 串联两个忆阻器不能用一个等效R骗自己单器件跑通之后下一步自然就是串并联。这里有个新手必踩的坑以为两个忆阻器串联可以等效成一个固定电阻R1R2。不对两个忆阻器串联时每个器件的状态变量独立演化总电压是两者分压之和但电流是共同的所以状态方程是二维的。% memristor_series.m 两个忆阻器串联仿真 % 状态向量 x [x1, x2]分别对应两个器件的掺杂区占比 k 1000; % 状态方程增益 Amp 1e-4; % 电流幅值 freq 1; % 频率 tspan [0 2]; x0 [0.3; 0.7]; % 两个器件初始状态不同 [t, x] ode45((t,x) series_rhs(t, x, k, Amp, freq), tspan, x0); R1 100*x(1) 16000*(1-x(1)); R2 100*x(2) 16000*(1-x(2)); Rtotal R1 R2; i Amp * sin(2*pi*freq*t); v1 R1 .* i; v2 R2 .* i; figure(Color,w); subplot(2,1,1); plot(t, x, LineWidth, 1.5); legend(x1,x2); ylabel(x); grid on; title(两个器件状态各自演化); subplot(2,1,2); plot(v1v2, i*1000, LineWidth, 1.5); xlabel(总电压 (V)); ylabel(电流 (mA)); grid on; title(串联总I-V回线);function dx series_rhs(t, x, k, Amp, freq) % 串联流过两个器件的电流相同 i Amp * sin(2*pi*freq*t); dx zeros(2,1); dx(1) k * i * x(1) * (1 - x(1)); dx(2) k * i * x(2) * (1 - x(2)); end并联的情况类似但每个器件的电流不同需要先算出总电压再分流。这两个例子说明一个工程问题在crossbar阵列里不能像普通电阻网络那样直接做网络化简每个忆阻器节点都要保留独立的状态量。这也是为什么大阵列仿真通常用SPICE而不是纯MATLAB脚本MATLAB脚本的强项是单器件到几十个器件的教学和算法验证。4.2 脉冲编程与擦除ReRAM写入/擦除的标准操作忆阻器的应用场景里脉冲编程是最典型的操作。写脉冲用正电压把器件从高阻态往低阻态推擦脉冲用负电压把器件从低阻态拉回高阻态。第2章的HP状态方程是以电流为驱动量的电压源激励时需要先根据当前x算出R再算出电流iv/R然后代入状态方程。这个过程不需要解隐式方程因为R只是x的显式函数。% pulse_write_erase.m 正负脉冲编程与擦除循环 Ron 100; Roff 16000; k 1000; t_pulse 0.1; % 脉冲宽度 100ms V_write 3.0; % 写电压 V_erase -3.0; % 擦电压 V_read 0.2; % 读电压越小越好 t_read 0.02; % 读脉冲宽度 20ms n_pulses 20; % 写/擦循环次数 R_log zeros(n_pulses*2, 1); x 0.5; for n 1:n_pulses % 写脉冲 p [k, Ron, Roff, V_write]; [~, x] ode45((t,x) hp_voltage_rhs(t,x,p), [0 t_pulse], x); R_log(2*n-1) Ron*x Roff*(1-x); % 擦脉冲 p [k, Ron, Roff, V_erase]; [~, x] ode45((t,x) hp_voltage_rhs(t,x,p), [0 t_pulse], x); R_log(2*n) Ron*x Roff*(1-x); end figure(Color,w); plot(R_log, o-, LineWidth, 1.2); xlabel(操作序号); ylabel(电阻 (ohm)); grid on; title(写脉冲降低阻值擦脉冲升高阻值);function dx hp_voltage_rhs(t, x, p) % 电压源激励下的HP状态方程 % p [k, Ron, Roff, V] k p(1); Ron p(2); Roff p(3); V p(4); R Ron*x Roff*(1-x); % 当前电阻 i V / R; % 由电压源和当前电阻算电流 f x * (1 - x); % Strukov窗口 dx k * i * f; end跑完这个脚本你会看到阻值波形是一个阶梯状交替序列写脉冲把阻值往下压擦脉冲把阻值往上抬n_pulses越大两个状态越稳定。如果把写脉冲改成不同的幅值序列阻值可以停在中间态这就是多级存储的仿真基础。脉冲宽度的选择要跟k和电压匹配。在上面的参数下100ms、3V的写脉冲把x从0.5推到0.65左右阻值从8kΩ降到大约5.5kΩ。如果发现一次脉冲后阻值几乎没变检查k需要调大还是t_pulse需要加宽公式是Δx≈k·(V/Ravg)·t_pulse·f(x)拿这个估算再决定。4.3 状态读取用小信号电压不打扰记忆读取操作的目标是测出当前阻值但不能改变它。实操上有两种常见做法一是加一个远小于写电压的直流小电压比如0.1V以下测量稳态电流二是加一个极窄的读脉冲脉冲面积V·t足够小让x的变化量低于可接受阈值。我对读取脉冲的量化标准是一次读取造成的Δx要小于0.001。以上面代码里的参数0.2V、20ms的读脉冲造成的Δx≈1e-4这个量级连续读十次也不会有可观测的状态漂移。如果读脉冲太大你测到的是被改写过的状态这在真实ReRAM芯片里就是读干扰问题仿真阶段就能发现这个坑。这里有个细节值得注意读取操作结束后器件的阻值会略有变化这在循环读写测试中会累积。真实芯片往往需要在读后加一个补偿脉冲把状态拉回去MATLAB仿真里可以用同样的方式验证补偿逻辑是否有效。5. 避坑与常见问题五条亲测防翻车记录这套仿真看着简单参数一动就翻车。下面五条是我自己踩过、也帮人排过的典型问题按现象→原因→解决的顺序写。5.1 状态锁死在边界回线从环变成半条线现象仿真跑了一两个周期后x(t)曲线变成一条直线贴在0或1上I-V回线从闭合环退化成一个半圆或直线段。原因Strukov窗口函数f(x)x(1-x)在x0或x1时等于零状态方程右边的驱动力消失。此时如果外部电流方向是往边界压的x就永远停在那里回不去。这是HP模型加Strukov窗口的固有缺陷不是求解器的问题。解决换Biolek窗口它带电流方向符号边界处电流反向时f会重新大于零状态能拉回来。如果坚持用Strukov避免x撞边界的唯一办法是控制激励幅度和仿真时长保证x的峰值在0.05到0.95以内。我一般把x的上下限设成预警值在绘图脚本里加个判断x超出区间就直接报警不等到回线变形才发现。5.2 初始状态取0或1回线永远出不来现象x0设成0跑完v-i图是一条完美的过原点直线完全没有滞回。原因HP模型的状态方程里x0或x1时窗口函数f(x)0初始状态本身就落在锁死点上微分方程的右端恒等于零x根本不会动。解决x0取0.3到0.7之间。我默认取0.5这是阻值落在Roff和Ron正中间的位置回线上下形状对称。如果你需要仿真一个已经处于低阻态的器件别直接把x0设成1设成0.99或0.97留一点演化空间。同理高阻态用0.01而不是0。5.3 回线变成一条直线频率和增益不般配现象x0取0.5k和Amp都看起来正常但v-i图就是一条过原点的直线面积几乎为零。原因状态演化速度远小于激励周期x在一整个激励周期内的波动幅度趋近于零R(x)几乎不变。对照2.2节那个估算式Δx≈k·Amp/(π·freq)如果算出来Δx小于0.01就是这个情况。解决提高k或Amp降低freq。实操时先不动其他参数只把频率从1Hz改成0.5Hz观察回线是否变宽。如果变宽了说明频率匹配问题如果还是直线查k的量级常见问题是把muV少乘了几个数量级导致k只有个位数。反过来回线变得像一个大方框、顶底平坦说明撞边界了需要降低Amp。5.4 ODE45发散或数值爆炸现象警告窗口弹出Failure at t...或者x值变成大于10的荒谬数字v-i图出现螺旋状乱线。原因数值溢出通常由两种问题引发。一种是x被推出[0,1]后Strukov窗口f(x)x(1-x)变成负值状态方程右端符号反转形成正反馈另一种是激励信号频率远高于状态方程的时间常数ODE45自动步长失控。解决在窗口函数入口做钳位这是最保险的function f window_strukov_safe(x) x min(max(x, 0), 1); % 钳位到[0,1] f x * (1 - x); end同时给ODE45设置刚性求解器选项options odeset(RelTol,1e-6,AbsTol,1e-8);。HP状态方程本身不刚性但窗口函数在边界附近的陡峭变化会让非刚性求解器吃步长遇到警告直接用ode15s替换ode45通常是最后手段也是最快解决手段。5.5 回线方向反了或形状不对称现象I-V回线的旋转方向跟论文里的相反或者上下两个半环不对称、一个胖一个瘦。原因旋转方向反了基本是符号问题。检查状态方程里i的符号或者外部激励电流源的正方向定义。上下不对称的原因分两种一是x0不取0.5导致正半周和负半周的演化速度不一致二是电压源激励下R(x)在高低阻态下的电流差异导致状态变化速率天然不对称这是物理模型本身的特性不一定是错。解决先做符号检查把激励幅值调大、频率调低让x的摆幅达到0.2以上然后观察x(t)曲线。如果x的正向变化量和负向变化量差异超过10%检查k的符号和窗口函数如果x对称但回线不对称那就是器件本身电阻值范围不对称带来的需要在论文或者报告里解释清楚不要强行修正。提示遇到回线形态异常我的排查顺序永远是先看x(t)曲线再看R(t)曲线最后看I-V回线。x曲线的异常原因通常直接指向参数跳过前两步直接看回线容易被形状误导。6. 进阶从实测I-V回线反推模型参数的拟合技巧6.1 最小二乘拟合k和x0前面的仿真都是给定参数观察现象实际工程里往往是反过来的——你有一组实测的I-V回线数据想反推器件的k、Ron、Roff和初始状态x0。做法是把ODE45封装成一个黑匣子函数输入参数向量p输出仿真回线然后跟实测数据做最小二乘。% fit_memristor.m 从实测I-V回线拟合HP模型参数 % p [k, Ron, Roff, x0] meas load(iv_measured.mat); % 实测数据包含v_meas, i_meas cost (p) sum((sim_iv(p, meas.i) - meas.v).^2); p0 [1000, 100, 16000, 0.5]; p_lb [100, 10, 1000, 0.1]; p_ub [10000, 1000, 100000, 0.9]; p_opt fmincon(cost, p0, [], [], [], [], p_lb, p_ub); disp(p_opt);sim_iv函数内部就是第3章的ODE45仿真流程输入电流波形i_meas输出对应电压v_sim。四个参数里k和x0对回线形状影响最大Ron和Roff影响回线在高低阻态的饱和值四个参数存在一定耦合所以要用边界约束而不是纯无约束优化。实测数据如果来自真实器件建议先做一次平滑滤波测量噪声会让梯度计算失真拟合结果不稳定。这里我不贴完整脚本因为sim_iv的接口取决于你的数据格式但核心就是ODE45当黑匣子用fmincon做有界优化这一句话。6.2 回线方向与压点验证拟合完成后验证工作比拟合本身更重要。我每次都会做三个检查回线是否穿过原点、旋转方向是否和实测一致、回线面积是否随频率增大而减小。第三个检查是忆阻器的指纹特征线性电阻和普通非线性电阻都不具备这个性质。如果拟合结果回线面积随频率增大的方向反了说明模型的时间常数和实测器件对不上优先怀疑muV的量级偏差。我最后一次做忆阻器参数拟合时卡了一个下午拟合出来的回线形状总是不对称最后发现是实测数据的电流探头方向接反了整个数据集极性反相。从那以后每次拿到新的I-V实测数据第一件事就是先画出原始曲线确认回线方向再做参数拟合绝不直接丢进优化器。希望帮到你。本文还有配套的精品资源点击获取
返回列表