diff --git a/src/spicelib/devices/vdmos/vdmos.c b/src/spicelib/devices/vdmos/vdmos.c index 43f233e50..29e8ab2fe 100644 --- a/src/spicelib/devices/vdmos/vdmos.c +++ b/src/spicelib/devices/vdmos/vdmos.c @@ -83,6 +83,7 @@ IFparm VDMOSmPTable[] = { /* model parameters */ /* weak inversion */ IOP("subthres", VDMOS_MOD_SUBTHRES, IF_REAL, "Current(per volt Vds) to switch from square law to exponential subthreshold conduction"), + IOP("subshift", VDMOS_MOD_SUBSHIFT, IF_REAL, "Shift of weak inversion plot on the vgs axis"), /* body diode */ IOP("bv", VDMOS_MOD_BV, IF_REAL, "Vds breakdown voltage"), diff --git a/src/spicelib/devices/vdmos/vdmosdefs.h b/src/spicelib/devices/vdmos/vdmosdefs.h index eb2675a24..cf9a58c97 100644 --- a/src/spicelib/devices/vdmos/vdmosdefs.h +++ b/src/spicelib/devices/vdmos/vdmosdefs.h @@ -332,6 +332,7 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */ double VDMOSa; double VDMOScgs; double VDMOSsubth; + double VDMOSsubshift; double VDMOSmtr; /* bulk diode */ @@ -377,6 +378,7 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */ unsigned VDMOScgsGiven :1; unsigned VDMOSaGiven :1; unsigned VDMOSsubthGiven :1; + unsigned VDMOSsubshiftGiven :1; unsigned VDMOSmtrGiven :1; unsigned VDMOSDbvGiven :1; @@ -443,6 +445,7 @@ enum { VDMOS_MOD_RB, VDMOS_MOD_MTRIODE, VDMOS_MOD_SUBTHRES, + VDMOS_MOD_SUBSHIFT, VDMOS_MOD_BV, VDMOS_MOD_IBV, VDMOS_MOD_NBV, diff --git a/src/spicelib/devices/vdmos/vdmosload.c b/src/spicelib/devices/vdmos/vdmosload.c index 453623a37..ffd3a8aaf 100644 --- a/src/spicelib/devices/vdmos/vdmosload.c +++ b/src/spicelib/devices/vdmos/vdmosload.c @@ -15,7 +15,7 @@ VDMOS: 2018 Holger Vogt #include "ngspice/suffix.h" static double -cweakinv(double n, double vgst, double vds, double lambda, double beta, double vt, double mtr); +cweakinv(double n, double shift, double vgst, double vds, double lambda, double beta, double vt, double mtr); int @@ -369,22 +369,22 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt) * 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, + cdrain = cweakinv(model->VDMOSsubth, model->VDMOSsubshift, vgst, vds, model->VDMOSlambda, Beta, vt, model->VDMOSmtr); /* gd */ double vds1 = vds + delta; - double cdrp = cweakinv(model->VDMOSsubth, vgst, vds1, model->VDMOSlambda, + double cdrp = cweakinv(model->VDMOSsubth, model->VDMOSsubshift, vgst, vds1, model->VDMOSlambda, Beta, vt, model->VDMOSmtr); vds1 = vds - delta; - double cdrm = cweakinv(model->VDMOSsubth, vgst, vds1, model->VDMOSlambda, + double cdrm = cweakinv(model->VDMOSsubth, model->VDMOSsubshift, 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, + cdrp = cweakinv(model->VDMOSsubth, model->VDMOSsubshift, vgst1, vds, model->VDMOSlambda, Beta, vt, model->VDMOSmtr); vgst1 = vgst - delta; - cdrm = cweakinv(model->VDMOSsubth, vgst1, vds, model->VDMOSlambda, + cdrm = cweakinv(model->VDMOSsubth, model->VDMOSsubshift, vgst1, vds, model->VDMOSlambda, Beta, vt, model->VDMOSmtr); here->VDMOSgm = (cdrp - cdrm) / (2. * delta); here->VDMOSgmbs = 0.; @@ -888,14 +888,15 @@ scalef(double nf2, double vgst) */ static double -cweakinv(double n, double vgst, double vds, double lambda, double beta, double vt, double mtr) +cweakinv(double slope, double shift, double vgst, double vds, double lambda, double beta, double vt, double mtr) { - double nf2 = 0.1; /* empirical setting of sin 'speed' */ - double n1 = n + (1 - n) * scalef(nf2, vgst); /* n < n1 < 1 */ + vgst += shift * (1 - scalef(2, vgst)); + double n = slope / 2.3 / 0.0256; /* Tsividis, p. 208 */ + double n1 = n + (1 - n) * scalef(2, vgst); /* 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(nf2, vgst) * lambda * vds) * + beta * n1 * 2 * vt * vt * (1 + scalef(2, vgst) * lambda * vds) * (first * first - second * second); return cds; } diff --git a/src/spicelib/devices/vdmos/vdmosmask.c b/src/spicelib/devices/vdmos/vdmosmask.c index 967e8dac5..86ae8c957 100644 --- a/src/spicelib/devices/vdmos/vdmosmask.c +++ b/src/spicelib/devices/vdmos/vdmosmask.c @@ -51,6 +51,9 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value) case VDMOS_MOD_SUBTHRES: value->rValue = model->VDMOSsubth; return(OK); + case VDMOS_MOD_SUBSHIFT: + value->rValue = model->VDMOSsubshift; + return(OK); case VDMOS_MOD_TYPE: if (model->VDMOStype > 0) value->sValue = "vdmosn"; diff --git a/src/spicelib/devices/vdmos/vdmosmpar.c b/src/spicelib/devices/vdmos/vdmosmpar.c index 0d4dd5c68..c1309f4d7 100644 --- a/src/spicelib/devices/vdmos/vdmosmpar.c +++ b/src/spicelib/devices/vdmos/vdmosmpar.c @@ -125,6 +125,10 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel) model->VDMOSsubth = value->rValue; model->VDMOSsubthGiven = TRUE; break; + case VDMOS_MOD_SUBSHIFT: + model->VDMOSsubshift = value->rValue; + model->VDMOSsubshiftGiven = TRUE; + break; case VDMOS_MOD_BV: model->VDMOSDbv = value->rValue; model->VDMOSDbvGiven = TRUE; diff --git a/src/spicelib/devices/vdmos/vdmosset.c b/src/spicelib/devices/vdmos/vdmosset.c index 55bcad319..d0cfe18ba 100644 --- a/src/spicelib/devices/vdmos/vdmosset.c +++ b/src/spicelib/devices/vdmos/vdmosset.c @@ -75,6 +75,9 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, if (!model->VDMOSsubthGiven) { model->VDMOSsubth = 0; } + if (!model->VDMOSsubshiftGiven) { + model->VDMOSsubshift = 0; + } if (!model->VDMOSmtrGiven) { model->VDMOSmtr = 1.; }