restructering thermal update by unified function
introduce diode series resistor thermal contribution separate naming of mos and diode model parameter
This commit is contained in:
parent
f07a17878a
commit
280bea9d50
|
|
@ -94,8 +94,8 @@ IFparm VDMOSmPTable[] = { /* model parameters */
|
|||
IOP( "trg2", VDMOS_MOD_TRG2, IF_REAL, "Gate resistance quadratic temperature coefficient"),
|
||||
IOP( "trs1", VDMOS_MOD_TRS1, IF_REAL, "Source resistance linear temperature coefficient"),
|
||||
IOP( "trs2", VDMOS_MOD_TRS2, IF_REAL, "Source resistance quadratic temperature coefficient"),
|
||||
IOP( "trb1", VDMOS_MOD_TRB1, IF_REAL, "Body resistance linear temperature coefficient"),
|
||||
IOP( "trb2", VDMOS_MOD_TRB2, IF_REAL, "Body resistance quadratic temperature coefficient"),
|
||||
IOP( "trb1", VDIO_MOD_TRB1, IF_REAL, "Body resistance linear temperature coefficient"),
|
||||
IOP( "trb2", VDIO_MOD_TRB2, IF_REAL, "Body resistance quadratic temperature coefficient"),
|
||||
|
||||
/* weak inversion */
|
||||
IOP("subshift", VDMOS_MOD_SUBSHIFT, IF_REAL, "Shift of weak inversion plot on the vgs axis"),
|
||||
|
|
@ -104,22 +104,22 @@ IFparm VDMOSmPTable[] = { /* model parameters */
|
|||
IOP("tksubthres2", VDMOS_MOD_TKSUBTHRES2, IF_REAL, "Quadratic temperature coefficient of ksubthres"),
|
||||
|
||||
/* body diode */
|
||||
IOP("bv", VDMOS_MOD_BV, IF_REAL, "Vds breakdown voltage"),
|
||||
IOP("ibv", VDMOS_MOD_IBV, IF_REAL, "Current at Vds=bv"),
|
||||
IOP("nbv", VDMOS_MOD_NBV, IF_REAL, "Vds breakdown emission coefficient"),
|
||||
IOP("bv", VDIO_MOD_BV, IF_REAL, "Vds breakdown voltage"),
|
||||
IOP("ibv", VDIO_MOD_IBV, IF_REAL, "Current at Vds=bv"),
|
||||
IOP("nbv", VDIO_MOD_NBV, IF_REAL, "Vds breakdown emission coefficient"),
|
||||
IOP("rds", VDMOS_MOD_RDS, IF_REAL, "Drain-source shunt resistance"),
|
||||
IOP("rb", VDMOS_MOD_RB, IF_REAL, "Body diode ohmic resistance"),
|
||||
IOP("n", VDMOS_MOD_N, IF_REAL, "Body diode emission coefficient"),
|
||||
IOP("tt", VDMOS_MOD_TT, IF_REAL, "Body diode transit time"),
|
||||
IOP("eg", VDMOS_MOD_EG, IF_REAL, "Body diode activation energy for temperature effect on Is"),
|
||||
IOP("xti", VDMOS_MOD_XTI, IF_REAL, "Body diode saturation current temperature exponent"),
|
||||
IOP("is", VDMOS_MOD_IS, IF_REAL, "Body diode saturation current"),
|
||||
IOP("vj", VDMOS_MOD_VJ, IF_REAL, "Body diode junction potential"),
|
||||
IOP("rb", VDIO_MOD_RB, IF_REAL, "Body diode ohmic resistance"),
|
||||
IOP("n", VDIO_MOD_N, IF_REAL, "Body diode emission coefficient"),
|
||||
IOP("tt", VDIO_MOD_TT, IF_REAL, "Body diode transit time"),
|
||||
IOP("eg", VDIO_MOD_EG, IF_REAL, "Body diode activation energy for temperature effect on Is"),
|
||||
IOP("xti", VDIO_MOD_XTI, IF_REAL, "Body diode saturation current temperature exponent"),
|
||||
IOP("is", VDIO_MOD_IS, IF_REAL, "Body diode saturation current"),
|
||||
IOP("vj", VDIO_MOD_VJ, IF_REAL, "Body diode junction potential"),
|
||||
|
||||
/* body diode capacitance (e.g. source-drain capacitance) */
|
||||
IOP("fc", VDMOS_MOD_FC, IF_REAL, "Body diode coefficient for forward-bias depletion capacitance formula"),
|
||||
IOPA("cjo", VDMOS_MOD_CJ, IF_REAL, "Zero-bias body diode junction capacitance"),
|
||||
IOP("m", VDMOS_MOD_MJ, IF_REAL, "Body diode grading coefficient"),
|
||||
IOP("fc", VDIO_MOD_FC, IF_REAL, "Body diode coefficient for forward-bias depletion capacitance formula"),
|
||||
IOPA("cjo", VDIO_MOD_CJ, IF_REAL, "Zero-bias body diode junction capacitance"),
|
||||
IOP("m", VDIO_MOD_MJ, IF_REAL, "Body diode grading coefficient"),
|
||||
|
||||
/* gate-source and gate-drain capacitances */
|
||||
IOPA("cgdmin", VDMOS_MOD_CGDMIN, IF_REAL, "Minimum non-linear G-D capacitance"),
|
||||
|
|
|
|||
|
|
@ -78,11 +78,13 @@ typedef struct sVDMOSinstance {
|
|||
double VDMOSgds;
|
||||
|
||||
double VDIOcap;
|
||||
double VDIOtSatCur; /* temperature corrected saturation Cur. density*/
|
||||
double VDIOtSatCur; /* temperature corrected saturation Cur. density */
|
||||
double VDIOtSatCur_dT;
|
||||
double VDIOinitCond;
|
||||
double VDIOtVcrit;
|
||||
double VDIOconductance;
|
||||
double VDIOtConductance;
|
||||
double VDIOtConductance_dT;
|
||||
double VDIOtBrkdwnV;
|
||||
double VDIOtJctCap;
|
||||
double VDIOtDepCap; /* temperature adjusted transition point in */
|
||||
|
|
@ -105,7 +107,6 @@ typedef struct sVDMOSinstance {
|
|||
double VDMOScdT;
|
||||
double VDMOScth; /* current alias power */
|
||||
|
||||
// double VDIOdIth_dVdio;
|
||||
/*
|
||||
* naming convention:
|
||||
* x = vgs
|
||||
|
|
@ -233,6 +234,8 @@ typedef struct sVDMOSinstance {
|
|||
double *VDMOSTempdPtr;
|
||||
double *VDIOPosPrimetempPtr;
|
||||
double *VDMOSDtempPtr;
|
||||
double *VDMOStempSPtr;
|
||||
double *VDMOSSTempPtr;
|
||||
|
||||
double *VDMOSTcasetcasePtr; /* for Rthjc */
|
||||
double *VDMOSTcasetempPtr;
|
||||
|
|
@ -315,26 +318,28 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOSsubshift;
|
||||
double VDMOSksubthres;
|
||||
double VDMOSmtr;
|
||||
double VDMOSrds;
|
||||
|
||||
/* body diode */
|
||||
double VDIOjunctionCap; /* input - use tCj */
|
||||
double VDIOjunctionPot; /* input - use tJctPot */
|
||||
double VDIOdepletionCapCoeff;
|
||||
double VDIOjctSatCur; /* input - use tSatCur */
|
||||
double VDMOSbv;
|
||||
double VDMOSibv;
|
||||
double VDIObv;
|
||||
double VDIOibv;
|
||||
double VDIObrkdEmissionCoeff;
|
||||
double VDIOresistance;
|
||||
double VDMOSrds;
|
||||
double VDMOSn;
|
||||
double VDIOn;
|
||||
double VDIOtransitTime;
|
||||
double VDIOtranTimeTemp1;
|
||||
double VDIOtranTimeTemp2;
|
||||
double VDMOSeg;
|
||||
double VDMOSxti;
|
||||
double VDIOeg;
|
||||
double VDIOxti;
|
||||
double VDIOgradCoeff;
|
||||
double VDIOgradCoeffTemp1;
|
||||
double VDIOgradCoeffTemp2;
|
||||
double VDIOtrb1;
|
||||
double VDIOtrb2;
|
||||
|
||||
double VDMOStcvth;
|
||||
double VDMOSrthjc;
|
||||
|
|
@ -349,8 +354,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOStrg2;
|
||||
double VDMOStrs1;
|
||||
double VDMOStrs2;
|
||||
double VDMOStrb1;
|
||||
double VDMOStrb2;
|
||||
double VDMOStksubthres1;
|
||||
double VDMOStksubthres2;
|
||||
|
||||
|
|
@ -361,7 +364,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
double VDMOSvgdrMax;
|
||||
|
||||
unsigned VDMOStypeGiven :1;
|
||||
unsigned VDIOjctSatCurGiven :1;
|
||||
unsigned VDMOSdrainResistanceGiven :1;
|
||||
unsigned VDMOSsourceResistanceGiven :1;
|
||||
unsigned VDMOSgateResistanceGiven :1;
|
||||
|
|
@ -370,8 +372,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOSqsGiven :1;
|
||||
unsigned VDMOStransconductanceGiven :1;
|
||||
unsigned VDMOSvth0Given :1;
|
||||
unsigned VDIOgradCoeffGiven :1;
|
||||
unsigned VDIOdepletionCapCoeffGiven :1;
|
||||
unsigned VDMOSphiGiven :1;
|
||||
unsigned VDMOSlambdaGiven :1;
|
||||
unsigned VDMOSthetaGiven :1;
|
||||
|
|
@ -386,18 +386,23 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOSsubshiftGiven :1;
|
||||
unsigned VDMOSksubthresGiven :1;
|
||||
unsigned VDMOSmtrGiven :1;
|
||||
unsigned VDMOSrdsGiven :1;
|
||||
|
||||
unsigned VDMOSbvGiven :1;
|
||||
unsigned VDMOSibvGiven :1;
|
||||
unsigned VDIOjctSatCurGiven :1;
|
||||
unsigned VDIOgradCoeffGiven :1;
|
||||
unsigned VDIOdepletionCapCoeffGiven :1;
|
||||
unsigned VDIObvGiven :1;
|
||||
unsigned VDIOibvGiven :1;
|
||||
unsigned VDIOjunctionCapGiven :1;
|
||||
unsigned VDIOjunctionPotGiven :1;
|
||||
unsigned VDIObrkdEmissionCoeffGiven :1;
|
||||
unsigned VDIOresistanceGiven :1;
|
||||
unsigned VDMOSrdsGiven :1;
|
||||
unsigned VDMOSnGiven :1;
|
||||
unsigned VDIOnGiven :1;
|
||||
unsigned VDIOtransitTimeGiven :1;
|
||||
unsigned VDMOSegGiven :1;
|
||||
unsigned VDMOSxtiGiven :1;
|
||||
unsigned VDIOegGiven :1;
|
||||
unsigned VDIOxtiGiven :1;
|
||||
unsigned VDIOtrb1Given :1;
|
||||
unsigned VDIOtrb2Given :1;
|
||||
|
||||
unsigned VDMOStcvthGiven :1;
|
||||
unsigned VDMOSrthjcGiven :1;
|
||||
|
|
@ -412,8 +417,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
|
|||
unsigned VDMOStrg2Given :1;
|
||||
unsigned VDMOStrs1Given :1;
|
||||
unsigned VDMOStrs2Given :1;
|
||||
unsigned VDMOStrb1Given :1;
|
||||
unsigned VDMOStrb2Given :1;
|
||||
unsigned VDMOStksubthres1Given :1;
|
||||
unsigned VDMOStksubthres2Given :1;
|
||||
|
||||
|
|
@ -456,11 +459,6 @@ enum {
|
|||
VDMOS_MOD_RG,
|
||||
VDMOS_MOD_RQ,
|
||||
VDMOS_MOD_VQ,
|
||||
VDMOS_MOD_IS,
|
||||
VDMOS_MOD_VJ,
|
||||
VDMOS_MOD_CJ,
|
||||
VDMOS_MOD_MJ,
|
||||
VDMOS_MOD_FC,
|
||||
VDMOS_MOD_NMOS,
|
||||
VDMOS_MOD_PMOS,
|
||||
VDMOS_MOD_TNOM,
|
||||
|
|
@ -472,18 +470,25 @@ enum {
|
|||
VDMOS_MOD_CGDMAX,
|
||||
VDMOS_MOD_A,
|
||||
VDMOS_MOD_CGS,
|
||||
VDMOS_MOD_RB,
|
||||
VDMOS_MOD_MTRIODE,
|
||||
VDMOS_MOD_SUBSHIFT,
|
||||
VDMOS_MOD_KSUBTHRES,
|
||||
VDMOS_MOD_BV,
|
||||
VDMOS_MOD_IBV,
|
||||
VDMOS_MOD_NBV,
|
||||
VDMOS_MOD_RDS,
|
||||
VDMOS_MOD_N,
|
||||
VDMOS_MOD_TT,
|
||||
VDMOS_MOD_EG,
|
||||
VDMOS_MOD_XTI,
|
||||
VDIO_MOD_IS,
|
||||
VDIO_MOD_VJ,
|
||||
VDIO_MOD_CJ,
|
||||
VDIO_MOD_MJ,
|
||||
VDIO_MOD_FC,
|
||||
VDIO_MOD_RB,
|
||||
VDIO_MOD_BV,
|
||||
VDIO_MOD_IBV,
|
||||
VDIO_MOD_NBV,
|
||||
VDIO_MOD_N,
|
||||
VDIO_MOD_TT,
|
||||
VDIO_MOD_EG,
|
||||
VDIO_MOD_XTI,
|
||||
VDIO_MOD_TRB1,
|
||||
VDIO_MOD_TRB2,
|
||||
VDMOS_MOD_TCVTH,
|
||||
VDMOS_MOD_RTHJC,
|
||||
VDMOS_MOD_RTHCA,
|
||||
|
|
@ -497,8 +502,6 @@ enum {
|
|||
VDMOS_MOD_TRG2,
|
||||
VDMOS_MOD_TRS1,
|
||||
VDMOS_MOD_TRS2,
|
||||
VDMOS_MOD_TRB1,
|
||||
VDMOS_MOD_TRB2,
|
||||
VDMOS_MOD_TKSUBTHRES1,
|
||||
VDMOS_MOD_TKSUBTHRES2,
|
||||
VDMOS_MOD_VGS_MAX,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ VDMOS: 2018 Holger Vogt, 2020 Dietmar Warning
|
|||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/suffix.h"
|
||||
|
||||
void VDMOStempUpdate(VDMOSmodel *inModel, VDMOSinstance *here, double Temp, CKTcircuit *ckt);
|
||||
|
||||
int
|
||||
VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
||||
/* actually load the current value into the
|
||||
|
|
@ -279,7 +281,12 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
}
|
||||
|
||||
Temp = here->VDMOStemp + delTemp;
|
||||
if (selfheat) {
|
||||
Temp = here->VDMOStemp + delTemp;
|
||||
VDMOStempUpdate(model, here, Temp, ckt);
|
||||
} else {
|
||||
Temp = here->VDMOStemp;
|
||||
}
|
||||
here->VDMOSTempSH = Temp; /* added for portability of SH Temp for noise analysis */
|
||||
|
||||
/* Calculate temperature dependent values for self-heating effect */
|
||||
|
|
@ -665,14 +672,15 @@ bypass:
|
|||
double vd, cd;
|
||||
double vte;
|
||||
double vtebrk, vbrknp;
|
||||
double cdb, csat, cdeq;
|
||||
double cdb, cdeq;
|
||||
double capd;
|
||||
double gd, gdb, gspr;
|
||||
double delvd; /* change in diode voltage temporary */
|
||||
double evrev;
|
||||
double Ith=0.0, dIth_dT=0.0;
|
||||
double dIdio_dT=0.0, dIth_dVdio=0.0;
|
||||
double arg1, darg1_dT, arg2, darg2_dT, csat_dT;
|
||||
double vrs=0.0, dIrs_dT=0.0, dIth_dVrs=0.0;
|
||||
|
||||
#ifndef NOBYPASS
|
||||
double tol; /* temporary for tolerance calculations */
|
||||
#endif
|
||||
|
|
@ -684,7 +692,7 @@ bypass:
|
|||
gspr = here->VDIOtConductance;
|
||||
|
||||
vt = CONSTKoverQ * Temp;
|
||||
vte = model->VDMOSn * vt;
|
||||
vte = model->VDIOn * vt;
|
||||
vtebrk = model->VDIObrkdEmissionCoeff * vt;
|
||||
vbrknp = here->VDIOtBrkdwnV;
|
||||
|
||||
|
|
@ -751,7 +759,7 @@ bypass:
|
|||
/*
|
||||
* limit new junction voltage
|
||||
*/
|
||||
if ((model->VDMOSbvGiven) &&
|
||||
if ((model->VDIObvGiven) &&
|
||||
(vd < MIN(0, -vbrknp + 10 * vtebrk))) {
|
||||
double vdtemp;
|
||||
vdtemp = -(vd + vbrknp);
|
||||
|
|
@ -766,19 +774,6 @@ bypass:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* temperature dependent diode saturation current and derivative
|
||||
*/
|
||||
arg1 = ((Temp / model->VDMOStnom) - 1) * model->VDMOSeg / (model->VDMOSn*vt);
|
||||
darg1_dT = model->VDMOSeg / (vte*model->VDMOStnom)
|
||||
- model->VDMOSeg*(Temp/model->VDMOStnom -1)/(vte*Temp);
|
||||
|
||||
arg2 = model->VDMOSxti / model->VDMOSn * log(Temp / model->VDMOStnom);
|
||||
darg2_dT = model->VDMOSxti / model->VDMOSn / Temp;
|
||||
|
||||
csat = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2);
|
||||
csat_dT = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2) * (darg1_dT + darg2_dT);
|
||||
|
||||
/*
|
||||
* compute dc current and derivatives
|
||||
*/
|
||||
|
|
@ -786,27 +781,27 @@ bypass:
|
|||
double evd;
|
||||
|
||||
evd = exp(vd / vte);
|
||||
cdb = csat*(evd - 1);
|
||||
dIdio_dT = csat_dT * (evd - 1) - csat * vd * evd / (vte * Temp);
|
||||
gdb = csat*evd / vte;
|
||||
cdb = here->VDIOtSatCur*(evd - 1);
|
||||
dIdio_dT = here->VDIOtSatCur_dT * (evd - 1) - here->VDIOtSatCur * vd * evd / (vte * Temp);
|
||||
gdb = here->VDIOtSatCur*evd / vte;
|
||||
|
||||
} else if ((!(model->VDMOSbvGiven)) ||
|
||||
} else if ((!(model->VDIObvGiven)) ||
|
||||
vd >= -vbrknp) { /* reverse */
|
||||
double arg3, darg3_dT;
|
||||
|
||||
arg = 3 * vte / (vd*CONSTe);
|
||||
arg3 = arg * arg * arg;
|
||||
darg3_dT = 3 * arg3 / Temp;
|
||||
cdb = -csat*(1 + arg3);
|
||||
dIdio_dT = -csat_dT * (arg3 + 1) - csat * darg3_dT;
|
||||
gdb = csat * 3 * arg / vd;
|
||||
cdb = -here->VDIOtSatCur*(1 + arg3);
|
||||
dIdio_dT = -here->VDIOtSatCur_dT * (arg3 + 1) - here->VDIOtSatCur * darg3_dT;
|
||||
gdb = here->VDIOtSatCur * 3 * arg / vd;
|
||||
|
||||
} else { /* breakdown */
|
||||
|
||||
evrev = exp(-(vbrknp + vd) / vtebrk);
|
||||
cdb = -csat*evrev;
|
||||
dIdio_dT = csat * (-vbrknp-vd) * evrev / vtebrk / Temp - csat_dT * evrev;
|
||||
gdb = csat*evrev / vtebrk;
|
||||
cdb = -here->VDIOtSatCur*evrev;
|
||||
dIdio_dT = here->VDIOtSatCur * (-vbrknp-vd) * evrev / vtebrk / Temp - here->VDIOtSatCur_dT * evrev;
|
||||
gdb = here->VDIOtSatCur*evrev / vtebrk;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -888,9 +883,18 @@ bypass:
|
|||
load:
|
||||
#endif
|
||||
if (selfheat) {
|
||||
Ith = vd*cd;
|
||||
double dIrs_dgspr, dIth_dIrs;
|
||||
vrs = *(ckt->CKTrhsOld + here->VDMOSsNode) - *(ckt->CKTrhsOld + here->VDIOposPrimeNode);
|
||||
|
||||
Ith = vd*cd + vrs*vrs*gspr;
|
||||
|
||||
dIth_dVdio = cd + vd*gd;
|
||||
dIth_dT = dIdio_dT*vd;
|
||||
dIth_dVrs = vrs*gspr;
|
||||
|
||||
dIrs_dgspr = vrs;
|
||||
dIrs_dT = dIrs_dgspr * here->VDIOtConductance_dT;
|
||||
dIth_dIrs = vrs;
|
||||
dIth_dT = dIth_dIrs*dIrs_dT + dIdio_dT*vd;
|
||||
}
|
||||
/*
|
||||
* load current vector
|
||||
|
|
@ -904,9 +908,10 @@ load:
|
|||
*(ckt->CKTrhs + here->VDIOposPrimeNode) += cdeq;
|
||||
}
|
||||
if (selfheat) {
|
||||
*(ckt->CKTrhs + here->VDIOposPrimeNode) += dIdio_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDIOposPrimeNode) += dIdio_dT*delTemp - dIrs_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSdNode) += -dIdio_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOStempNode) += Ith - model->VDMOStype*dIth_dVdio*vd - dIth_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOSsNode) += dIrs_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->VDMOStempNode) += Ith - model->VDMOStype*dIth_dVdio*vd - dIth_dVrs*vrs - dIth_dT*delTemp;
|
||||
}
|
||||
/*
|
||||
* load matrix
|
||||
|
|
@ -919,10 +924,12 @@ load:
|
|||
*(here->VDIORPsPtr) -= gspr;
|
||||
*(here->VDIORPdPtr) -= gd;
|
||||
if (selfheat) {
|
||||
(*(here->VDIOTempposPrimePtr) += -dIth_dVdio);
|
||||
(*(here->VDMOStempSPtr) += -dIth_dVrs);
|
||||
(*(here->VDIOTempposPrimePtr) += -dIth_dVdio + dIth_dVrs);
|
||||
(*(here->VDMOSTempdPtr) += dIth_dVdio);
|
||||
(*(here->VDMOSTemptempPtr) += -dIth_dT);
|
||||
(*(here->VDIOPosPrimetempPtr) += dIdio_dT);
|
||||
(*(here->VDIOPosPrimetempPtr) += dIdio_dT - dIrs_dT);
|
||||
(*(here->VDMOSSTempPtr) += dIrs_dT);
|
||||
(*(here->VDMOSDtempPtr) += -dIdio_dT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,47 +83,47 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
|
|||
return(OK);
|
||||
|
||||
/* body diode */
|
||||
case VDMOS_MOD_RB:
|
||||
case VDIO_MOD_RB:
|
||||
value->rValue = model->VDIOresistance;
|
||||
return(OK);
|
||||
case VDMOS_MOD_IS:
|
||||
case VDIO_MOD_IS:
|
||||
value->rValue = model->VDIOjctSatCur;
|
||||
return(OK);
|
||||
case VDMOS_MOD_N:
|
||||
value->rValue = model->VDMOSn;
|
||||
case VDIO_MOD_N:
|
||||
value->rValue = model->VDIOn;
|
||||
return(OK);
|
||||
case VDMOS_MOD_VJ:
|
||||
case VDIO_MOD_VJ:
|
||||
value->rValue = model->VDIOjunctionPot;
|
||||
return(OK);
|
||||
case VDMOS_MOD_CJ:
|
||||
case VDIO_MOD_CJ:
|
||||
value->rValue = model->VDIOjunctionCap;
|
||||
return(OK);
|
||||
case VDMOS_MOD_MJ:
|
||||
case VDIO_MOD_MJ:
|
||||
value->rValue = model->VDIOgradCoeff;
|
||||
return(OK);
|
||||
case VDMOS_MOD_BV:
|
||||
value->rValue = model->VDMOSbv;
|
||||
case VDIO_MOD_BV:
|
||||
value->rValue = model->VDIObv;
|
||||
return(OK);
|
||||
case VDMOS_MOD_IBV:
|
||||
value->rValue = model->VDMOSibv;
|
||||
case VDIO_MOD_IBV:
|
||||
value->rValue = model->VDIOibv;
|
||||
return(OK);
|
||||
case VDMOS_MOD_NBV:
|
||||
case VDIO_MOD_NBV:
|
||||
value->rValue = model->VDIObrkdEmissionCoeff;
|
||||
return(OK);
|
||||
case VDMOS_MOD_RDS:
|
||||
value->rValue = model->VDMOSrds;
|
||||
return(OK);
|
||||
case VDMOS_MOD_FC:
|
||||
case VDIO_MOD_FC:
|
||||
value->rValue = model->VDIOdepletionCapCoeff;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TT:
|
||||
case VDIO_MOD_TT:
|
||||
value->rValue = model->VDIOtransitTime;
|
||||
return(OK);
|
||||
case VDMOS_MOD_EG:
|
||||
value->rValue = model->VDMOSeg;
|
||||
case VDIO_MOD_EG:
|
||||
value->rValue = model->VDIOeg;
|
||||
return(OK);
|
||||
case VDMOS_MOD_XTI:
|
||||
value->rValue = model->VDMOSxti;
|
||||
case VDIO_MOD_XTI:
|
||||
value->rValue = model->VDIOxti;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TCVTH:
|
||||
value->rValue = model->VDMOStcvth;
|
||||
|
|
@ -164,11 +164,11 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
|
|||
case VDMOS_MOD_TRS2:
|
||||
value->rValue = model->VDMOStrs2;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TRB1:
|
||||
value->rValue = model->VDMOStrb1;
|
||||
case VDIO_MOD_TRB1:
|
||||
value->rValue = model->VDIOtrb1;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TRB2:
|
||||
value->rValue = model->VDMOStrb2;
|
||||
case VDIO_MOD_TRB2:
|
||||
value->rValue = model->VDIOtrb2;
|
||||
return(OK);
|
||||
case VDMOS_MOD_TKSUBTHRES1:
|
||||
value->rValue = model->VDMOStksubthres1;
|
||||
|
|
|
|||
|
|
@ -60,29 +60,29 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSqsVoltage = value->rValue;
|
||||
model->VDMOSqsVoltageGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_RB:
|
||||
case VDIO_MOD_RB:
|
||||
model->VDIOresistance = value->rValue;
|
||||
model->VDIOresistanceGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_IS:
|
||||
case VDIO_MOD_IS:
|
||||
model->VDIOjctSatCur = value->rValue;
|
||||
model->VDIOjctSatCurGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_VJ:
|
||||
case VDIO_MOD_VJ:
|
||||
model->VDIOjunctionPot = value->rValue;
|
||||
model->VDIOjunctionPotGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_CJ:
|
||||
case VDIO_MOD_CJ:
|
||||
model->VDIOjunctionCap = value->rValue;
|
||||
model->VDIOjunctionCapGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_MJ:
|
||||
case VDIO_MOD_MJ:
|
||||
model->VDIOgradCoeff = value->rValue;
|
||||
model->VDIOgradCoeffGiven = TRUE;
|
||||
model->VDIOgradCoeffTemp1 = 0;
|
||||
model->VDIOgradCoeffTemp2 = 0;
|
||||
break;
|
||||
case VDMOS_MOD_FC:
|
||||
case VDIO_MOD_FC:
|
||||
model->VDIOdepletionCapCoeff = value->rValue;
|
||||
model->VDIOdepletionCapCoeffGiven = TRUE;
|
||||
break;
|
||||
|
|
@ -140,15 +140,15 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSksubthres = value->rValue;
|
||||
model->VDMOSksubthresGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_BV:
|
||||
model->VDMOSbv = value->rValue;
|
||||
model->VDMOSbvGiven = TRUE;
|
||||
case VDIO_MOD_BV:
|
||||
model->VDIObv = value->rValue;
|
||||
model->VDIObvGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_IBV:
|
||||
model->VDMOSibv = value->rValue;
|
||||
model->VDMOSibvGiven = TRUE;
|
||||
case VDIO_MOD_IBV:
|
||||
model->VDIOibv = value->rValue;
|
||||
model->VDIOibvGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_NBV:
|
||||
case VDIO_MOD_NBV:
|
||||
model->VDIObrkdEmissionCoeff = value->rValue;
|
||||
model->VDIObrkdEmissionCoeffGiven = TRUE;
|
||||
break;
|
||||
|
|
@ -156,23 +156,23 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOSrds = value->rValue;
|
||||
model->VDMOSrdsGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_N:
|
||||
model->VDMOSn = value->rValue;
|
||||
model->VDMOSnGiven = TRUE;
|
||||
case VDIO_MOD_N:
|
||||
model->VDIOn = value->rValue;
|
||||
model->VDIOnGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TT:
|
||||
case VDIO_MOD_TT:
|
||||
model->VDIOtransitTime = value->rValue;
|
||||
model->VDIOtransitTimeGiven = TRUE;
|
||||
model->VDIOtranTimeTemp1 = 0;
|
||||
model->VDIOtranTimeTemp2 = 0;
|
||||
break;
|
||||
case VDMOS_MOD_EG:
|
||||
model->VDMOSeg = value->rValue;
|
||||
model->VDMOSegGiven = TRUE;
|
||||
case VDIO_MOD_EG:
|
||||
model->VDIOeg = value->rValue;
|
||||
model->VDIOegGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_XTI:
|
||||
model->VDMOSxti = value->rValue;
|
||||
model->VDMOSxtiGiven = TRUE;
|
||||
case VDIO_MOD_XTI:
|
||||
model->VDIOxti = value->rValue;
|
||||
model->VDIOxtiGiven = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TCVTH:
|
||||
model->VDMOStcvth = value->rValue;
|
||||
|
|
@ -226,13 +226,13 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->VDMOStrs2 = value->rValue;
|
||||
model->VDMOStrs2Given = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TRB1:
|
||||
model->VDMOStrb1 = value->rValue;
|
||||
model->VDMOStrb1Given = TRUE;
|
||||
case VDIO_MOD_TRB1:
|
||||
model->VDIOtrb1 = value->rValue;
|
||||
model->VDIOtrb1Given = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TRB2:
|
||||
model->VDMOStrb2 = value->rValue;
|
||||
model->VDMOStrb2Given = TRUE;
|
||||
case VDIO_MOD_TRB2:
|
||||
model->VDIOtrb2 = value->rValue;
|
||||
model->VDIOtrb2Given = TRUE;
|
||||
break;
|
||||
case VDMOS_MOD_TKSUBTHRES1:
|
||||
model->VDMOStksubthres1 = value->rValue;
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDMOSmtrGiven)
|
||||
model->VDMOSmtr = 1.;
|
||||
|
||||
if (!model->VDMOSbvGiven)
|
||||
model->VDMOSbv = 1.0e30;
|
||||
if (!model->VDIObvGiven)
|
||||
model->VDIObv = 1.0e30;
|
||||
|
||||
if (!model->VDMOSibvGiven)
|
||||
model->VDMOSibv = 1.0e-10;
|
||||
if (!model->VDIOibvGiven)
|
||||
model->VDIOibv = 1.0e-10;
|
||||
|
||||
if (!model->VDIObrkdEmissionCoeffGiven)
|
||||
model->VDIObrkdEmissionCoeff = 1.;
|
||||
|
|
@ -109,14 +109,14 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDIOresistanceGiven)
|
||||
model->VDIOresistance = 10e-03;
|
||||
|
||||
if (!model->VDMOSnGiven)
|
||||
model->VDMOSn = 1.;
|
||||
if (!model->VDIOnGiven)
|
||||
model->VDIOn = 1.;
|
||||
|
||||
if (!model->VDIOtransitTimeGiven)
|
||||
model->VDIOtransitTime = 0.;
|
||||
|
||||
if (!model->VDMOSegGiven)
|
||||
model->VDMOSeg = 1.11;
|
||||
if (!model->VDIOegGiven)
|
||||
model->VDIOeg = 1.11;
|
||||
|
||||
if (!model->VDMOSrthjcGiven)
|
||||
model->VDMOSrthjc = 1.0e-03;
|
||||
|
|
@ -157,11 +157,11 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
if (!model->VDMOStrs2Given)
|
||||
model->VDMOStrs2 = 0.0;
|
||||
|
||||
if (!model->VDMOStrb1Given)
|
||||
model->VDMOStrb1 = 0.0;
|
||||
if (!model->VDIOtrb1Given)
|
||||
model->VDIOtrb1 = 0.0;
|
||||
|
||||
if (!model->VDMOStrb2Given)
|
||||
model->VDMOStrb2 = 0.0;
|
||||
if (!model->VDIOtrb2Given)
|
||||
model->VDIOtrb2 = 0.0;
|
||||
|
||||
if (!model->VDMOStksubthres1Given)
|
||||
model->VDMOStksubthres1 = 0.0;
|
||||
|
|
@ -189,6 +189,38 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
else
|
||||
model->VDMOSqsGiven = 0;
|
||||
|
||||
if(!model->VDMOStnomGiven) {
|
||||
model->VDMOStnom = ckt->CKTnomTemp;
|
||||
}
|
||||
|
||||
/* now model parameter preprocessing */
|
||||
if (model->VDMOSphi <= 0.0) {
|
||||
SPfrontEnd->IFerrorf(ERR_FATAL,
|
||||
"%s: Phi is not positive.", model->VDMOSmodName);
|
||||
return(E_BADPARM);
|
||||
}
|
||||
|
||||
model->VDMOSoxideCapFactor = 3.9 * 8.854214871e-12 / 1e-07; /* use default Tox of 100nm */
|
||||
|
||||
/* body diode model */
|
||||
/* limit activation energy to min of .1 */
|
||||
if (model->VDIOeg<.1) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: body diode activation energy too small, limited to 0.1",
|
||||
model->VDMOSmodName);
|
||||
model->VDIOeg = .1;
|
||||
}
|
||||
/* limit depletion cap coeff to max of .95 */
|
||||
if (model->VDIOdepletionCapCoeff>.95) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: coefficient Fc too large, limited to 0.95",
|
||||
model->VDMOSmodName);
|
||||
model->VDIOdepletionCapCoeff = .95;
|
||||
}
|
||||
/* set lower limit of saturation current */
|
||||
if (model->VDIOjctSatCur < ckt->CKTepsmin)
|
||||
model->VDIOjctSatCur = ckt->CKTepsmin;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (here = VDMOSinstances(model); here != NULL;
|
||||
here = VDMOSnextInstance(here)) {
|
||||
|
|
@ -368,30 +400,6 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
return(E_NOMEM);\
|
||||
} } while(0)
|
||||
|
||||
if ((here->VDMOSthermalGiven) && (model->VDMOSrthjcGiven)) {
|
||||
TSTALLOC(VDMOSTemptempPtr, VDMOStempNode, VDMOStempNode); /* Transistor thermal contribution */
|
||||
TSTALLOC(VDMOSTempdpPtr, VDMOStempNode, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSTempspPtr, VDMOStempNode, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSTempgpPtr, VDMOStempNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGPtempPtr, VDMOSgNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDPtempPtr, VDMOSdNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSSPtempPtr, VDMOSsNodePrime, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDIOTempposPrimePtr, VDMOStempNode, VDIOposPrimeNode);/* Diode thermal contribution */
|
||||
TSTALLOC(VDMOSTempdPtr, VDMOStempNode, VDMOSdNode);
|
||||
TSTALLOC(VDIOPosPrimetempPtr, VDIOposPrimeNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDtempPtr, VDMOSdNode, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDMOSTcasetcasePtr, VDMOStcaseNode, VDMOStcaseNode); /* Rthjc between tj and tcase*/
|
||||
TSTALLOC(VDMOSTcasetempPtr, VDMOStcaseNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTemptcasePtr, VDMOStempNode, VDMOStcaseNode);
|
||||
TSTALLOC(VDMOSTptpPtr, VDMOStNodePrime, VDMOStNodePrime); /* Rthca between tcase and Vsrc */
|
||||
TSTALLOC(VDMOSTptcasePtr, VDMOStNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTcasetpPtr, VDMOStempNode, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSCktTcktTPtr, VDMOSvcktTbranch, VDMOSvcktTbranch); /* Vsrc=cktTemp to gnd */
|
||||
TSTALLOC(VDMOSCktTtpPtr, VDMOSvcktTbranch, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSTpcktTPtr, VDMOStNodePrime, VDMOSvcktTbranch);
|
||||
}
|
||||
TSTALLOC(VDMOSDdPtr, VDMOSdNode, VDMOSdNode);
|
||||
TSTALLOC(VDMOSGgPtr, VDMOSgNode, VDMOSgNode);
|
||||
TSTALLOC(VDMOSSsPtr, VDMOSsNode, VDMOSsNode);
|
||||
|
|
@ -409,7 +417,7 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
TSTALLOC(VDMOSSPsPtr, VDMOSsNodePrime, VDMOSsNode);
|
||||
TSTALLOC(VDMOSSPdpPtr, VDMOSsNodePrime, VDMOSdNodePrime);
|
||||
|
||||
TSTALLOC(VDMOSGgpPtr, VDMOSgNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGgpPtr, VDMOSgNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGPgPtr, VDMOSgNodePrime, VDMOSgNode);
|
||||
|
||||
TSTALLOC(VDMOSDsPtr, VDMOSdNode, VDMOSsNode);
|
||||
|
|
@ -420,6 +428,33 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
TSTALLOC(VDIOSrpPtr, VDMOSsNode, VDIOposPrimeNode);
|
||||
TSTALLOC(VDIORPsPtr, VDIOposPrimeNode, VDMOSsNode);
|
||||
TSTALLOC(VDIORPrpPtr, VDIOposPrimeNode, VDIOposPrimeNode);
|
||||
|
||||
if ((here->VDMOSthermalGiven) && (model->VDMOSrthjcGiven)) {
|
||||
TSTALLOC(VDMOSTemptempPtr, VDMOStempNode, VDMOStempNode); /* Transistor thermal contribution */
|
||||
TSTALLOC(VDMOSTempdpPtr, VDMOStempNode, VDMOSdNodePrime);
|
||||
TSTALLOC(VDMOSTempspPtr, VDMOStempNode, VDMOSsNodePrime);
|
||||
TSTALLOC(VDMOSTempgpPtr, VDMOStempNode, VDMOSgNodePrime);
|
||||
TSTALLOC(VDMOSGPtempPtr, VDMOSgNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDPtempPtr, VDMOSdNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSSPtempPtr, VDMOSsNodePrime, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDIOTempposPrimePtr, VDMOStempNode, VDIOposPrimeNode);/* Diode thermal contribution */
|
||||
TSTALLOC(VDMOSTempdPtr, VDMOStempNode, VDMOSdNode);
|
||||
TSTALLOC(VDIOPosPrimetempPtr, VDIOposPrimeNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSDtempPtr, VDMOSdNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOStempSPtr, VDMOStempNode, VDMOSsNode);
|
||||
TSTALLOC(VDMOSSTempPtr, VDMOSsNode, VDMOStempNode);
|
||||
|
||||
TSTALLOC(VDMOSTcasetcasePtr, VDMOStcaseNode, VDMOStcaseNode); /* Rthjc between tj and tcase*/
|
||||
TSTALLOC(VDMOSTcasetempPtr, VDMOStcaseNode, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTemptcasePtr, VDMOStempNode, VDMOStcaseNode);
|
||||
TSTALLOC(VDMOSTptpPtr, VDMOStNodePrime, VDMOStNodePrime); /* Rthca between tcase and Vsrc */
|
||||
TSTALLOC(VDMOSTptcasePtr, VDMOStNodePrime, VDMOStempNode);
|
||||
TSTALLOC(VDMOSTcasetpPtr, VDMOStempNode, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSCktTcktTPtr, VDMOSvcktTbranch, VDMOSvcktTbranch); /* Vsrc=cktTemp to gnd */
|
||||
TSTALLOC(VDMOSCktTtpPtr, VDMOSvcktTbranch, VDMOStNodePrime);
|
||||
TSTALLOC(VDMOSTpcktTPtr, VDMOStNodePrime, VDMOSvcktTbranch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ Modified: 2000 AlansFixes
|
|||
VDMOS: 2018 Holger Vogt, 2020 Dietmar Warning
|
||||
**********/
|
||||
|
||||
/* perform the temperature update to the vdmos */
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "vdmosdefs.h"
|
||||
|
|
@ -12,11 +14,9 @@ VDMOS: 2018 Holger Vogt, 2020 Dietmar Warning
|
|||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/suffix.h"
|
||||
|
||||
int
|
||||
VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||
{
|
||||
VDMOSmodel *model = (VDMOSmodel *)inModel;
|
||||
VDMOSinstance *here;
|
||||
void VDMOStempUpdate(VDMOSmodel *inModel, VDMOSinstance *here, double Temp, CKTcircuit *ckt) {
|
||||
|
||||
VDMOSmodel *model = (VDMOSmodel*)inModel;
|
||||
|
||||
double egfet,egfet1;
|
||||
double fact1,fact2;
|
||||
|
|
@ -28,199 +28,179 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double vt,vtnom;
|
||||
double xfc;
|
||||
|
||||
/* loop through all the resistor models */
|
||||
for( ; model != NULL; model = VDMOSnextModel(model)) {
|
||||
|
||||
fact1 = model->VDMOStnom/REFTEMP;
|
||||
vtnom = model->VDMOStnom*CONSTKoverQ;
|
||||
kt1 = CONSTboltz * model->VDMOStnom;
|
||||
egfet1 = 1.16-(7.02e-4*model->VDMOStnom*model->VDMOStnom)/
|
||||
(model->VDMOStnom+1108);
|
||||
arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1);
|
||||
|
||||
/* perform model defaulting */
|
||||
if(!model->VDMOStnomGiven) {
|
||||
model->VDMOStnom = ckt->CKTnomTemp;
|
||||
}
|
||||
xfc = log(1 - model->VDIOdepletionCapCoeff);
|
||||
|
||||
fact1 = model->VDMOStnom/REFTEMP;
|
||||
vtnom = model->VDMOStnom*CONSTKoverQ;
|
||||
kt1 = CONSTboltz * model->VDMOStnom;
|
||||
egfet1 = 1.16-(7.02e-4*model->VDMOStnom*model->VDMOStnom)/
|
||||
(model->VDMOStnom+1108);
|
||||
arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1);
|
||||
double arg; /* 1 - fc */
|
||||
|
||||
/* now model parameter preprocessing */
|
||||
if (model->VDMOSphi <= 0.0) {
|
||||
SPfrontEnd->IFerrorf(ERR_FATAL,
|
||||
"%s: Phi is not positive.", model->VDMOSmodName);
|
||||
return(E_BADPARM);
|
||||
}
|
||||
double dt = Temp - model->VDMOStnom;
|
||||
|
||||
model->VDMOSoxideCapFactor = 3.9 * 8.854214871e-12 / 1e-07; /* use default Tox of 100nm */
|
||||
/* vdmos temperature model */
|
||||
ratio = Temp/model->VDMOStnom;
|
||||
here->VDMOStTransconductance = model->VDMOStransconductance
|
||||
* here->VDMOSm * pow(ratio, model->VDMOSmu);
|
||||
|
||||
/* body diode model */
|
||||
/* limit activation energy to min of .1 */
|
||||
if (model->VDMOSeg<.1) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: body diode activation energy too small, limited to 0.1",
|
||||
model->VDMOSmodName);
|
||||
model->VDMOSeg = .1;
|
||||
}
|
||||
/* limit depletion cap coeff to max of .95 */
|
||||
if (model->VDIOdepletionCapCoeff>.95) {
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: coefficient Fc too large, limited to 0.95",
|
||||
model->VDMOSmodName);
|
||||
model->VDIOdepletionCapCoeff = .95;
|
||||
}
|
||||
/* set lower limit of saturation current */
|
||||
if (model->VDIOjctSatCur < ckt->CKTepsmin)
|
||||
model->VDIOjctSatCur = ckt->CKTepsmin;
|
||||
here->VDMOStVth = model->VDMOSvth0 - model->VDMOStype * model->VDMOStcvth * dt;
|
||||
|
||||
xfc = log(1 - model->VDIOdepletionCapCoeff);
|
||||
here->VDMOStksubthres = model->VDMOSksubthres * (1.0 + (model->VDMOStksubthres1 * dt) + (model->VDMOStksubthres2 * dt * dt));
|
||||
|
||||
/* loop through all instances of the model */
|
||||
for(here = VDMOSinstances(model); here!= NULL;
|
||||
here = VDMOSnextInstance(here)) {
|
||||
double arg; /* 1 - fc */
|
||||
if (model->VDMOStexp0Given)
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * pow(ratio, model->VDMOStexp0);
|
||||
else
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * (1.0 + (model->VDMOStrd1 * dt) + (model->VDMOStrd2 * dt * dt));
|
||||
|
||||
/* perform the parameter defaulting */
|
||||
if(!here->VDMOSdtempGiven) {
|
||||
here->VDMOSdtemp = 0.0;
|
||||
}
|
||||
if(!here->VDMOStempGiven) {
|
||||
here->VDMOStemp = ckt->CKTtemp + here->VDMOSdtemp;
|
||||
}
|
||||
here->VDMOSgateConductance = here->VDMOSgateConductance / (1.0 + (model->VDMOStrg1 * dt) + (model->VDMOStrg2 * dt * dt));
|
||||
|
||||
double dt = here->VDMOStemp - model->VDMOStnom;
|
||||
here->VDMOSsourceConductance = here->VDMOSsourceConductance / (1.0 + (model->VDMOStrs1 * dt) + (model->VDMOStrs2 * dt * dt));
|
||||
|
||||
/* vdmos temperature model */
|
||||
ratio = here->VDMOStemp/model->VDMOStnom;
|
||||
here->VDMOStTransconductance = model->VDMOStransconductance
|
||||
* here->VDMOSm * pow(ratio, model->VDMOSmu);
|
||||
if (model->VDMOSqsGiven)
|
||||
here->VDMOSqsResistance = model->VDMOSqsResistance / here->VDMOSm * pow(ratio, model->VDMOStexp1);
|
||||
|
||||
here->VDMOStVth = model->VDMOSvth0 - model->VDMOStype * model->VDMOStcvth * dt;
|
||||
vt = Temp * CONSTKoverQ;
|
||||
fact2 = Temp/REFTEMP;
|
||||
kt = Temp * CONSTboltz;
|
||||
egfet = 1.16-(7.02e-4*Temp*Temp)/
|
||||
(Temp+1108);
|
||||
arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg);
|
||||
|
||||
here->VDMOStksubthres = model->VDMOSksubthres * (1.0 + (model->VDMOStksubthres1 * dt) + (model->VDMOStksubthres2 * dt * dt));
|
||||
phio = (model->VDMOSphi - pbfact1) / fact1;
|
||||
here->VDMOStPhi = fact2 * phio + pbfact; /* needed for distortion analysis */
|
||||
|
||||
if (model->VDMOStexp0Given)
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * pow(ratio, model->VDMOStexp0);
|
||||
else
|
||||
here->VDMOSdrainResistance = model->VDMOSdrainResistance / here->VDMOSm * (1.0 + (model->VDMOStrd1 * dt) + (model->VDMOStrd2 * dt * dt));
|
||||
/* body diode temperature model */
|
||||
double pbo, gmaold;
|
||||
double gmanew, factor;
|
||||
double tBreakdownVoltage, vte, cbv;
|
||||
double xbv, xcbv, tol, iter;
|
||||
double arg1_dT, arg2, arg2_dT;
|
||||
|
||||
here->VDMOSgateConductance = here->VDMOSgateConductance / (1.0 + (model->VDMOStrg1 * dt) + (model->VDMOStrg2 * dt * dt));
|
||||
/* Junction grading temperature adjust */
|
||||
factor = 1.0 + (model->VDIOgradCoeffTemp1 * dt)
|
||||
+ (model->VDIOgradCoeffTemp2 * dt * dt);
|
||||
here->VDIOtGradingCoeff = model->VDIOgradCoeff * factor;
|
||||
|
||||
here->VDMOSsourceConductance = here->VDMOSsourceConductance / (1.0 + (model->VDMOStrs1 * dt) + (model->VDMOStrs2 * dt * dt));
|
||||
pbo = (model->VDIOjunctionPot - pbfact1) / fact1;
|
||||
gmaold = (model->VDIOjunctionPot - pbo) / pbo;
|
||||
here->VDIOtJctCap = here->VDMOSm * model->VDIOjunctionCap /
|
||||
(1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(model->VDMOStnom - REFTEMP) - gmaold));
|
||||
here->VDIOtJctPot = pbfact + fact2*pbo;
|
||||
gmanew = (here->VDIOtJctPot - pbo) / pbo;
|
||||
here->VDIOtJctCap *= 1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(Temp - REFTEMP) - gmanew);
|
||||
|
||||
if (model->VDMOSqsGiven)
|
||||
here->VDMOSqsResistance = model->VDMOSqsResistance / here->VDMOSm * pow(ratio, model->VDMOStexp1);
|
||||
vte = model->VDIOn*vt;
|
||||
|
||||
vt = here->VDMOStemp * CONSTKoverQ;
|
||||
fact2 = here->VDMOStemp/REFTEMP;
|
||||
kt = here->VDMOStemp * CONSTboltz;
|
||||
egfet = 1.16-(7.02e-4*here->VDMOStemp*here->VDMOStemp)/
|
||||
(here->VDMOStemp+1108);
|
||||
arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg);
|
||||
arg1 = ((Temp / model->VDMOStnom) - 1) * model->VDIOeg / vte;
|
||||
arg1_dT = model->VDIOeg / (vte*model->VDMOStnom)
|
||||
- model->VDIOeg*(Temp/model->VDMOStnom -1)/(vte*Temp);
|
||||
arg2 = model->VDIOxti / model->VDIOn * log(Temp / model->VDMOStnom);
|
||||
arg2_dT = model->VDIOxti / model->VDIOn / Temp;
|
||||
here->VDIOtSatCur = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2);
|
||||
here->VDIOtSatCur_dT = here->VDMOSm * model->VDIOjctSatCur * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
||||
|
||||
phio = (model->VDMOSphi - pbfact1) / fact1;
|
||||
here->VDMOStPhi = fact2 * phio + pbfact; /* needed for distortion analysis */
|
||||
/* the defintion of f1, just recompute after temperature adjusting
|
||||
* all the variables used in it */
|
||||
here->VDIOtF1 = here->VDIOtJctPot*
|
||||
(1 - exp((1 - here->VDIOtGradingCoeff)*xfc)) /
|
||||
(1 - here->VDIOtGradingCoeff);
|
||||
/* same for Depletion Capacitance */
|
||||
here->VDIOtDepCap = model->VDIOdepletionCapCoeff *
|
||||
here->VDIOtJctPot;
|
||||
|
||||
/* body diode temperature model */
|
||||
double pbo, gmaold;
|
||||
double gmanew, factor;
|
||||
double tBreakdownVoltage, vte, cbv;
|
||||
double xbv, xcbv, tol, iter;
|
||||
/* and Vcrit */
|
||||
here->VDIOtVcrit = vte * log(vte / (CONSTroot2*here->VDIOtSatCur));
|
||||
|
||||
/* Junction grading temperature adjust */
|
||||
factor = 1.0 + (model->VDIOgradCoeffTemp1 * dt)
|
||||
+ (model->VDIOgradCoeffTemp2 * dt * dt);
|
||||
here->VDIOtGradingCoeff = model->VDIOgradCoeff * factor;
|
||||
|
||||
pbo = (model->VDIOjunctionPot - pbfact1) / fact1;
|
||||
gmaold = (model->VDIOjunctionPot - pbo) / pbo;
|
||||
here->VDIOtJctCap = here->VDMOSm * model->VDIOjunctionCap /
|
||||
(1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(model->VDMOStnom - REFTEMP) - gmaold));
|
||||
here->VDIOtJctPot = pbfact + fact2*pbo;
|
||||
gmanew = (here->VDIOtJctPot - pbo) / pbo;
|
||||
here->VDIOtJctCap *= 1 + here->VDIOtGradingCoeff*
|
||||
(400e-6*(here->VDMOStemp - REFTEMP) - gmanew);
|
||||
|
||||
here->VDIOtSatCur = here->VDMOSm * model->VDIOjctSatCur * exp(
|
||||
((here->VDMOStemp / model->VDMOStnom) - 1) *
|
||||
model->VDMOSeg / (model->VDMOSn*vt) +
|
||||
model->VDMOSxti / model->VDMOSn *
|
||||
log(here->VDMOStemp / model->VDMOStnom));
|
||||
|
||||
/* the defintion of f1, just recompute after temperature adjusting
|
||||
* all the variables used in it */
|
||||
here->VDIOtF1 = here->VDIOtJctPot*
|
||||
(1 - exp((1 - here->VDIOtGradingCoeff)*xfc)) /
|
||||
(1 - here->VDIOtGradingCoeff);
|
||||
/* same for Depletion Capacitance */
|
||||
here->VDIOtDepCap = model->VDIOdepletionCapCoeff *
|
||||
here->VDIOtJctPot;
|
||||
|
||||
/* and Vcrit */
|
||||
vte = model->VDMOSn*vt;
|
||||
|
||||
here->VDIOtVcrit = vte * log(vte / (CONSTroot2*here->VDIOtSatCur));
|
||||
|
||||
/* limit junction potential to max of 1/FC */
|
||||
if (here->VDIOtDepCap > 2.5) {
|
||||
here->VDIOtJctPot = 2.5 / model->VDMOSn;
|
||||
here->VDIOtDepCap = model->VDMOSn*here->VDIOtJctPot;
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: junction potential VJ too large, limited to %f",
|
||||
model->VDMOSmodName, here->VDIOtJctPot);
|
||||
}
|
||||
|
||||
/* and now to compute the breakdown voltage, again, using
|
||||
* temperature adjusted basic parameters */
|
||||
if (model->VDMOSbvGiven) {
|
||||
/* tlev == 0 */
|
||||
tBreakdownVoltage = fabs(model->VDMOSbv);
|
||||
|
||||
cbv = model->VDMOSibv;
|
||||
|
||||
if (cbv < here->VDIOtSatCur * tBreakdownVoltage / vt) {
|
||||
cbv = here->VDIOtSatCur * tBreakdownVoltage / vt;
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: breakdown current increased to %g to resolve", here->VDMOSname, cbv);
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"incompatibility with specified saturation current");
|
||||
#endif
|
||||
xbv = tBreakdownVoltage;
|
||||
}
|
||||
else {
|
||||
tol = ckt->CKTreltol*cbv;
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(1 + cbv /
|
||||
(here->VDIOtSatCur));
|
||||
iter = 0;
|
||||
for (iter = 0; iter < 25; iter++) {
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(cbv /
|
||||
(here->VDIOtSatCur) + 1 - xbv / vt);
|
||||
xcbv = here->VDIOtSatCur *
|
||||
(exp((tBreakdownVoltage - xbv) / (model->VDIObrkdEmissionCoeff*vt)) - 1 + xbv / vt);
|
||||
if (fabs(xcbv - cbv) <= tol) goto matched;
|
||||
}
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", here->VDMOSname, xbv, xcbv);
|
||||
#endif
|
||||
}
|
||||
matched:
|
||||
here->VDIOtBrkdwnV = xbv;
|
||||
}
|
||||
|
||||
/* transit time temperature adjust */
|
||||
factor = 1.0 + (model->VDIOtranTimeTemp1 * dt)
|
||||
+ (model->VDIOtranTimeTemp2 * dt * dt);
|
||||
here->VDIOtTransitTime = model->VDIOtransitTime * factor;
|
||||
|
||||
/* Series resistance temperature adjust */
|
||||
here->VDIOtConductance = here->VDIOconductance / (1.0 + (model->VDMOStrb1 * dt) + (model->VDMOStrb2 * dt * dt));
|
||||
|
||||
here->VDIOtF2 = exp((1 + here->VDIOtGradingCoeff)*xfc);
|
||||
here->VDIOtF3 = 1 - model->VDIOdepletionCapCoeff*
|
||||
(1 + here->VDIOtGradingCoeff);
|
||||
}
|
||||
/* limit junction potential to max of 1/FC */
|
||||
if (here->VDIOtDepCap > 2.5) {
|
||||
here->VDIOtJctPot = 2.5 / model->VDIOn;
|
||||
here->VDIOtDepCap = model->VDIOn*here->VDIOtJctPot;
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"%s: junction potential VJ too large, limited to %f",
|
||||
model->VDMOSmodName, here->VDIOtJctPot);
|
||||
}
|
||||
|
||||
/* and now to compute the breakdown voltage, again, using
|
||||
* temperature adjusted basic parameters */
|
||||
if (model->VDIObvGiven) {
|
||||
/* tlev == 0 */
|
||||
tBreakdownVoltage = fabs(model->VDIObv);
|
||||
|
||||
cbv = model->VDIOibv;
|
||||
|
||||
if (cbv < here->VDIOtSatCur * tBreakdownVoltage / vt) {
|
||||
cbv = here->VDIOtSatCur * tBreakdownVoltage / vt;
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: breakdown current increased to %g to resolve", here->VDMOSname, cbv);
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING,
|
||||
"incompatibility with specified saturation current");
|
||||
#endif
|
||||
xbv = tBreakdownVoltage;
|
||||
}
|
||||
else {
|
||||
tol = ckt->CKTreltol*cbv;
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(1 + cbv /
|
||||
(here->VDIOtSatCur));
|
||||
iter = 0;
|
||||
for (iter = 0; iter < 25; iter++) {
|
||||
xbv = tBreakdownVoltage - model->VDIObrkdEmissionCoeff*vt*log(cbv /
|
||||
(here->VDIOtSatCur) + 1 - xbv / vt);
|
||||
xcbv = here->VDIOtSatCur *
|
||||
(exp((tBreakdownVoltage - xbv) / (model->VDIObrkdEmissionCoeff*vt)) - 1 + xbv / vt);
|
||||
if (fabs(xcbv - cbv) <= tol) goto matched;
|
||||
}
|
||||
#ifdef TRACE
|
||||
SPfrontEnd->IFerrorf(ERR_WARNING, "%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", here->VDMOSname, xbv, xcbv);
|
||||
#endif
|
||||
}
|
||||
matched:
|
||||
here->VDIOtBrkdwnV = xbv;
|
||||
}
|
||||
|
||||
/* transit time temperature adjust */
|
||||
factor = 1.0 + (model->VDIOtranTimeTemp1 * dt)
|
||||
+ (model->VDIOtranTimeTemp2 * dt * dt);
|
||||
here->VDIOtTransitTime = model->VDIOtransitTime * factor;
|
||||
|
||||
/* Series resistance temperature adjust */
|
||||
factor = 1.0 + (model->VDIOtrb1) * dt
|
||||
+ (model->VDIOtrb2 * dt * dt);
|
||||
here->VDIOtConductance = here->VDIOconductance / factor;
|
||||
here->VDIOtConductance_dT = -here->VDIOconductance * (model->VDIOtrb1 + model->VDIOtrb2 * dt) / (factor*factor);
|
||||
|
||||
here->VDIOtF2 = exp((1 + here->VDIOtGradingCoeff)*xfc);
|
||||
here->VDIOtF3 = 1 - model->VDIOdepletionCapCoeff*
|
||||
(1 + here->VDIOtGradingCoeff);
|
||||
}
|
||||
|
||||
int
|
||||
VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||
{
|
||||
VDMOSmodel *model = (VDMOSmodel*)inModel;
|
||||
VDMOSinstance *here;
|
||||
|
||||
/* loop through all the vdmos models */
|
||||
for( ; model != NULL; model = VDMOSnextModel(model)) {
|
||||
|
||||
/* loop through all the instances */
|
||||
for(here=VDMOSinstances(model);here;here=VDMOSnextInstance(here)) {
|
||||
|
||||
if(!here->VDMOSdtempGiven) here->VDMOSdtemp = 0.0;
|
||||
|
||||
if(!here->VDMOStempGiven)
|
||||
here->VDMOStemp = ckt->CKTtemp + here->VDMOSdtemp;
|
||||
|
||||
VDMOStempUpdate(model, here, here->VDMOStemp, ckt);
|
||||
|
||||
} /* instance */
|
||||
|
||||
} /* model */
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue