This package Mos2 contains functions and records with data of the mosfet model level 2.
Extends from Modelica.Icons.Package (Icon for standard packages).
| Name | Description |
|---|---|
| Record for Mosfet model line parameters (for level 2) | |
| Record for Mosfet model line variables (for level 2) | |
| Further mosfet variables (for level 2) | |
| Initial precalculation | |
| Drain current calculation | |
| Parameter renaming to internal names | |
| Device parameter renaming to internal names |
This record Mos1ModelLineParams contains the model line parameters that are used for the mosfet transistors level 2 in SPICE3.
Extends from Mos.MosModelLineParams (Record for Mosfet model line parameters (for level 1, 2, 3 and 6)).
| Type | Name | Default | Description |
|---|---|---|---|
| Initialization | |||
| Real | m_jctSatCurDensity.start | 0.0 | JS, Bulk jct. sat. current density, input - use tSatCurDens |
| Resistance | m_sheetResistance.start | 0.0 | RSH, Sheet resistance [Ohm] |
| Real | m_bulkJctPotential.start | 0.8 | PB, Bulk junction potential, input - use tBulkPot |
| Real | m_bulkJctBotGradingCoeff.start | 0.5 | MJ, Bottom grading coefficient |
| Real | m_bulkJctSideGradingCoeff.start | 0.33 | MJSW, Side grading coefficient |
| Real | m_oxideThickness.start | 1.0e-7 | TOX, Oxide thickness unit: micron |
| Real | m_gateSourceOverlapCapFactor.start | 0.0 | CGS0, Gate-source overlap cap |
| Real | m_gateDrainOverlapCapFactor.start | 0.0 | CGD0, Gate-drain overlap cap |
| Real | m_gateBulkOverlapCapFactor.start | 0.0 | CGB0, Gate-bulk overlap cap |
| Real | m_fNcoef.start | 0.0 | KF, Flicker noise coefficient |
| Real | m_fNexp.start | 1.0 | AF, Flicker noise exponent |
| Real | m_oxideCapFactor.start | 0.0 | |
| Voltage | m_vt0.start | 0.0 | VTO, Threshold voltage [V] |
| Capacitance | m_capBD.start | 0.0 | CBD, B-D junction capacitance [F] |
| Capacitance | m_capBS.start | 0.0 | CBS, B-S junction capacitance [F] |
| CapacitancePerArea | m_bulkCapFactor.start | 0.0 | CJ, Bottom junction cap per area [F/m2] |
| Permittivity | m_sideWallCapFactor.start | 0.0 | CJSW, Side grading coefficient [F/m] |
| Real | m_fwdCapDepCoeff.start | 0.5 | FC, Forward bias jct. fit parm. |
| Voltage | m_phi.start | 0.6 | PHI, Surface potential [V] |
| Voltage | m_gamma.start | 0.0 | GAMMA, Bulk threshold parameter [V] |
| InversePotential | m_lambda.start | 0.0 | Channel-length modulation [1/V] |
| Real | m_substrateDoping.start | 0.0 | NSUB, Substrate doping |
| Real | m_gateType.start | 1.0 | TPG, Gate type |
| PerArea_cm | m_surfaceStateDensity.start | 0.0 | NSS, Gate type [1/cm2] |
| Area_cmPerVoltageSecond | m_surfaceMobility.start | 600.0 | UO, Surface mobility [cm2/(V.s)] |
| Length | m_latDiff.start | 0.0 | LD, Lateral diffusion [m] |
| Current | m_jctSatCur.start | 1.0e-14 | IS, Bulk junction sat. current [A] |
| Resistance | m_drainResistance.start | 0 | RD, Drain ohmic resistance [Ohm] |
| Resistance | m_sourceResistance.start | 0 | RS, Source ohmic resistance [Ohm] |
| Transconductance | m_transconductance.start | 2.0e-5 | input - use tTransconductance [A/V2] |
record Mos2ModelLineParams
"Record for Mosfet model line parameters (for level 2)"
extends Mos.MosModelLineParams(
m_lambda(start=0.0),
m_transconductance(start=2.0e-5),
m_bulkJctSideGradingCoeff(start=0.33),
m_oxideThickness(start=1.0e-7));
Real m_narrowFactor( start = 0.0) "DELTA, Width effect on threshold";
Real m_critFieldExp( start = 0.0) "UEXP, Crit. field exp for mob. deg";
Real m_critField( start = 1.0e4) "UCRIT, Crit. field for mob. degradation";
Real m_maxDriftVel( start = 0.0) "VMAX, Maximum carrier drift velocity";
Real m_junctionDepth( start = 0.0) "XJ, Junction depth";
Modelica.SIunits.Charge m_channelCharge( start = 1.0)
"NEFF, Total channel charge coeff";
Real m_fastSurfaceStateDensity( start = 0.0)
"NFS, Fast surface state density";
end Mos2ModelLineParams;
This record MosModelLineVariables contains the model line variables that are used for the mosfet transistors level 2 SPICE3.
Extends from Mos.MosModelLineVariables (Record for Mosfet model line variables (for level 1)).
record Mos2ModelLineVariables "Record for Mosfet model line variables (for level 2)" extends Mos.MosModelLineVariables; Real m_bulkCapFactor; Real m_substrateDoping; Real m_xd;end Mos2ModelLineVariables;
This record Mos1Calc contains further mosfet variables (for level 2) that are needed for the calculations.
Extends from Mos.MosCalc (Further mosfet variables (for level 1, 2, 3 and 6)).
| Type | Name | Default | Description |
|---|---|---|---|
| Initialization | |||
| Integer | m_mode.start | 1 | Mode |
| Transconductance | m_tTransconductance.start | 0. | [A/V2] |
| Real | m_tSurfMob.start | 0. | |
| Voltage | m_tPhi.start | 0.7 | [V] |
| Voltage | m_tVto.start | 1. | [V] |
| Real | m_tSatCurDens.start | 0. | |
| Current | m_tDrainSatCur.start | 0. | [A] |
| Current | m_tSourceSatCur.start | 0. | [A] |
| Capacitance | m_tCBDb.start | 0. | [F] |
| Capacitance | m_tCBDs.start | 0. | [F] |
| Capacitance | m_tCBSb.start | 0. | [F] |
| Capacitance | m_tCBSs.start | 0. | [F] |
| Real | m_tCj.start | 0. | |
| Real | m_tCjsw.start | 0. | |
| Voltage | m_tBulkPot.start | 0.7 | [V] |
| Real | m_tDepCap.start | 0.35 | |
| Voltage | m_tVbi.start | 1. | [V] |
| Voltage | m_VBScrit.start | 0.7 | [V] |
| Voltage | m_VBDcrit.start | 0.7 | [V] |
| Real | m_f1b.start | 0. | |
| Real | m_f2b.start | 0. | |
| Real | m_f3b.start | 0. | |
| Real | m_f1s.start | 0. | |
| Real | m_f2s.start | 0. | |
| Real | m_f3s.start | 0. | |
| Real | m_dVt.start | 0. | |
| Capacitance | m_capgd.start | 0. | [F] |
| Capacitance | m_capgs.start | 0. | [F] |
| Capacitance | m_capgb.start | 0. | [F] |
| Charge | m_qgs.start | 0. | [C] |
| Charge | m_qgd.start | 0. | [C] |
| Charge | m_qgb.start | 0. | [C] |
record Mos2Calc "Further mosfet variables (for level 2)" extends Mos.MosCalc;end Mos2Calc;
This function mos1ModelLineParamsInitEquation does the initial precalculation of the mosfet model line parameters for level 2.
| Type | Name | Default | Description |
|---|---|---|---|
| Mos2ModelLineParams | in_p | Input record model line parameters for MOS2 | |
| SpiceConstants | in_C | Spice constants | |
| Integer | in_m_type | Type of MOS transistor |
| Type | Name | Description |
|---|---|---|
| Mos2ModelLineVariables | out_v | Output record with model line variables |
function mos2ModelLineParamsInitEquations "Initial precalculation"
input Mos2ModelLineParams in_p "Input record model line parameters for MOS2";
input SpiceConstants in_C "Spice constants";
input Integer in_m_type "Type of MOS transistor";
output Mos2ModelLineVariables out_v "Output record with model line variables";
protected
Modelica.SIunits.Voltage vtnom;
Modelica.SIunits.Voltage fermis;
Real fermig;
Real wkfng;
Real wkfngs;
Real egfet1;
Real vfb;
algorithm
out_v.m_oxideCapFactor := in_p.m_oxideCapFactor;
out_v.m_transconductance := in_p.m_transconductance;
out_v.m_phi := in_p.m_phi;
out_v.m_gamma := in_p.m_gamma;
out_v.m_vt0 := in_p.m_vt0;
out_v.m_substrateDoping := in_p.m_substrateDoping;
out_v.m_bulkCapFactor := in_p.m_bulkCapFactor;
vtnom := in_p.m_tnom * in_C.CONSTKoverQ;
egfet1 := 1.16 - (7.02e-4 * in_p.m_tnom * in_p.m_tnom) / (in_p.m_tnom + 1108);
out_v.m_oxideCapFactor := 3.9 * 8.854214871e-12 / in_p.m_oxideThickness;
if ( not (in_p.m_transconductanceIsGiven > 0.5)) then
out_v.m_transconductance := in_p.m_surfaceMobility * 1.0e-4 * out_v.m_oxideCapFactor;
end if;
if (in_p.m_substrateDopingIsGiven > 0.5) then
if ( out_v.m_substrateDoping * 1.0e6 > 1.45e16) then
if ( not (in_p.m_phiIsGiven > 0.5)) then
out_v.m_phi := 2 * vtnom * Modelica.Math.log( out_v.m_substrateDoping * 1.0e6 / 1.45e16);
out_v.m_phi := max( 0.1, out_v.m_phi);
end if;
fermis := in_m_type * 0.5 * out_v.m_phi;
wkfng := 3.2;
if ( in_p.m_gateType <> 0) then
fermig := in_m_type * in_p.m_gateType * 0.5 * egfet1;
wkfng := 3.25 + 0.5 * egfet1 - fermig;
end if;
wkfngs := wkfng - (3.25 + 0.5 * egfet1 + fermis);
if ( not (in_p.m_gammaIsGiven > 0.5)) then
out_v.m_gamma := sqrt(2.0 * 11.70 * 8.854214871e-12 * in_C.CHARGE * out_v.m_substrateDoping
* 1.0e6) / out_v.m_oxideCapFactor;
end if;
if ( not (in_p.m_vtOIsGiven > 0.5)) then
vfb := wkfngs - in_p.m_surfaceStateDensity * 1.0e4 * in_C.CHARGE / out_v.m_oxideCapFactor;
out_v.m_vt0 := vfb + in_m_type * (out_v.m_gamma * sqrt(out_v.m_phi)+ out_v.m_phi);
else
vfb := out_v.m_vt0 - in_m_type * (out_v.m_gamma * sqrt(out_v.m_phi) + out_v.m_phi);
end if;
out_v.m_xd := sqrt( (in_C.EPSSIL + in_C.EPSSIL) / (in_C.CHARGE * out_v.m_substrateDoping * 1.0e6));
else
out_v.m_substrateDoping := 0.0;
end if;
end if;
if ( not (in_p.m_bulkCapFactorIsGiven > 0.5)) then
out_v.m_bulkCapFactor := sqrt( in_C.EPSSIL * in_C.CHARGE * out_v.m_substrateDoping
* 1e6 /(2 * in_p.m_bulkJctPotential));
end if;
end mos2ModelLineParamsInitEquations;
This function drainCur calculates the main currents that flows from drain node to source node (level 2).
| Type | Name | Default | Description |
|---|---|---|---|
| Voltage | vbs | [V] | |
| Voltage | vgs | [V] | |
| Voltage | vds | [V] | |
| Mosfet | in_m | Record mosfet | |
| Mos2Calc | in_c | Input record Mos2Calc | |
| Mos2ModelLineParams | in_p | Input record model line parameters for MOS2 | |
| SpiceConstants | in_C | Spice constants | |
| Mos2ModelLineVariables | in_vp | Input record model line variables | |
| Integer | in_m_type | Type of MOS transistor |
| Type | Name | Description |
|---|---|---|
| Mos2Calc | out_c | Output record Mos2Calc |
function drainCur "Drain current calculation"
input Modelica.SIunits.Voltage vbs;
input Modelica.SIunits.Voltage vgs;
input Modelica.SIunits.Voltage vds;
input Mosfet.Mosfet in_m "Record mosfet";
input Mos2Calc in_c "Input record Mos2Calc";
input Mos2ModelLineParams in_p "Input record model line parameters for MOS2";
input SpiceConstants in_C "Spice constants";
input Mos2ModelLineVariables in_vp "Input record model line variables";
input Integer in_m_type "Type of MOS transistor";
output Mos2Calc out_c "Output record Mos2Calc";
protected
Real vt; // K * T / Q
Real beta1;
Real dsrgdb;
Real d2sdb2;
Real sphi = 0.0;
Real sphi3 = 1.0; // square root of phi
Real barg;
Real sarg;
Real bsarg = 0.0;
Real sarg3;
Real d2bdb2;
Real factor;
Real dbrgdb;
Real eta;
Real vbin;
Real vth;
Real dgddb2;
Real dgddvb;
Real dgdvds;
Real gamasd;
Real gammad;
Real xn = 1.0;
Real argg = 0.0;
Real vgst;
Real vgsx;
Real dgdvbs;
Real body;
Real bodys = 0.0;
Real gdbdv;
Real dodvbs;
Real dodvds = 0.0;
Real dxndvd = 0.0;
Real dxndvb = 0.0;
Real dudvgs;
Real dudvds;
Real dudvbs;
Real ufact;
Real ueff;
Real dsdvgs;
Real dsdvbs;
Real dbsrdb;
Real gdbdvs = 0.0;
Real dldvgs;
Real dldvds;
Real dldvbs;
Real clfact;
Real xleff;
Real deltal;
Real xwb;
Real xld;
Real xlamda = in_p.m_lambda;
Real phiMinVbs;
Real tmp;
Real argss;
Real argsd;
Real args = 0.0;
Real argd = 0.0;
Real argxs = 0.0;
Real argxd = 0.0;
Real dbargs;
Real dbargd;
Real dbxws;
Real dbxwd;
Real xwd;
Real xws;
Real daddb2;
Real dasdb2;
Real ddxwd;
Real cfs;
Real cdonco;
Real argv;
Real gammd2;
Real arg;
Real y3;
Real xvalid = 0.0;
Real[4] sig1;
Real[4] sig2;
Real[4] a4;
Real[4] b4;
Real[8] x4;
Real[8] poly4;
Real delta4;
Integer j;
Integer iknt = 0;
Integer i;
Integer jknt = 0;
Real v1;
Real v2;
Real xv;
Real a1;
Real b1;
Real c1;
Real d1;
Real b2;
Real r1;
Real s1;
Real s2;
Real p1;
Real p0;
Real p2;
Real a3;
Real b3;
Real sargv;
Real dldsat;
Real xlfact;
Real xdv;
Real xlv;
Real vqchan;
Real dqdsat;
Real vl;
Real dfunds;
Real dfundg;
Real dfundb;
Real xls;
Real dfact;
Real vdson;
Real cdson;
Real gdson;
Real didvds;
Real gmw;
Real gbson;
Real expg;
algorithm
out_c := in_c;
vt := in_C.CONSTKoverQ * in_C.REFTEMP;
phiMinVbs := out_c.m_tPhi - vbs;
if ( vbs <= 0.0) then
sarg := sqrt( phiMinVbs);
dsrgdb := -0.5 / sarg;
d2sdb2 := 0.5 * dsrgdb / phiMinVbs;
else
sphi :=sqrt(out_c.m_tPhi);
sphi3 :=out_c.m_tPhi*sphi;
sarg :=sphi/(1.0 + 0.5*vbs/out_c.m_tPhi);
tmp :=sarg/sphi3;
dsrgdb :=-0.5*sarg*tmp;
d2sdb2 :=-dsrgdb*tmp;
end if;
if ( (vds-vbs) >= 0) then
barg := sqrt( phiMinVbs + vds);
dbrgdb := -0.5 / barg;
d2bdb2 := 0.5 * dbrgdb / (phiMinVbs + vds);
else
barg := sphi / (1.0 + 0.5 * (vbs - vds) / out_c.m_tPhi);
tmp := barg / sphi3;
dbrgdb := -0.5 * barg * tmp;
d2bdb2 := -dbrgdb * tmp;
end if;
factor := 0.125 * in_p.m_narrowFactor * 2.0 * Modelica.Constants.pi*in_C.EPSSIL / out_c.m_capOx * out_c.m_lEff;
eta := 1.0 + factor;
vbin := out_c.m_tVbi * in_m_type + factor * phiMinVbs;
if ( (in_vp.m_gamma > 0.0) or (in_vp.m_substrateDoping > 0.0)) then
xwd := in_vp.m_xd * barg;
xws := in_vp.m_xd * sarg;
argss := 0.0;
argsd := 0.0;
dbargs := 0.0;
dbargd := 0.0;
dgdvds := 0.0;
dgddb2 := 0.0;
if ( in_p.m_junctionDepth > 0) then
tmp := 2.0 / in_p.m_junctionDepth;
argxs := 1.0 + xws * tmp;
argxd := 1.0 + xwd * tmp;
args := sqrt( argxs);
argd := sqrt( argxd);
tmp := 0.5 * in_p.m_junctionDepth / out_c.m_lEff;
argss := tmp * (args - 1.0);
argsd := tmp * (argd - 1.0);
end if;
gamasd := in_vp.m_gamma * (1.0 - argss - argsd);
dbxwd := in_vp.m_xd * dbrgdb;
dbxws := in_vp.m_xd * dsrgdb;
if ( in_p.m_junctionDepth > 0) then
tmp := 0.5 / out_c.m_lEff;
dbargs := tmp * dbxws / args;
dbargd := tmp * dbxwd / argd;
dasdb2 := -in_vp.m_xd * (d2sdb2 + dsrgdb * dsrgdb * in_vp.m_xd
/ (in_p.m_junctionDepth * argxs)) / (out_c.m_lEff * args);
daddb2 := -in_vp.m_xd * (d2bdb2 + dbrgdb * dbrgdb * in_vp.m_xd
/ (in_p.m_junctionDepth * argxd))
/ (out_c.m_lEff * argd);
dgddb2 := -0.5 * in_vp.m_gamma * (dasdb2 + daddb2);
end if;
dgddvb := -in_vp.m_gamma * (dbargs + dbargd);
if ( in_p.m_junctionDepth > 0) then
ddxwd := -dbxwd;
dgdvds := -in_vp.m_gamma * 0.5 * ddxwd / (out_c.m_lEff * argd);
end if;
else
gamasd := in_vp.m_gamma;
gammad := in_vp.m_gamma;
dgddvb := 0.0;
dgdvds := 0.0;
dgddb2 := 0.0;
end if;
out_c.m_von := vbin + gamasd * sarg;
vth := out_c.m_von;
out_c.m_vdsat := 0.0;
if ( in_p.m_fastSurfaceStateDensity <> 0.0 and out_c.m_capOx <> 0.0) then
cfs := in_C.CHARGE * in_p.m_fastSurfaceStateDensity * 1.0e4;
cdonco := -(gamasd * dsrgdb + dgddvb * sarg) + factor;
xn := 1.0 + cfs / out_c.m_capOx * in_m.m_width * out_c.m_lEff + cdonco;
tmp := vt * xn;
out_c.m_von := out_c.m_von + tmp;
argg := 1.0 / tmp;
vgst := vgs - out_c.m_von;
else
vgst := vgs - out_c.m_von;
if ( vgs <= out_c.m_von) then
// cutoff region
out_c.m_gds := 0.0;
out_c.m_cdrain := 0.0;
out_c.m_gm := 0.0;
out_c.m_gmbs := 0.0;
return;
end if;
end if;
sarg3 := sarg * sarg * sarg;
gammad := gamasd;
dgdvbs := dgddvb;
body := barg * barg * barg - sarg3;
gdbdv := 2.0 * gammad * (barg * barg * dbrgdb - sarg * sarg * dsrgdb);
dodvbs := -factor + dgdvbs * sarg + gammad * dsrgdb;
if ( (in_p.m_fastSurfaceStateDensity <> 0.0) and (out_c.m_capOx <> 0.0)) then
dxndvb := 2.0 * dgdvbs * dsrgdb + gammad * d2sdb2 + dgddb2 * sarg;
dodvbs := dodvbs + vt * dxndvb;
dxndvd := dgdvds * dsrgdb;
dodvds := dgdvds * sarg + vt * dxndvd;
end if;
// evaluate effective mobility and its derivatives
ufact := 1.0;
ueff := in_p.m_surfaceMobility * 1e-4;
dudvgs := 0.0;
dudvds := 0.0;
dudvbs := 0.0;
if (out_c.m_capOx > 0.0) then
tmp := in_p.m_critField * in_C.EPSSIL * 100 / in_vp.m_oxideCapFactor;
if (vgst > tmp) then
ufact := exp( in_p.m_critFieldExp * Modelica.Math.log( tmp / vgst));
ueff := in_p.m_surfaceMobility * 1.0e-4 * ufact;
dudvgs := -ufact * in_p.m_critFieldExp / vgst;
dudvds := 0.0;
dudvbs := in_p.m_critFieldExp * ufact * dodvbs / vgst;
end if;
end if;
// evaluate saturation voltage and its derivatives according to
// grove-frohman equation
vgsx := vgs;
gammad := gamasd / eta;
dgdvbs := dgddvb;
if (in_p.m_fastSurfaceStateDensity <> 0 and out_c.m_capOx <> 0) then
vgsx := max( vgs, out_c.m_von);
end if;
if (gammad > 0) then
gammd2 := gammad * gammad;
argv := (vgsx - vbin) / eta + phiMinVbs;
if (argv <= 0.0) then
out_c.m_vdsat := 0.0;
dsdvgs := 0.0;
dsdvbs := 0.0;
else
arg := sqrt( 1.0 + 4.0 * argv / gammd2);
out_c.m_vdsat := (vgsx - vbin) / eta + gammd2 * (1.0 - arg) / 2.0;
out_c.m_vdsat := max( out_c.m_vdsat, 0.0);
dsdvgs := (1.0 - 1.0 / arg) / eta;
dsdvbs := (gammad * (1.0 - arg) + 2.0 * argv / (gammad * arg))
/ eta * dgdvbs + 1.0 / arg + factor * dsdvgs;
end if;
else
out_c.m_vdsat := (vgsx - vbin) / eta;
out_c.m_vdsat := max( out_c.m_vdsat, 0.0);
dsdvgs := 1.0;
dsdvbs := 0.0;
end if;
if (in_p.m_maxDriftVel > 0) then
// evaluate saturation voltage and its derivatives
// according to baum's theory of scattering velocity saturation
v1 := (vgsx - vbin) / eta + phiMinVbs;
v2 := phiMinVbs;
xv := in_p.m_maxDriftVel * out_c.m_lEff / ueff;
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;
b2 := a1 * c1 - 4.0 * d1;
r1 := -b1 * b1 / 3.0 + b2;
s1 := 2.0 * b1 * b1 * (-b1) / 27.0 + b1 * b2 / 3.0 + (-d1) * (a1 * a1 - 4.0 * b1) - c1 * c1;
s2 := s1 * s1;
p1 := s2 / 4.0 + r1 * r1 * r1 / 27.0;
p0 := abs( p1);
p2 := sqrt( p0);
sig1[1] := 1.0;
sig1[2] := -1.0;
sig1[3] := 1.0;
sig1[4] := -1.0;
sig2[1] := 1.0;
sig2[2] := 1.0;
sig2[3] := -1.0;
sig2[4] := -1.0;
if (p1 < 0) then
y3 := 2.0 * exp( Modelica.Math.log( sqrt( s2 / 4.0 + p0)) / 3.0)
* cos( Modelica.Math.atan( -2.0 * p2 / s1) / 3.0) + b1 / 3.0;
else
y3 := exp( Modelica.Math.log( abs( -s1 / 2.0 + p2)) / 3.0)
+ exp( Modelica.Math.log( abs( -s1 / 2.0 - p2)) / 3.0)
+ b1 / 3.0;
end if;
a3 := sqrt( a1 * a1 / 4.0 - b1 + y3);
b3 := sqrt( y3 * y3 / 4.0 - d1);
for i in 1:4 loop
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) then
iknt := iknt+1;
tmp := sqrt(delta4);
x4[iknt] := -a4[i]/2.0+tmp;
iknt := iknt+1;
x4[iknt] := -a4[i]/2.0-tmp;
end if;
end for;
jknt := 0;
for j in 1:iknt loop
if (x4[j] > 0) then
poly4[j] := x4[j]*x4[j]*x4[j]*x4[j]+a1*x4[j]*x4[j]*x4[j];
poly4[j] := poly4[j]+b1*x4[j]*x4[j]+c1*x4[j]+d1;
if (abs(poly4[j]) <= 1.0e-6) then
jknt := jknt+1;
if (jknt <= 1) then
xvalid := x4[j];
end if;
if (x4[j] <= xvalid) then
xvalid := x4[j];
end if;
end if;
end if;
end for;
if (jknt > 0) then
out_c.m_vdsat := xvalid * xvalid - phiMinVbs;
end if;
end if;
// evaluate effective channel length and its derivatives
dldvgs := 0.0;
dldvds := 0.0;
dldvbs := 0.0;
if (vds <> 0.0) then
gammad :=gamasd;
if ((vbs - out_c.m_vdsat) <= 0) then
bsarg := sqrt(out_c.m_vdsat + phiMinVbs);
dbsrdb := -0.5 / bsarg;
else
bsarg :=sphi/(1.0 + 0.5*(vbs - out_c.m_vdsat)/out_c.m_tPhi);
dbsrdb :=-0.5*bsarg*bsarg/sphi3;
end if;
bodys := bsarg * bsarg * bsarg - sarg3;
gdbdvs := 2.0 * gammad * (bsarg * bsarg * dbsrdb - sarg * sarg * dsrgdb);
if (in_p.m_maxDriftVel <= 0) then
if (in_vp.m_substrateDoping <> 0.0 and (xlamda <= 0.0)) then
argv := (vds - out_c.m_vdsat) / 4.0;
sargv := sqrt(1.0 + argv * argv);
arg := sqrt(argv + sargv);
xlfact := in_vp.m_xd / (out_c.m_lEff * vds);
xlamda := xlfact * arg;
dldsat := vds * xlamda / (8.0 * sargv);
dldvgs := dldsat * dsdvgs;
dldvds := -xlamda + dldsat;
dldvbs := dldsat * dsdvbs;
end if;
else
argv := (vgsx - vbin) / eta - out_c.m_vdsat;
xdv := in_vp.m_xd / sqrt(in_p.m_channelCharge);
xlv := in_p.m_maxDriftVel * xdv / (2.0 * ueff);
vqchan := argv - gammad * bsarg;
dqdsat := -1.0 + gammad * dbsrdb;
vl := in_p.m_maxDriftVel *out_c. m_lEff;
dfunds := vl * dqdsat - ueff * vqchan;
dfundg := (vl - ueff * out_c.m_vdsat) / eta;
dfundb := -vl * (1.0 + dqdsat - factor / eta) + ueff *
(gdbdvs - dgdvbs * bodys / 1.5) / eta;
dsdvgs := -dfundg / dfunds;
dsdvbs := -dfundb / dfunds;
if ((in_vp.m_substrateDoping <> 0.0) and (xlamda <= 0.0)) then
argv := vds - out_c.m_vdsat;
argv := max(argv,0.0);
xls := sqrt(xlv * xlv + argv);
dldsat := xdv / (2.0 * xls);
xlfact := xdv / (out_c.m_lEff * vds);
xlamda := xlfact * (xls - xlv);
dldsat := dldsat / out_c.m_lEff;
dldvgs := dldsat * dsdvgs;
dldvds := -xlamda + dldsat;
dldvbs := dldsat * dsdvbs;
end if;
end if;
end if;
// limit channel shortening at punch-through
xwb :=in_vp.m_xd*sqrt(out_c.m_tBulkPot);
xld :=out_c.m_lEff - xwb;
clfact :=1.0 - xlamda*vds;
dldvds :=-xlamda - dldvds;
xleff :=out_c.m_lEff*clfact;
deltal :=xlamda*vds*out_c.m_lEff;
if (in_vp.m_substrateDoping == 0.0) then
xwb := 0.25e-6;
end if;
if (xleff < xwb) then
xleff := xwb / (1.0 + (deltal - xld) / xwb);
clfact := xleff / out_c.m_lEff;
dfact := xleff * xleff / (xwb * xwb);
dldvgs := dfact * dldvgs;
dldvds := dfact * dldvds;
dldvbs := dfact * dldvbs;
end if;
// evaluate effective beta (effective kp)
beta1 := out_c.m_Beta * ufact / clfact;
// test for mode of operation and branch appropriately
gammad := gamasd;
dgdvbs := dgddvb;
if (vds <= 1.0e-10) then
if (vgs <= out_c.m_von) then
if ((in_p.m_fastSurfaceStateDensity == 0.0) or (out_c.m_capOx == 0.0)) then
out_c.m_gds := 0.0;
else
out_c.m_gds := beta1 * (out_c.m_von - vbin - gammad * sarg) * exp(argg * (vgs - out_c.m_von));
end if;
else
out_c.m_gds :=beta1*(vgs - vbin - gammad*sarg);
end if;
out_c.m_cdrain :=0.0;
out_c.m_gm :=0.0;
out_c.m_gmbs :=0.0;
return;
end if;
if (vgs <= out_c.m_von) then
// subthreshold region
if (out_c.m_vdsat <= 0) then
out_c.m_gds := 0.0;
if (vgs > vth) then
return;
end if;
out_c.m_cdrain := 0.0;
out_c.m_gm := 0.0;
out_c.m_gmbs := 0.0;
return;
end if;
vdson := min(out_c.m_vdsat, vds);
if (vds > out_c.m_vdsat) then
barg := bsarg;
dbrgdb := dbsrdb;
body := bodys;
gdbdv := gdbdvs;
end if;
cdson := beta1 * ((out_c.m_von - vbin - eta * vdson * 0.5) * vdson - gammad * body / 1.5);
didvds := beta1 * (out_c.m_von - vbin - eta * vdson - gammad * barg);
gdson := -cdson * dldvds / clfact - beta1 * dgdvds * body / 1.5;
if (vds < out_c.m_vdsat) then
gdson := gdson + didvds;
end if;
gbson := -cdson * dldvbs / clfact + beta1 *
(dodvbs * vdson + factor * vdson - dgdvbs * body / 1.5 - gdbdv);
if (vds > out_c.m_vdsat) then
gbson := gbson + didvds * dsdvbs;
end if;
expg := exp(argg * (vgs - out_c.m_von));
out_c.m_cdrain := cdson * expg;
gmw := out_c.m_cdrain * argg;
out_c.m_gm := gmw;
if (vds > out_c.m_vdsat) then
out_c.m_gm := gmw + didvds * dsdvgs * expg;
end if;
tmp := gmw * (vgs - out_c.m_von) / xn;
out_c.m_gds := gdson * expg - out_c.m_gm * dodvds - tmp * dxndvd;
out_c.m_gmbs := gbson * expg - out_c.m_gm * dodvbs - tmp * dxndvb;
elseif (vds <= out_c.m_vdsat) then
// linear region
out_c.m_cdrain := beta1 * ((vgs - vbin - eta * vds / 2.0) * vds - gammad * body / 1.5);
arg := out_c.m_cdrain * (dudvgs / ufact - dldvgs / clfact);
out_c.m_gm := arg + beta1 * vds;
arg := out_c.m_cdrain * (dudvds / ufact - dldvds / clfact);
out_c.m_gds := arg + beta1 * (vgs - vbin - eta *
vds - gammad * barg - dgdvds * body / 1.5);
arg := out_c.m_cdrain * (dudvbs / ufact - dldvbs / clfact);
out_c.m_gmbs := arg - beta1 * (gdbdv + dgdvbs * body / 1.5 - factor * vds);
else
// saturation region
out_c.m_cdrain := beta1 * ((vgs - vbin - eta *
out_c.m_vdsat / 2.0) * out_c.m_vdsat - gammad * bodys / 1.5);
arg := out_c.m_cdrain * (dudvgs / ufact - dldvgs / clfact);
out_c.m_gm := arg + beta1 * out_c.m_vdsat
+ beta1 * (vgs - vbin - eta * out_c.m_vdsat - gammad * bsarg) * dsdvgs;
out_c.m_gds := -out_c.m_cdrain * dldvds / clfact - beta1 * dgdvds * bodys / 1.5;
arg := out_c.m_cdrain * (dudvbs / ufact - dldvbs / clfact);
out_c.m_gmbs := arg - beta1 * (gdbdvs + dgdvbs * bodys / 1.5 - factor * out_c.m_vdsat)
+ beta1 * (vgs - vbin - eta * out_c.m_vdsat - gammad * bsarg) * dsdvbs;
end if;
end drainCur;
This function mos2RenameParameters assigns the external (given by the user, e.g., RD) technology parameters to the internal parameters (e.g., m_drainResistance). It also does the analysis of the IsGiven values (level 2).
| Type | Name | Default | Description |
|---|---|---|---|
| ModelcardMOS2 | ex | Modelcard with technologie parameters | |
| SpiceConstants | con | Spice constants |
| Type | Name | Description |
|---|---|---|
| Mos2ModelLineParams | intern | Output record model line parameters |
function mos2RenameParameters "Parameter renaming to internal names"
input ModelcardMOS2 ex "Modelcard with technologie parameters";
input SpiceConstants con "Spice constants";
output Mos2ModelLineParams intern "Output record model line parameters";
algorithm
intern.m_narrowFactor := ex.DELTA; // DELTA, Width effect on threshold
intern.m_critFieldExp := ex.UEXP; // UEXP, Crit. field exp for mob. deg
intern.m_critField := ex.UCRIT; // UCRIT, Crit. field for mob. degradation
intern.m_maxDriftVel := ex.VMAX; // VMAX, Maximum carrier drift velocity
intern.m_junctionDepth := ex.XJ; // XJ, Junction depth
intern.m_channelCharge := ex.NEFF; // NEFF, Total channel charge coeff
intern.m_fastSurfaceStateDensity := ex.NFS; // NFS, Fast surface state density
intern.m_oxideCapFactor := 0;
intern.m_vtOIsGiven := if (ex.VTO > -1e40) then 1 else 0;
intern.m_vt0 := if (ex.VTO > -1e40) then ex.VTO else 0;
intern.m_capBDIsGiven := if (ex.CBD > -1e40) then 1 else 0;
intern.m_capBD := if (ex.CBD > -1e40) then ex.CBD else 0;
intern.m_capBSIsGiven := if (ex.CBS > -1e40) then 1 else 0;
intern.m_capBS := if (ex.CBS > -1e40) then ex.CBS else 0;
intern.m_bulkCapFactor := ex.CJ; // F/(m*m) zero-bias bulk junction bottom cap. per sq-meter of junction area (default 0)
intern.m_sideWallCapFactor := ex.CJSW; // F/m zero-bias junction sidewall cap. per meter of junction perimeter (default 0)
intern.m_fwdCapDepCoeff := ex.FC; // coefficient for forward-bias depletion capacitance formula (default 0.5)
intern.m_phiIsGiven := if (ex.PHI > -1e40) then 1 else 0;
intern.m_phi := if (ex.PHI > -1e40) then ex.PHI else 0.6;
intern.m_gammaIsGiven := if (ex.GAMMA > -1e40) then 1 else 0;
intern.m_gamma := if (ex.GAMMA > -1e40) then ex.GAMMA else 0;
intern.m_lambda := ex.LAMBDA; // 1/V channel-length modulation (default 0)
intern.m_substrateDopingIsGiven := if (ex.NSUB > -1e40) then 1 else 0;
intern.m_substrateDoping := if (ex.NSUB > -1e40) then ex.NSUB else 0;
intern.m_gateType := ex.TPG; // type of gate material: +1 opp. to substrate, -1 same as substrate, 0 Al gate (default 1)
intern.m_surfaceStateDensity := ex.NSS; // 1/(cm*cm) surface state density (default 0)
intern.m_surfaceMobility := ex.UO; // (cm*cm)/(Vs) surface mobility (default 600)
intern.m_latDiff := ex.LD; // m lateral diffusion (default 0)
intern.m_jctSatCur := ex.IS; // A bulk junction saturation current (defaul 1e-14)
intern.m_drainResistanceIsGiven := if
(ex.RD > -1e40) then 1 else 0;
intern.m_drainResistance := if
(ex.RD > -1e40) then ex.RD else 0;
intern.m_sourceResistanceIsGiven := if
(ex.RS > -1e40) then 1 else 0;
intern.m_sourceResistance := if
(ex.RS > -1e40) then ex.RS else 0;
intern.m_transconductanceIsGiven := if (ex.KP > -1e40) then 1 else 0;
intern.m_transconductance := if (ex.KP > -1e40) then ex.KP else 2e-5;
intern.m_tnom := if (ex.TNOM > -1e40) then ex.TNOM + SpiceConstants.CONSTCtoK else
300.15;
intern.m_jctSatCurDensity := ex.JS; // A/(m*m) bulk junction saturation current per sq-meter of junction area (default 0)
intern.m_sheetResistance := ex.RSH; // Ohm drain and source diffusion sheet resistance (default 0)
intern.m_bulkJctPotential := ex.PB; // V bulk junction potential (default 0.8)
intern.m_bulkJctBotGradingCoeff := ex.MJ; // bulk junction bottom grading coeff. (default 0.5)
intern.m_bulkJctSideGradingCoeff := ex.MJSW; // bulk junction sidewall grading coeff. (default 0.5)
intern.m_oxideThickness := ex.TOX; // m oxide thickness (default 1e-7)
intern.m_oxideThicknessIsGiven := if (ex.TOX > -1e40) then 1 else 0;
intern.m_oxideThickness := if (ex.TOX > -1e40) then ex.TOX else 1e-7;
intern.m_gateSourceOverlapCapFactor := ex.CGSO; // F/m gate-source overlap capacitance per meter channel width (default 0)
intern.m_gateDrainOverlapCapFactor := ex.CGDO; // F/m gate-drain overlap capacitance per meter channel width (default 0)
intern.m_gateBulkOverlapCapFactor := ex.CGBO; // F/m gate-bulk overlap capacitance per meter channel width (default 0)
intern.m_fNcoef := ex.KF; // flicker-noise coefficient (default 0)
intern.m_fNexp := ex.AF; // flicker-noise exponent (default 1)
end mos2RenameParameters;
This function mos2RenameParameters assigns the external (given by the user) device parameters to the internal parameters. It also does the analysis of the IsGiven values (level 2).
| Type | Name | Default | Description |
|---|---|---|---|
| ModelcardMOS2 | ex | ||
| Integer | mtype | ||
| Length | W | Width of channel region [m] | |
| Length | L | Length of channel region [m] | |
| Area | AD | Area of drain diffusion [m2] | |
| Area | AS | Area of source diffusion [m2] | |
| Length | PD | Drain perimeter [m] | |
| Length | PS | Source perimeter [m] | |
| Real | NRD | Length of drain squares | |
| Real | NRS | Length of Source squares | |
| Integer | OFF | Optional initial condition: 0 - IC not used, 1 - IC used, not implemented yet | |
| Real | IC | Initial condition values, not implemented yet | |
| Temp_C | TEMP | Temperature [degC] |
| Type | Name | Description |
|---|---|---|
| Mosfet | dev | Output record Mosfet |
function mos2RenameParametersDev
"Device parameter renaming to internal names"
input ModelcardMOS2 ex;
input Integer mtype;
input Modelica.SIunits.Length W "Width of channel region";
input Modelica.SIunits.Length L "Length of channel region";
input Modelica.SIunits.Area AD "Area of drain diffusion";
input Modelica.SIunits.Area AS "Area of source diffusion";
input Modelica.SIunits.Length PD "Drain perimeter";
input Modelica.SIunits.Length PS "Source perimeter";
input Real NRD "Length of drain squares";
input Real NRS "Length of Source squares";
input Integer OFF
"Optional initial condition: 0 - IC not used, 1 - IC used, not implemented yet";
input Real IC "Initial condition values, not implemented yet";
input Modelica.SIunits.Temp_C TEMP "Temperature";
output Mosfet.Mosfet dev "Output record Mosfet";
algorithm
/*device parameters*/
dev.m_len := L; // L, length of channel region
dev.m_width := W; // W, width of channel region
dev.m_drainArea := AD; // AD, area of drain diffusion
dev.m_sourceArea := AS; // AS, area of source diffusion
dev.m_drainSquares := NRD; // NRD, length of drain in squares
dev.m_sourceSquares := NRS; // NRS, length of source in squares
dev.m_drainPerimiter := PD; // PD, Drain perimeter;
dev.m_sourcePerimiter := PS; // PS, Source perimeter
dev.m_dICVDSIsGiven := if (IC > -1e40) then 1 else 0;
dev.m_dICVDS := if (IC > -1e40) then IC else 0;
dev.m_dICVGSIsGiven := if (IC > -1e40) then 1 else 0;
dev.m_dICVGS := if (IC > -1e40) then IC else 0;
dev.m_dICVBSIsGiven := if (IC > -1e40) then 1 else 0;
dev.m_dICVBS := if (IC > -1e40) then IC else 0;
dev.m_off := OFF; // non-zero to indicate device is off for dc analysis
dev.m_bPMOS := mtype; // P type MOSfet model
dev.m_nLevel := ex.LEVEL;
assert(ex.LEVEL== 1, "only MOS Level1 implemented");
dev.m_dTemp :=TEMP + SpiceConstants.CONSTCtoK;
end mos2RenameParametersDev;