add weak inversion current capability
calibration of parameter subthres with LTSPICE is still missing.
This commit is contained in:
parent
013d70681f
commit
62297b2450
|
|
@ -94,6 +94,9 @@ IFparm VDMOSmPTable[] = { /* model parameters */
|
|||
|
||||
IOP("mtriode", VDMOS_MOD_MTRIODE, IF_REAL, "Conductance multiplier in triode region"),
|
||||
|
||||
/* weak inversion */
|
||||
IOP("subthres", VDMOS_MOD_SUBTHRES, IF_REAL, "Current(per volt Vds) to switch from square law to exponential subthreshold conduction"),
|
||||
|
||||
/* body diode */
|
||||
IOP("bv", VDMOS_MOD_BV, IF_REAL, "Vds breakdown voltage"),
|
||||
IOP("ibv", VDMOS_MOD_IBV, IF_REAL, "Current at Vds=bv"),
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOScgdmax;
|
||||
double VDMOSa;
|
||||
double VDMOScgs;
|
||||
double VDMOSsubth;
|
||||
double VDMOSmtr;
|
||||
|
||||
/* bulk diode */
|
||||
|
|
@ -375,6 +376,7 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOScgdmaxGiven :1;
|
||||
unsigned VDMOScgsGiven :1;
|
||||
unsigned VDMOSaGiven :1;
|
||||
unsigned VDMOSsubthGiven :1;
|
||||
unsigned VDMOSmtrGiven :1;
|
||||
|
||||
unsigned VDMOSDbvGiven :1;
|
||||
|
|
@ -441,6 +443,7 @@ enum {
|
|||
VDMOS_MOD_CGS,
|
||||
VDMOS_MOD_RB,
|
||||
VDMOS_MOD_MTRIODE,
|
||||
VDMOS_MOD_SUBTHRES,
|
||||
VDMOS_MOD_BV,
|
||||
VDMOS_MOD_IBV,
|
||||
VDMOS_MOD_NBV,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ VDMOS: 2018 Holger Vogt
|
|||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/suffix.h"
|
||||
|
||||
static double
|
||||
cweakinv(double n, double vgst, double vds, double lambda, double beta, double vt, double mtr);
|
||||
|
||||
|
||||
int
|
||||
VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
||||
/* actually load the current value into the
|
||||
|
|
@ -361,38 +365,63 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vgst = (here->VDMOSmode == 1 ? vgs : vgd) - von;
|
||||
vdsat = MAX(vgst, 0);
|
||||
arg = 0;
|
||||
if (vgst <= 0) {
|
||||
/*
|
||||
* cutoff region
|
||||
*/
|
||||
cdrain = 0;
|
||||
here->VDMOSgm = 0;
|
||||
here->VDMOSgds = 0;
|
||||
here->VDMOSgmbs = 0;
|
||||
/* drain current including subthreshold current
|
||||
* numerical differentiation for gd and gm with a delta of 2 mV */
|
||||
if (model->VDMOSsubthGiven && (here->VDMOSmode == 1)) {
|
||||
double delta = 0.001;
|
||||
cdrain = cweakinv(model->VDMOSsubth, vgst, vds, model->VDMOSlambda,
|
||||
Beta, vt, model->VDMOSmtr);
|
||||
/* gd */
|
||||
double vds1 = vds + delta;
|
||||
double cdrp = cweakinv(model->VDMOSsubth, vgst, vds1, model->VDMOSlambda,
|
||||
Beta, vt, model->VDMOSmtr);
|
||||
vds1 = vds - delta;
|
||||
double cdrm = cweakinv(model->VDMOSsubth, vgst, vds1, model->VDMOSlambda,
|
||||
Beta, vt, model->VDMOSmtr);
|
||||
here->VDMOSgds = (cdrp - cdrm) / (2. * delta);
|
||||
/* gm */
|
||||
double vgst1 = vgst + delta;
|
||||
cdrp = cweakinv(model->VDMOSsubth, vgst1, vds, model->VDMOSlambda,
|
||||
Beta, vt, model->VDMOSmtr);
|
||||
vgst1 = vgst - delta;
|
||||
cdrm = cweakinv(model->VDMOSsubth, vgst1, vds, model->VDMOSlambda,
|
||||
Beta, vt, model->VDMOSmtr);
|
||||
here->VDMOSgm = (cdrp - cdrm) / (2. * delta);
|
||||
here->VDMOSgmbs = 0.;
|
||||
} else {
|
||||
/*
|
||||
* saturation region
|
||||
*/
|
||||
/* scale vds with mtr */
|
||||
double mtr = model->VDMOSmtr;
|
||||
betap = Beta*(1 + model->VDMOSlambda*(vds*here->VDMOSmode));
|
||||
if (vgst <= (vds * here->VDMOSmode) * mtr) {
|
||||
cdrain = betap*vgst*vgst*.5;
|
||||
here->VDMOSgm = betap*vgst;
|
||||
here->VDMOSgds = model->VDMOSlambda*Beta*vgst*vgst*.5;
|
||||
here->VDMOSgmbs = here->VDMOSgm*arg;
|
||||
if (vgst <= 0) {
|
||||
/*
|
||||
* cutoff region
|
||||
*/
|
||||
cdrain = 0;
|
||||
here->VDMOSgm = 0;
|
||||
here->VDMOSgds = 0;
|
||||
here->VDMOSgmbs = 0;
|
||||
} else {
|
||||
/*
|
||||
* linear region
|
||||
* saturation region
|
||||
*/
|
||||
cdrain = betap * (vds * here->VDMOSmode) * mtr *
|
||||
(vgst - .5 * (vds*here->VDMOSmode) * mtr);
|
||||
here->VDMOSgm = betap * (vds * here->VDMOSmode) * mtr;
|
||||
here->VDMOSgds = betap * (vgst - (vds * here->VDMOSmode) * mtr) +
|
||||
model->VDMOSlambda * Beta *
|
||||
(vds * here->VDMOSmode) * mtr *
|
||||
(vgst - .5 * (vds * here->VDMOSmode) * mtr);
|
||||
here->VDMOSgmbs = here->VDMOSgm * arg;
|
||||
/* scale vds with mtr */
|
||||
double mtr = model->VDMOSmtr;
|
||||
betap = Beta*(1 + model->VDMOSlambda*(vds*here->VDMOSmode));
|
||||
if (vgst <= (vds * here->VDMOSmode) * mtr) {
|
||||
cdrain = betap*vgst*vgst*.5;
|
||||
here->VDMOSgm = betap*vgst;
|
||||
here->VDMOSgds = model->VDMOSlambda*Beta*vgst*vgst*.5;
|
||||
here->VDMOSgmbs = here->VDMOSgm*arg;
|
||||
} else {
|
||||
/*
|
||||
* linear region
|
||||
*/
|
||||
cdrain = betap * (vds * here->VDMOSmode) * mtr *
|
||||
(vgst - .5 * (vds*here->VDMOSmode) * mtr);
|
||||
here->VDMOSgm = betap * (vds * here->VDMOSmode) * mtr;
|
||||
here->VDMOSgds = betap * (vgst - (vds * here->VDMOSmode) * mtr) +
|
||||
model->VDMOSlambda * Beta *
|
||||
(vds * here->VDMOSmode) * mtr *
|
||||
(vgst - .5 * (vds * here->VDMOSmode) * mtr);
|
||||
here->VDMOSgmbs = here->VDMOSgm * arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -829,3 +858,35 @@ load :
|
|||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* Calculate D/S current including weak inversion.
|
||||
* Uses a single function covering weak-moderate-stong inversion, as well
|
||||
* as linear and saturation regions, with an interpolation method according to
|
||||
* Tvividis, McAndrew: "Operation and Modeling of the MOS Transistor", Oxford, 2011, p. 209.
|
||||
* A single parameter n sets the slope of the weak inversion current. The weak inversion
|
||||
* current is independent from vds, as in long channel devices.
|
||||
* The following modification has been added for VDMOS compatibility:
|
||||
* n and lambda are depending on vgst with a sine function interpolating between 0 and 1.
|
||||
*/
|
||||
|
||||
static double
|
||||
cweakinv(double n, double vgst, double vds, double lambda, double beta, double vt, double mtr)
|
||||
{
|
||||
double scalef;
|
||||
double nf2 = 0.1; /* empirical setting of sin 'speed' */
|
||||
double vgstsin = vgst / nf2;
|
||||
if (vgstsin > 1)
|
||||
scalef = 1;
|
||||
else if (vgstsin < -1)
|
||||
scalef = 0;
|
||||
else
|
||||
scalef = 0.5 * sin(vgstsin * M_PI / 2) + 0.5;
|
||||
double n1 = n + (1 - n) * scalef; /* n < n1 < 1 */
|
||||
double first = log(1 + exp(vgst / (2 * n1 * vt)));
|
||||
double second = log(1 + exp((vgst - vds * mtr * n1) / (2 * n1 * vt)));
|
||||
double cds =
|
||||
beta * n1 * 2 * vt * vt * (1 + scalef * lambda * vds) *
|
||||
(first * first - second * second);
|
||||
return cds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
|
|||
case VDMOS_MOD_MTRIODE:
|
||||
value->rValue = model->VDMOSmtr;
|
||||
return(OK);
|
||||
case VDMOS_MOD_SUBTHRES:
|
||||
value->rValue = model->VDMOSsubth;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TYPE:
|
||||
if (model->VDMOStype > 0)
|
||||
value->sValue = "vdmosn";
|
||||
|
|
|
|||
|
|
@ -121,6 +121,10 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSmtr = value->rValue;
|
||||
model->VDMOSmtrGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_SUBTHRES:
|
||||
model->VDMOSsubth = value->rValue;
|
||||
model->VDMOSsubthGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_BV:
|
||||
model->VDMOSDbv = value->rValue;
|
||||
model->VDMOSDbvGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDMOSaGiven) {
|
||||
model->VDMOSa = 1.;
|
||||
}
|
||||
if (!model->VDMOSsubthGiven) {
|
||||
model->VDMOSsubth = 0;
|
||||
}
|
||||
if (!model->VDMOSmtrGiven) {
|
||||
model->VDMOSmtr = 1.;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue