Browse Source

add weak inversion current capability

calibration of parameter subthres with LTSPICE is still missing.
pre-master-46
Holger Vogt 8 years ago
committed by rlar
parent
commit
62297b2450
  1. 3
      src/spicelib/devices/vdmos/vdmos.c
  2. 3
      src/spicelib/devices/vdmos/vdmosdefs.h
  3. 117
      src/spicelib/devices/vdmos/vdmosload.c
  4. 3
      src/spicelib/devices/vdmos/vdmosmask.c
  5. 4
      src/spicelib/devices/vdmos/vdmosmpar.c
  6. 3
      src/spicelib/devices/vdmos/vdmosset.c

3
src/spicelib/devices/vdmos/vdmos.c

@ -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"),

3
src/spicelib/devices/vdmos/vdmosdefs.h

@ -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,

117
src/spicelib/devices/vdmos/vdmosload.c

@ -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;
}

3
src/spicelib/devices/vdmos/vdmosmask.c

@ -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";

4
src/spicelib/devices/vdmos/vdmosmpar.c

@ -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;

3
src/spicelib/devices/vdmos/vdmosset.c

@ -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…
Cancel
Save