【工业工艺与设计 电子】MOS仿真+ Falstad 仿真器实现(circuitjs1-MosfetElm.java)+Level-1/Shichman–Hodges模型+体二极管仿真
建模
-
截止区(Cutoff) V G S < V T V_{GS}<V_T VGS<VT
- MOSFET未形成沟道。仿真器不能让器件完全开路,否则矩阵奇异。
Gds = 1e-8;ids = vds*Gds;等效 R ≈ 100 M Ω R \approx 100M\Omega R≈100MΩ
- MOSFET未形成沟道。仿真器不能让器件完全开路,否则矩阵奇异。
-
线性区(Triode / Linear): V D S < V G S − V T V_{DS}<V_{GS}-V_T VDS<VGS−VT
-
漏极电流 对应公式: I D = β [ ( V G S − V T ) V D S − V D S 2 2 ] I_D=\beta \left[ (V_{GS}-V_T)V_{DS} -\frac{V_{DS}^2}{2} \right] ID=β[(VGS−VT)VDS−2VDS2]
-
此时: g m = ∂ I D ∂ V G S = β V D S g_m=\frac{\partial I_D}{\partial V_{GS}} =\beta V_{DS} gm=∂VGS∂ID=βVDS
-
G d s = ∂ I D ∂ V D S = β [ ( V G S − V T ) − V D S ] = G d s = β ( V G S − V T − V D S ) G_{ds}=\frac{\partial I_D} {\partial V_{DS}} =\beta \left[ (V_{GS}-V_T)-V_{DS} \right]=G_{ds}=\beta (V_{GS}-V_T-V_{DS}) Gds=∂VDS∂ID=β[(VGS−VT)−VDS]=Gds=β(VGS−VT−VDS)
-
-
饱和区(Saturation): V D S ≥ V G S − V T V_{DS}\ge V_{GS}-V_T VDS≥VGS−VT
-
I D = β 2 ( V G S − V T ) 2 I_D=\frac{\beta}{2}(V_{GS}-V_T)^2 ID=2β(VGS−VT)2 经典的长沟道 MOSFET 饱和区方程。
-
此时 : g m = ∂ I D ∂ V G S = β ( V G S − V T ) g_m=\frac{\partial I_D}{\partial V_{GS}}=\beta(V_{GS}-V_T) gm=∂VGS∂ID=β(VGS−VT)
-
此时: G d s = 0 G_{ds}=0 Gds=0,为了防止迭代求解发散,另 G d s = 1 e − 8 G_{ds}=1e^{-8} Gds=1e−8,相当于 100 MΩ 的巨型电阻
-
求解非线性方程
- I D ( V G S , V D S ) I_D(V_{GS},V_{DS}) ID(VGS,VDS) 在当前工作点附近展开:
I D ≈ I D 0 + g m Δ V G S + G d s Δ V D S I_D \approx I_{D0} + g_m\Delta V_{GS} + G_{ds}\Delta V_{DS} ID≈ID0+gmΔVGS+GdsΔVDS
I D = I D 0 + g m ( V G S − V G S 0 ) + G d s ( V D S − V D S 0 ) I_D= I_{D0}+g_m(V_{GS}-V_{GS0})+G_{ds}(V_{DS}-V_{DS0}) ID=ID0+gm(VGS−VGS0)+Gds(VDS−VDS0)
I D = g m V G S + G d s V D S + I e q 定义每次牛顿迭代的常数项目: I e q = I D 0 − g m V G S 0 − G d s V D S 0 = − r s I_D =g_mV_{GS}+G_{ds}V_{DS}+I_{eq}\\ 定义每次牛顿迭代的常数项目:I_{eq}=I_{D0}-g_mV_{GS0}-G_{ds}V_{DS0}=-rs ID=gmVGS+GdsVDS+Ieq定义每次牛顿迭代的常数项目:Ieq=ID0−gmVGS0−GdsVDS0=−rs
- 这样可写成“矩阵项 + 右侧常数项”(MNA 的标准 A x = b Ax=b Ax=b)的形式,并迭代求解:
[ G d s − ( G d s + g m ) g m − G d s G d s + g m − g m ] [ V D V S V G ] = [ − r s r s ] \begin{bmatrix} G_{ds} & -(G_{ds}+g_m) & g_m \\ -G_{ds} & G_{ds}+g_m & -g_m \end{bmatrix} \begin{bmatrix} V_D\ V_S\ V_G\end{bmatrix} =\begin{bmatrix} -rs\\ rs \end{bmatrix} [Gds−Gds−(Gds+gm)Gds+gmgm−gm][VD VS VG]=[−rsrs]
代码实现
- 不考虑沟道长度调制效应(Channel Length Modulation)和体效应,考虑体二极管的实现代码:
- https://github.com/sharpie7/circuitjs1/blob/master/src/com/lushprojects/circuitjs1/client/MosfetElm.java
- 在代码中,饱和区(mode = 2)的漏极电流 I d s I_{ds} Ids 计算公式为:
ids = .5beta(vgs-vt)*(vgs-vt) + (vds-(vgs-vt))*Gds;
// this is called in doStep to stamp the matrix, and also called in stepFinished() to calculate the current
// this is called in doStep to stamp the matrix, and also called in stepFinished() to calculate the current
void calculate(boolean finished) {
double vs[];
if (finished)
vs = volts;
else {
// limit voltage changes to .5V
vs = new double[3];
vs[0] = volts[0];
vs[1] = volts[1];
vs[2] = volts[2];
if (vs[1] > lastv1 + .5)
vs[1] = lastv1 + .5;
if (vs[1] < lastv1 - .5)
vs[1] = lastv1 - .5;
if (vs[2] > lastv2 + .5)
vs[2] = lastv2 + .5;
if (vs[2] < lastv2 - .5)
vs[2] = lastv2 - .5;
}
int source = 1;
int drain = 2;
// if source voltage > drain (for NPN), swap source and drain
// (opposite for PNP)
if (pnp*vs[1] > pnp*vs[2]) {
source = 2;
drain = 1;
}
int gate = 0;
double vgs = vs[gate ]-vs[source];
double vds = vs[drain]-vs[source];
if (!finished && (nonConvergence(lastv1, vs[1]) || nonConvergence(lastv2, vs[2]) || nonConvergence(lastv0, vs[0])))
sim.converged = false;
lastv0 = vs[0];
lastv1 = vs[1];
lastv2 = vs[2];
double realvgs = vgs;
double realvds = vds;
vgs *= pnp;
vds *= pnp;
ids = 0;
gm = 0;
double Gds = 0;
if (vgs < vt) {
// should be all zero, but that causes a singular matrix,
// so instead we treat it as a large resistor
Gds = 1e-8;
ids = vds*Gds;
mode = 0;
} else if (vds < vgs-vt) {
// linear
ids = beta*((vgs-vt)*vds - vds*vds*.5);
gm = beta*vds;
Gds = beta*(vgs-vds-vt);
mode = 1;
} else {
// saturation; Gds = 0
gm = beta*(vgs-vt);
// use very small Gds to avoid nonconvergence
Gds = 1e-8;
ids = .5*beta*(vgs-vt)*(vgs-vt) + (vds-(vgs-vt))*Gds;
mode = 2;
}
if (doBodyDiode()) {
diodeB1.doStep(pnp*(volts[bodyTerminal]-volts[1]));
diodeCurrent1 = diodeB1.calculateCurrent(pnp*(volts[bodyTerminal]-volts[1]))*pnp;
diodeB2.doStep(pnp*(volts[bodyTerminal]-volts[2]));
diodeCurrent2 = diodeB2.calculateCurrent(pnp*(volts[bodyTerminal]-volts[2]))*pnp;
} else
diodeCurrent1 = diodeCurrent2 = 0;
double ids0 = ids;
// flip ids if we swapped source and drain above
if (source == 2 && pnp == 1 ||
source == 1 && pnp == -1)
ids = -ids;
if (finished)
return;
double rs = -pnp*ids0 + Gds*realvds + gm*realvgs;
sim.stampMatrix(nodes[drain], nodes[drain], Gds);
sim.stampMatrix(nodes[drain], nodes[source], -Gds-gm);
sim.stampMatrix(nodes[drain], nodes[gate], gm);
sim.stampMatrix(nodes[source], nodes[drain], -Gds);
sim.stampMatrix(nodes[source], nodes[source], Gds+gm);
sim.stampMatrix(nodes[source], nodes[gate], -gm);
sim.stampRightSide(nodes[drain], rs);
sim.stampRightSide(nodes[source], -rs);
}
体二极管
setupDiodes() {
diodeB1 = new Diode(sim);
diodeB2 = new Diode(sim);
}
- 根据bodyTerminal之不同实际计算时只会使用一个(另外一个为0):
0 = gate
1 = source
2 = drain
diodeB1.doStep(
pnp*(volts[bodyTerminal]-volts[1])
);
diodeB2.doStep(
pnp*(volts[bodyTerminal]-volts[2])
);
if (doBodyDiode()) {
diodeB1.doStep(pnp*(volts[bodyTerminal]-volts[1]));
diodeCurrent1 = diodeB1.calculateCurrent(pnp*(volts[bodyTerminal]-volts[1]))*pnp;
diodeB2.doStep(pnp*(volts[bodyTerminal]-volts[2]));
diodeCurrent2 = diodeB2.calculateCurrent(pnp*(volts[bodyTerminal]-volts[2]))*pnp;
} else
diodeCurrent1 = diodeCurrent2 = 0;

