Baum:
PROC [VgsX, Vbin, Eta, Phi, Vbs, Vmax, L, UEffective, gammaD,
SArg3:
REAL]
RETURNS [Vdsat: REAL] = {
v1, v2, xv, a1, b1, c1, d1, a3, b3, A, B, C, R, S,
r3, s2, P, p0, p2, fi, y3, delta4, xValid: REAL← 0.0;
x4, poly4: ARRAY[1..8] OF REAL;
a4, b4, Sig1, Sig2: ARRAY[1..4] OF REAL;
Icount, Jcount: NAT← 0;
Icount ← Jcount← 0;
x4← poly4← ALL[0.0];
a4← b4← ALL[0.0];
Sig1← [1.0, -1.0, 1.0, -1.0];
Sig2← [1.0, 1.0, -1.0, -1.0];
v1← (VgsX-Vbin)/Eta+Phi-Vbs;
v2← Phi-Vbs;
xv← Vmax*L/UEffective;
a1← gammaD/0.75; b1← -2.0*(v1+xv); c1← -2.0*gammaD*xv;
d1← 2.0*v1*(v2+xv)-v2*v2-4.0/3.0*gammaD*SArg3;
A← -b1; B← a1*c1-4.0*d1; C← -d1*(a1*a1-4.0*b1)-c1*c1;
R← -A*A/3.0+B; r3← R*R*R;
S← 2.0*A*A*A/27.0-A*B/3.0+C; s2← S*S;
P← s2/4.0+r3/27.0; p0← ABS[P]; p2← RealFns.SqRt[p0];
get y3 value.
IF P < 0.0
THEN {
ro: REAL;
ro← RealFns.SqRt[s2/4.0+p0];
ro← RealFns.Ln[ro]/3.0;
ro← RealFns.Exp[ro];
fi← RealFns.ArcTan[-2.0*p2/S, 1]; -- arcTan(-2.0*p2/S);
y3← 2.0*ro*RealFns.Cos[fi/3.0]-A/3.0; }
ELSE {
-- 550
p3, p4: REAL;
p3← RealFns.Exp[ RealFns.Ln[ABS[-S/2.0+p2]]/3.0 ];
p4← RealFns.Exp[ RealFns.Ln[ABS[-S/2.0-p2]]/3.0 ];
y3← p3+p4-A/3.0;
};
a3← RealFns.SqRt[a1*a1/4.0-b1+y3];
b3← RealFns.SqRt[y3*y3/4.0-d1];
from a3, b3, Sig1, Sig2, y3 -> a4, b4 -> delta4 -> x4
FOR
I:
NAT
IN[1..4]
DO
a4[I]← a1/2.0+Sig1[I]*a3;
b4[I]← y3/2.0+Sig2[I]*b3;
delta4← a4[I]*a4[I]/4.0-b4[I];
IF delta4 >= 0.0
THEN {
sqrtd4: REAL;
sqrtd4← RealFns.SqRt[delta4];
Icount← Icount+1;
x4[Icount]← a4[I]/(-2.0)+sqrtd4;
Icount← Icount+1;
x4[Icount]← a4[I]/(-2.0)-sqrtd4;
};
ENDLOOP;
FOR
J:
NAT
IN [1..Icount]
DO
tmp: REAL;
IF x4[J] <= 0.0 AND J < Icount THEN LOOP;
tmp← (x4[J]+a1);
tmp← (tmp*x4[J]+b1);
tmp← (tmp*x4[J]+c1);
poly4[J]← (tmp*x4[J]+d1);
IF ABS[poly4[J]] > 1.0E-6 AND J < Icount THEN LOOP;
Jcount← Jcount+1;
IF Jcount <= 1 THEN xValid← x4[J];
IF x4[J] <= xValid THEN xValid← x4[J];
ENDLOOP;
IF Jcount > 0 THEN Vdsat← xValid*xValid+Vbs-Phi
ELSE SIGNAL ThymeGlobals.Retreat["Error in immediate velocity saturation model"];
}; -- Baum
SpiceLevel2: ThymeGlobals.model = {
args
VdX: NAT= 0;
VgX: NAT= 1;
VsX: NAT= 2;
VbX: NAT= 3;
oldArgs
oldVdX: NAT= 0;
oldVgX: NAT= 1;
oldVsX: NAT= 2;
oldVbX: NAT= 3;
parms
LX: NAT= 0;
WX: NAT= 1;
XdX: NAT= 2;
XjX: NAT= 3;
IssatX: NAT= 4;
IdsatX: NAT= 5;
BetaX: NAT= 6;
PhiX: NAT= 7;
SqRtPhiX: NAT= 8;
SqRtPhi3X: NAT= 9;
PbX: NAT= 10;
SqRtPbX: NAT= 11;
VbpX: NAT= 12;
VbiX: NAT= 13;
GammaX: NAT= 14;
LambdaX: NAT= 15;
VtX: NAT= 16;
UoX: NAT= 17;
VmaxX: NAT= 18;
QNfsX: NAT= 19;
NsubX: NAT= 20;
UexpX: NAT= 21;
NeffX: NAT= 22;
EtaX: NAT= 23;
FactorX: NAT= 24;
CoxX: NAT= 25;
CovGSX: NAT= 26;
CovGDX: NAT= 27;
CgbMX: NAT= 28;
Cgb23rdsX: NAT= 29;
CbsBottomX: NAT= 30;
CbdBottomX: NAT= 31;
CbsSWX: NAT= 32;
CbdSWX: NAT= 33;
CbsFwd1X: NAT= 34;
CbsFwd2X: NAT= 35;
CbdFwd1X: NAT= 36;
CbdFwd2X: NAT= 37;
MjX: NAT= 38;
MjswX: NAT= 39;
FcPbX: NAT= 40;
VonX: NAT= 41;
minVX: NAT= 42;
maxVX: NAT= 43;
SignX: NAT= 44;
reverse: BOOL;
sign, Vd, Vg, Vs, Vb, oldVd, oldVg, oldVs, oldVb, Vds, Vgs, Vbs, Vgd, Vbd, oldVds, oldVgs, oldVbs, oldVgd, oldVbd, Id, Cgb, Cgs, Cgd, Cbs, Cbd, t1, Vbin, XdBarg, XdSarg, ArgSS, ArgSD, DBArgS, DBArgD, ArgD, ArgS, gamaSD, DBXWD, DBXWS, gammaD, DgdDvb, VgsT, VgdT, SArg3, body, UFactor, UEffective, VgsX, bodyS, clFactor, Vdsat, ArgG, beta1, Vcrit: REAL;
SArg, BArg: Pair;
LimitNodeVoltage:
PROC[oldV:
REAL]
RETURNS[newV: REAL]= {
newV← MIN[parms[maxVX], MAX[parms[minVX], oldV]];
}; -- LimitNodeVoltage
Id← 0;
sign← parms[SignX];
Vd← LimitNodeVoltage[sign*args[VdX]];
Vg← LimitNodeVoltage[sign*args[VgX]];
Vs← LimitNodeVoltage[sign*args[VsX]];
Vb← LimitNodeVoltage[sign*args[VbX]];
oldVd← LimitNodeVoltage[sign*args[oldVdX]];
oldVg← LimitNodeVoltage[sign*args[oldVgX]];
oldVs← LimitNodeVoltage[sign*args[oldVsX]];
oldVb← LimitNodeVoltage[sign*args[oldVbX]];
Vds ← Vd - Vs; Vgs← Vg - Vs; Vbs← Vb - Vs;
Vgd ← Vg - Vd; Vbd← Vb - Vd;
oldVds ← oldVd - oldVs; oldVgs ← oldVg - oldVs; oldVbs← oldVb - oldVs;
oldVgd ← oldVg - oldVd; oldVbd ← oldVb - oldVd;
IF oldVds >= 0
THEN {
Vgs← LimitVgs[Vgs, oldVgs, parms[VonX]];
Vds← Vgs - Vgd;
Vds← LimitVds[Vds, oldVds];
Vgd← Vgs - Vds; }
ELSE {
Vgd← LimitVgs[Vgd, oldVgd, parms[VonX]];
Vds← Vgs - Vgd;
Vds← -LimitVds[-Vds, -oldVds];
Vgs← Vgd + Vds;
};
IF Vds >= 0
THEN {
Vcrit← parms[VtX]*RealFns.Ln[parms[VtX]/(1.414*parms[IssatX])];
Vbs← LimitVbs[Vbs, oldVbs, parms[VtX], Vcrit];
Vbd← Vbs - Vds;
args[VdX]← sign*(Vs + Vds);
args[VgX]← sign*(Vs + Vgs);
args[VbX]← sign*(Vs + Vbs); }
ELSE {
Vcrit← parms[VtX]*RealFns.Ln[parms[VtX]/(1.414*parms[IdsatX])];
Vbd← LimitVbs[Vbd, oldVbd, parms[VtX], Vcrit];
Vbs← Vbd + Vds;
args[VsX]← sign*(Vd - Vds);
args[VgX]← sign*(Vd + Vgd);
args[VbX]← sign*(Vd + Vbd);
};
get Ibs and Ibd
results[6]← sign*JcnCurrent[parms[VtX], Vbs, parms[IssatX]];
results[7]← sign*JcnCurrent[parms[VtX], Vbd, parms[IdsatX]];
IF Vds >= 0 THEN reverse← FALSE
ELSE {
reverse← TRUE; Vds← -Vds;
t1← Vbs; Vbs← Vbd; Vbd← t1;
t1← Vgs; Vgs← Vgd; Vgd← t1;
};
100
SArg← FandDF[Vbs, parms[PhiX], parms[SqRtPhiX], parms[SqRtPhi3X]];
BArg← FandDF[Vbd, parms[PhiX], parms[SqRtPhiX], parms[SqRtPhi3X]];
200, Calculate parms[VonX], narrow channel effect
Vbin← parms[VbiX]+parms[FactorX]*(parms[PhiX]-Vbs);
XdBarg← parms[XdX]*BArg.f;
XdSarg← parms[XdX]*SArg.f;
short channel effect with Vds # 0
ArgSS← ArgSD← DBArgS← DBArgD← 0.0;
IF parms[XjX] > 0.0
THEN {
ArgXS, ArgXD: REAL;
ArgXS← 1.0+2.0*XdSarg/parms[XjX];
ArgS← RealFns.SqRt[ArgXS];
ArgSS← 0.5*parms[XjX]/parms[LX]*(ArgS-1.0);
ArgXD← 1.0+2.0*XdBarg/parms[XjX];
ArgD← RealFns.SqRt[ArgXD];
ArgSD← 0.5*parms[XjX]/parms[LX]*(ArgD-1.0);
};
(205)
gamaSD← parms[GammaX]*(1.0-ArgSS-ArgSD);
DBXWD← parms[XdX]*BArg.df;
DBXWS← parms[XdX]*SArg.df;
IF parms[XjX] > 0.0
THEN {
DBArgS← 0.5/parms[LX]*DBXWS/ArgS;
DBArgD← 0.5/parms[LX]*DBXWD/ArgD;
};
DgdDvb← -parms[GammaX]*(DBArgS+DBArgD);
220
parms[VonX]← Vbin+gamaSD*SArg.f;
Vdsat← 0.0;
225
{
IF parms[QNfsX] = 0.0
THEN {
-- 230
VgsT← Vgs-parms[VonX];
IF VgsT<=0.0 THEN GOTO done;
} -- (Id=0) 1050
ELSE {
CdOnCo, Xn: REAL;
CdOnCo← -(gamaSD*SArg.df+DgdDvb*SArg.f)+parms[FactorX];
Xn← 1.0+parms[QNfsX]/parms[CoxX]+CdOnCo;
parms[VonX]← parms[VonX]+parms[VtX]*Xn;
ArgG← 1.0/(parms[VtX]*Xn);
VgsT← Vgs-parms[VonX];
};
300
SArg3← SArg.f*SArg.f*SArg.f;
gammaD← gamaSD;
body← BArg.f*BArg.f*BArg.f-SArg3;
400, evaluate effective mobility and its derivatives
IF VgsT > parms[VbpX]
THEN {
UFactor← RealFns.Exp[ parms[UexpX]*RealFns.Ln[parms[VbpX]/VgsT] ];
UEffective← parms[UoX]*UFactor; }
ELSE {
-- 410
UFactor← 1.0;
UEffective← parms[UoX];
};
500 evaluate saturation voltage and its derivatives
according to grove-frohman equation
VgsX← Vgs;
gammaD← gamaSD/parms[EtaX];
IF parms[QNfsX]#0.0 THEN VgsX← MAX[Vgs, parms[VonX]];
Vdsat←
IF gammaD <= 0.0
THEN
MAX[0.0, (VgsX-Vbin)/parms[EtaX]]
ELSE Grove[gammaD, VgsX, Vbin, parms[EtaX], parms[PhiX], Vbs];
545
IF parms[VmaxX] > 0.0
THEN Vdsat← Baum[
VgsX, Vbin, parms[EtaX], parms[PhiX], Vbs, parms[VmaxX],
parms[LX], UEffective, gammaD, SArg3];
600, evaluate effective channel length and its derivatives
IF Vds # 0.0
THEN {
lFactor, ArgV, xdv, lv, ls, SArgV, BSArg: REAL;
gammaD← gamaSD;
BSArg← IF Vbs <= Vdsat THEN RealFns.SqRt[Vdsat-Vbs+parms[PhiX]]
ELSE parms[SqRtPhiX]/(1.0+0.5*(Vbs-Vdsat)/parms[PhiX]);
bodyS← BSArg*BSArg*BSArg-SArg3;
IF parms[VmaxX] <=0.0
THEN {
IF parms[NsubX] # 0.0
AND parms[LambdaX] <= 0.0
THEN {
Arg: REAL;
ArgV← (Vds-Vdsat)/4.0;
SArgV← RealFns.SqRt[1.0+ArgV*ArgV];
Arg← RealFns.SqRt[ArgV+SArgV];
lFactor← parms[XdX]/(parms[LX]*Vds);
parms[LambdaX]← lFactor*Arg;
};
}
ELSE {
-- 603
ArgV← (VgsX-Vbin)/parms[EtaX]-Vdsat;
xdv← parms[XdX]/RealFns.SqRt[parms[NeffX]];
lv← parms[VmaxX]*xdv/(2.0*UEffective);
IF parms[NsubX] # 0.0
AND parms[LambdaX] <= 0.0
THEN {
ArgV← MAX[Vds-Vdsat, 0.0];
ls← RealFns.SqRt[lv*lv+ArgV];
lFactor← xdv/(parms[LX]*Vds);
parms[LambdaX]← lFactor*(ls-lv);
};
};
}; -- block 600
620, limit channel shortening at punch-through
{
leffective, deltaL, xwb, ld: REAL;
xwb← parms[XdX]*parms[SqRtPbX];
ld← parms[LX]-xwb;
clFactor← 1.0-parms[LambdaX]*Vds;
leffective← parms[LX]*clFactor;
deltaL← parms[LambdaX]*Vds*parms[LX];
IF parms[NsubX]=0.0 THEN xwb← 0.25E-6;
IF leffective<xwb
THEN {
leffective← xwb/(1.0+(deltaL-ld)/xwb);
clFactor← leffective/parms[LX];
};
}; -- block 620
700 evaluate effective beta (effective kp)
beta1← parms[BetaX]*UFactor/clFactor;
test for mode of operation and branch appropriately
gammaD← gamaSD;
IF Vds <= 1.0E-8 THEN GOTO done; -- (id=0) 1050
730
IF VgsT <= 0.0
THEN {
-- else goto 900
subthreshold region, if vdsat<=0.0 then id← 0.0
IF Vdsat > 0.0
THEN {
-- 830
VdsOn, IdsOn, ArgGVgsT: REAL;
VdsOn← MIN[Vdsat,Vds];
ArgGVgsT← ArgG*VgsT;
IF Vds > Vdsat THEN body← bodyS;
IdsOn← beta1*( (parms[VonX] - Vbin -
parms[EtaX]*VdsOn*0.5)*VdsOn - gammaD*body/1.5 );
if arggvgst < -ln(idson) - 34.539 then id < 1e-15 ~ 0
Id←
IF ArgGVgsT < (- 34.539 - RealFns.Ln[IdsOn])
THEN 0
ELSE sign*IdsOn*RealFns.Exp[ArgGVgsT];
};
}
ELSE
Id ←
IF Vds <= Vdsat
THEN
-- 900 LINEAR REGION
sign*beta1*((Vgs-Vbin-parms[EtaX]*Vds/2.0)*Vds-gammaD*body/1.5)
ELSE
-- 1000 saturation region
sign*beta1*((Vgs-Vbin-parms[EtaX]*Vdsat/2.0)*
Vdsat-gammaD*bodyS/1.5);
};
capacitances, and results
VgdT← Vgd - parms[VonX];
cgb:
Cgb← IF VgsT <= 0 THEN parms[CgbMX] ELSE 0;
cgs and cgd:
t1← VgsT+VgdT;
t1← t1*t1; -- (Vgs + Vgd - 2Von)^2
Cgs←
IF VgsT <= 0.0
THEN parms[CovGSX]
ELSE
IF VgdT <= 0.0 THEN parms[Cgb23rdsX] + parms[CovGSX]
ELSE parms[CovGSX] + parms[Cgb23rdsX]*(1.0 - VgdT*VgdT/t1);
Cgd←
IF VgdT <= 0.0
THEN parms[CovGDX]
ELSE parms[CovGDX] + parms[Cgb23rdsX]*(1.0 - VgsT*VgsT/t1);
cbs and cbd
IF Vbs >= parms[FcPbX]
THEN
-- 520
Cbs← parms[CbsFwd1X] + Vbs*parms[CbsFwd2X]
ELSE {
t1← RealFns.Ln[1.0-Vbs/parms[PbX]];
Cbs← parms[CbsBottomX] * RealFns.Exp[-parms[MjX] * t1] + parms[CbsSWX] * RealFns.Exp[-parms[MjswX] * t1]
};
IF Vbd >= parms[FcPbX]
THEN
-- 520
Cbd← parms[CbdFwd1X] + Vbd*parms[CbdFwd2X]
ELSE {
t1← RealFns.Ln[1.0-Vbd/parms[PbX]];
Cbd← parms[CbdBottomX] * RealFns.Exp[-parms[MjX] * t1] + parms[CbdSWX] * RealFns.Exp[-parms[MjswX] * t1]
};
results order: id, cgb, cgs, cgd, cbs, cbd, ibs, ibd.
IF reverse
THEN {
results[0]← -Id;
results[1]← Cgb;
results[2]← Cgd;
results[3]← Cgs;
results[4]← Cbd;
results[5]← Cbs;
}
ELSE {
results[0]← Id;
results[1]← Cgb;
results[2]← Cgs;
results[3]← Cgd;
results[4]← Cbs;
results[5]← Cbd;
};
}; -- SpiceLevel2