- pnp 变量(NMOS 时 pnp = 1,PMOS 时 pnp = -1)完成极性的自动翻转:
- 当它是 NMOS 时 (pnp = 1):
- 传入二极管的电压为:1 * (volts[bodyTerminal] - volts[1])。这就是真实的 V b o d y − V 1 V_{body} - V_1 Vbody−V1 压差。因为 NMOS 的衬底是 P,引脚1(假设是源极)是 N,P 减 N 为正时二极管导通。这完全符合物理学。
- 计算出的电流 diodeCurrent1 = 算出的电流 * 1。
- 当它是 PMOS 时 (pnp = -1):
- PMOS 的衬底是 N 型硅,源漏是 P 型。此时,反而是引脚 1 的电压高于衬底时,二极管才会导通。
- 传入二极管的电压变为了:-1 * (volts[bodyTerminal] - volts[1]),即 V 1 − V b o d y V_1 - V_{body} V1−Vbody。通过乘以 -1,代码成功把 PMOS 的反向电压“骗”成了二极管类需要的“正向导通电压”。
- 最后的电流 diodeCurrent1 = 算出的电流 * (-1)。因为进入二极管类的电流方向对 PMOS 来说是反向的,乘以 -1 才能正确修正电流在节点矩阵中的符号。
所有评论(0)