diode model for bulk diode added code taken from dio.c etc. capacitance calculation for vdmos bulk cap removed, is now completely with the diode. An internal node added for series diode resistance RB

matrix entries not yet done!
This commit is contained in:
Holger Vogt 2018-04-09 20:11:45 +02:00 committed by rlar
parent 1ce7fef519
commit 4ac7a641ec
8 changed files with 490 additions and 153 deletions

View File

@ -37,6 +37,7 @@ IFparm VDMOSpTable[] = { /* parameters */
OP( "cgs", VDMOS_CGS, IF_REAL, "Gate-Source capacitance"),
OP( "cgd", VDMOS_CGD, IF_REAL, "Gate-Drain capacitance"),
*/
OP( "cds", VDMOS_CDS, IF_REAL, "Drain-Source capacitance"),
OPU( "dnode", VDMOS_DNODE, IF_INTEGER, "Number of the drain node "),
OPU( "gnode", VDMOS_GNODE, IF_INTEGER, "Number of the gate node "),
@ -105,6 +106,7 @@ IFparm VDMOSmPTable[] = { /* model parameters */
/* 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("mj", VDMOS_MOD_MJ, IF_REAL, "Body diode grading coefficient"),
/* gate-source and gate-drain capacitances */

View File

@ -35,6 +35,9 @@ VDMOSask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
case VDMOS_CGD:
value->rValue = 2* *(ckt->CKTstate0 + here->VDMOScapgd);
return(OK);
case VDMOS_CDS:
value->rValue = here->VDIOcap;
return(OK);
case VDMOS_M:
value->rValue = here->VDMOSm;
return(OK);

View File

@ -45,6 +45,7 @@ typedef struct sVDMOSinstance {
int VDMOSdNodePrime; /* number of the internal drain node of the mosfet */
int VDMOSsNodePrime; /* number of the internal source node of the mosfet */
int VDMOSgNodePrime; /* number of the internal gate node of the mosfet */
int VDIOposPrimeNode; /* number of the internal node of the bulk diode */
double VDMOSm; /* parallel device multiplier */
@ -60,9 +61,6 @@ typedef struct sVDMOSinstance {
double VDMOStPhi; /* temperature corrected Phi */
double VDMOStVto; /* temperature corrected Vto */
double VDMOStSatCur; /* temperature corrected saturation Cur. */
double VDMOStBulkPot; /* temperature corrected Bulk potential */
double VDMOStDepCap; /* temperature adjusted transition point in */
/* the cureve matching Fc * Vj */
double VDMOSicVBS; /* initial condition B-S voltage */
double VDMOSicVDS; /* initial condition D-S voltage */
@ -90,6 +88,23 @@ typedef struct sVDMOSinstance {
double VDMOSf3s;
double VDMOSf4s;
double VDIOcap;
double VDIOtSatCur; /* temperature corrected saturation Cur. density*/
double VDIOinitCond;
double VDIOtVcrit;
double VDIOtConductance;
double VDIOtBrkdwnV;
double VDIOtJctCap;
double VDIOtDepCap; /* temperature adjusted transition point in */
/* the cureve matching Fc * Vj */
double VDIOtJctPot; /* temperature corrected Bulk potential */
double VDIOtGradingCoeff;
double VDIOtTransitTime;
double VDIOtF1;
double VDIOtF2;
double VDIOtF3;
/*
* naming convention:
* x = vgs
@ -256,7 +271,13 @@ typedef struct sVDMOSinstance {
#define VDMOSqbs VDMOSstates+ 15 /* bulk-source capacitor charge */
#define VDMOScqbs VDMOSstates+ 16 /* bulk-source capacitor current */
#define VDMOSnumStates 17
#define VDIOvoltage VDMOSstates+ 17
#define VDIOcurrent VDMOSstates+ 18
#define VDIOconduct VDMOSstates+ 19
#define VDIOcapCharge VDMOSstates+ 20
#define VDIOcapCurrent VDMOSstates+ 21
#define VDMOSnumStates 22
/* per model data */
@ -279,7 +300,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
int VDMOStype; /* device type : 1 = nmos, -1 = pmos */
double VDMOStnom; /* temperature at which parameters measured */
double VDMOSjctSatCur; /* input - use tSatCur */
double VDMOSdrainResistance;
double VDMOSsourceResistance;
double VDMOSgateResistance;
@ -287,9 +307,6 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
double VDMOStransconductance; /* input - use tTransconductance */
double VDMOSoxideCapFactor;
double VDMOSvt0; /* input - use tVto */
double VDMOSbulkJctPotential; /* input - use tBulkPot */
double VDMOSbulkJctBotGradingCoeff;
double VDMOSfwdCapDepCoeff;
double VDMOSphi; /* input - use tPhi */
double VDMOSlambda;
double VDMOSfNcoef;
@ -299,27 +316,37 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
double VDMOSa;
double VDMOScgs;
/* bulk diode */
double VDIOjunctionCap; /* input - use tCj */
double VDIOjunctionPot; /* input - use tBulkPot */
double VDMOSbulkJctBotGradingCoeff;
double VDIOdepletionCapCoeff;
double VDIOjctSatCur; /* input - use tSatCur */
double VDMOSDbv;
double VDMOSDibv;
double VDIObrkdEmissionCoeff;
double VDIOresistance;
double VDIOresistTemp1;
double VDIOresistTemp2;
double VDIOconductance;
double VDMOSDn;
double VDIOtransitTime;
double VDIOtranTimeTemp1;
double VDIOtranTimeTemp2;
double VDMOSDeg;
double VDMOSDxti;
double VDIOgradCoeffTemp1;
double VDIOgradCoeffTemp2;
unsigned VDMOStypeGiven :1;
unsigned VDMOSjctSatCurGiven :1;
unsigned VDIOjctSatCurGiven :1;
unsigned VDMOSdrainResistanceGiven :1;
unsigned VDMOSsourceResistanceGiven :1;
unsigned VDMOSgateResistanceGiven :1;
unsigned VDMOStransconductanceGiven :1;
unsigned VDMOSvt0Given :1;
unsigned VDMOSbulkJctPotentialGiven :1;
unsigned VDMOSbulkJctBotGradingCoeffGiven :1;
unsigned VDMOSfwdCapDepCoeffGiven :1;
unsigned VDIOdepletionCapCoeffGiven :1;
unsigned VDMOSphiGiven :1;
unsigned VDMOSlambdaGiven :1;
unsigned VDMOStnomGiven :1;
@ -333,6 +360,8 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
unsigned VDMOSDbvGiven :1;
unsigned VDMOSDibvGiven :1;
unsigned VDIOjunctionCapGiven :1;
unsigned VDIOjunctionPotGiven :1;
unsigned VDIObrkdEmissionCoeffGiven :1;
unsigned VDIOresistanceGiven :1;
unsigned VDMOSDnGiven :1;
@ -376,6 +405,7 @@ enum {
VDMOS_MOD_RG,
VDMOS_MOD_IS,
VDMOS_MOD_VJ,
VDMOS_MOD_CJ,
VDMOS_MOD_MJ,
VDMOS_MOD_FC,
VDMOS_MOD_NMOS,
@ -403,6 +433,7 @@ enum {
enum {
VDMOS_CGS = 201,
VDMOS_CGD,
VDMOS_CDS,
VDMOS_DNODE,
VDMOS_GNODE,
VDMOS_SNODE,

View File

@ -48,7 +48,6 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
double gcgs;
double geq;
double sarg;
double sargsw;
double vbd;
double vbs;
double vds;
@ -454,144 +453,20 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) {
/*
* now we do the hard part of the bulk-drain and bulk-source
* diode - we evaluate the non-linear capacitance and
* charge
*
* the basic equations are not hard, but the implementation
* is somewhat long in an attempt to avoid log/exponential
* evaluations
* capacitance evaluation for drain-source is done with the bulk diode
*/
/*
* charge storage elements
*
*.. bulk-drain and bulk-source depletion capacitances
*/
{
/* can't bypass the diode capacitance calculations */
if (here->VDMOSCbs != 0) {
if (vbs < here->VDMOStDepCap) {
arg = 1 - vbs / here->VDMOStBulkPot;
/*
* the following block looks somewhat long and messy,
* but since most users use the default grading
* coefficients of .5, and sqrt is MUCH faster than an
* exp(log()) we use this special case code to buy time.
* (as much as 10% of total job time!)
*/
if (model->VDMOSbulkJctBotGradingCoeff == .5) {
sarg = sargsw = 1 / sqrt(arg);
}
else {
sarg = sargsw =
exp(-model->VDMOSbulkJctBotGradingCoeff*
log(arg));
}
*(ckt->CKTstate0 + here->VDMOSqbs) =
here->VDMOStBulkPot*(here->VDMOSCbs*
(1 - arg*sarg) / (1 - model->VDMOSbulkJctBotGradingCoeff));
here->VDMOScapbs = here->VDMOSCbs * sarg;
}
else {
*(ckt->CKTstate0 + here->VDMOSqbs) = here->VDMOSf4s +
vbs*(here->VDMOSf2s + vbs*(here->VDMOSf3s / 2));
here->VDMOScapbs = here->VDMOSf2s + here->VDMOSf3s*vbs;
}
}
else {
*(ckt->CKTstate0 + here->VDMOSqbs) = 0;
here->VDMOScapbs = 0;
}
}
{
if (here->VDMOSCbd != 0) {
if (vbd < here->VDMOStDepCap) {
arg = 1 - vbd / here->VDMOStBulkPot;
/*
* the following block looks somewhat long and messy,
* but since most users use the default grading
* coefficients of .5, and sqrt is MUCH faster than an
* exp(log()) we use this special case code to buy time.
* (as much as 10% of total job time!)
*/
if (model->VDMOSbulkJctBotGradingCoeff == .5) {
sarg = sargsw = 1 / sqrt(arg);
}
else {
if (model->VDMOSbulkJctBotGradingCoeff == .5) {
sarg = 1 / sqrt(arg);
}
else {
sarg = exp(-model->VDMOSbulkJctBotGradingCoeff*
log(arg));
}
}
*(ckt->CKTstate0 + here->VDMOSqbd) =
here->VDMOStBulkPot*(here->VDMOSCbd*
(1 - arg*sarg)
/ (1 - model->VDMOSbulkJctBotGradingCoeff));
here->VDMOScapbd = here->VDMOSCbd * sarg;
}
else {
*(ckt->CKTstate0 + here->VDMOSqbd) = here->VDMOSf4d +
vbd * (here->VDMOSf2d + vbd * here->VDMOSf3d / 2);
here->VDMOScapbd = here->VDMOSf2d + vbd * here->VDMOSf3d;
}
}
else {
*(ckt->CKTstate0 + here->VDMOSqbd) = 0;
here->VDMOScapbd = 0;
}
}
/*
*/
if ((ckt->CKTmode & MODETRAN) || ((ckt->CKTmode&MODEINITTRAN)
&& !(ckt->CKTmode&MODEUIC))) {
/* (above only excludes tranop, since we're only at this
* point if tran or tranop )
*/
/*
* calculate equivalent conductances and currents for
* depletion capacitors
*/
/* integrate the capacitors and save results */
error = NIintegrate(ckt, &geq, &ceq, here->VDMOScapbd,
here->VDMOSqbd);
if (error) return(error);
here->VDMOSgbd += geq;
here->VDMOScbd += *(ckt->CKTstate0 + here->VDMOScqbd);
here->VDMOScd -= *(ckt->CKTstate0 + here->VDMOScqbd);
error = NIintegrate(ckt, &geq, &ceq, here->VDMOScapbs,
here->VDMOSqbs);
if (error) return(error);
here->VDMOSgbs += geq;
here->VDMOScbs += *(ckt->CKTstate0 + here->VDMOScqbs);
}
}
/*
*/
/*
* check convergence
*/
if ((here->VDMOSoff == 0) ||
(!(ckt->CKTmode & (MODEINITFIX | MODEINITSMSIG)))) {
if (Check == 1) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *)here;
}
}
/*
*/
/* save things away for next time */
@ -781,6 +656,236 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt)
*(here->VDMOSSPbPtr) += (-here->VDMOSgbs - (xnrm - xrev)*here->VDMOSgmbs);
*(here->VDMOSSPdpPtr) += (-here->VDMOSgds - xrev*
(here->VDMOSgm + here->VDMOSgmbs));
/* bulk diode model
* Delivers reverse conduction and forward breakdown
* of VDMOS transistor
*/
double vd; /* current diode voltage */
double vdtemp;
double vte;
double vtebrk;
double cd, cdb, csat, cdeq;
double czero;
double czof2;
double capd;
double gd, gdb, gspr;
double delvd; /* change in diode voltage temporary */
double diffcharge, deplcharge, diffcap, deplcap;
double evd, evrev;
#ifndef NOBYPASS
double tol; /* temporary for tolerence calculations */
#endif
cd = 0.0;
cdb = 0.0;
gd = 0.0;
gdb = 0.0;
csat = here->VDIOtSatCur;
gspr = here->VDIOtConductance;
vte = model->VDMOSDn * vt;
vtebrk = model->VDIObrkdEmissionCoeff * vt;
Check = 1;
if (ckt->CKTmode & MODEINITSMSIG) {
vd = *(ckt->CKTstate0 + here->VDIOvoltage);
}
else if (ckt->CKTmode & MODEINITTRAN) {
vd = *(ckt->CKTstate1 + here->VDIOvoltage);
}
else if ((ckt->CKTmode & MODEINITJCT) &&
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
vd = here->VDIOinitCond;
}
else if (ckt->CKTmode & MODEINITJCT) {
vd = here->VDIOtVcrit;
}
else {
#ifndef PREDICTOR
if (ckt->CKTmode & MODEINITPRED) {
*(ckt->CKTstate0 + here->VDIOvoltage) =
*(ckt->CKTstate1 + here->VDIOvoltage);
vd = DEVpred(ckt, here->VDIOvoltage);
*(ckt->CKTstate0 + here->VDIOcurrent) =
*(ckt->CKTstate1 + here->VDIOcurrent);
*(ckt->CKTstate0 + here->VDIOconduct) =
*(ckt->CKTstate1 + here->VDIOconduct);
}
else {
#endif /* PREDICTOR */
vd = *(ckt->CKTrhsOld + here->VDIOposPrimeNode) -
*(ckt->CKTrhsOld + here->VDMOSdNode);
#ifndef PREDICTOR
}
#endif /* PREDICTOR */
delvd = vd - *(ckt->CKTstate0 + here->VDIOvoltage);
cdhat = *(ckt->CKTstate0 + here->VDIOcurrent) +
*(ckt->CKTstate0 + here->VDIOconduct) * delvd;
/*
* bypass if solution has not changed
*/
#ifndef NOBYPASS
if ((!(ckt->CKTmode & MODEINITPRED)) && (ckt->CKTbypass)) {
tol = ckt->CKTvoltTol + ckt->CKTreltol*
MAX(fabs(vd), fabs(*(ckt->CKTstate0 + here->VDIOvoltage)));
if (fabs(delvd) < tol) {
tol = ckt->CKTreltol* MAX(fabs(cdhat),
fabs(*(ckt->CKTstate0 + here->VDIOcurrent))) +
ckt->CKTabstol;
if (fabs(cdhat - *(ckt->CKTstate0 + here->VDIOcurrent))
< tol) {
vd = *(ckt->CKTstate0 + here->VDIOvoltage);
cd = *(ckt->CKTstate0 + here->VDIOcurrent);
gd = *(ckt->CKTstate0 + here->VDIOconduct);
goto load;
}
}
}
#endif /* NOBYPASS */
/*
* limit new junction voltage
*/
if ((model->VDMOSDbvGiven) &&
(vd < MIN(0, -here->VDIOtBrkdwnV + 10 * vtebrk))) {
vdtemp = -(vd + here->VDIOtBrkdwnV);
vdtemp = DEVpnjlim(vdtemp,
-(*(ckt->CKTstate0 + here->VDIOvoltage) +
here->VDIOtBrkdwnV), vtebrk,
here->VDIOtVcrit, &Check);
vd = -(vdtemp + here->VDIOtBrkdwnV);
}
else {
vd = DEVpnjlim(vd, *(ckt->CKTstate0 + here->VDIOvoltage),
vte, here->VDIOtVcrit, &Check);
}
}
/*
* compute dc current and derivitives
*/
if (vd >= -3 * vte) { /* bottom current forward */
evd = exp(vd / vte);
cdb = csat*(evd - 1);
gdb = csat*evd / vte;
}
else if ((!(model->VDMOSDbvGiven)) ||
vd >= -here->VDIOtBrkdwnV) { /* reverse */
arg = 3 * vte / (vd*CONSTe);
arg = arg * arg * arg;
cdb = -csat*(1 + arg);
gdb = csat * 3 * arg / vd;
}
else { /* breakdown */
evrev = exp(-(here->VDIOtBrkdwnV + vd) / vtebrk);
cdb = -csat*evrev;
gdb = csat*evrev / vtebrk;
}
cd = cdb;
gd = gdb;
gd = gd + ckt->CKTgmin;
cd = cd + ckt->CKTgmin*vd;
if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) ||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) {
/*
* charge storage elements
*/
czero = here->VDIOtJctCap;
if (vd < here->VDIOtDepCap) {
arg = 1 - vd / here->VDIOtJctPot;
sarg = exp(-here->VDIOtGradingCoeff*log(arg));
deplcharge = here->VDIOtJctPot*czero*(1 - arg*sarg) / (1 - here->VDIOtGradingCoeff);
deplcap = czero*sarg;
}
else {
czof2 = czero / here->VDIOtF2;
deplcharge = czero*here->VDIOtF1 + czof2*(here->VDIOtF3*(vd - here->VDIOtDepCap) +
(here->VDIOtGradingCoeff / (here->VDIOtJctPot + here->VDIOtJctPot))*(vd*vd - here->VDIOtDepCap*here->VDIOtDepCap));
deplcap = czof2*(here->VDIOtF3 + here->VDIOtGradingCoeff*vd / here->VDIOtJctPot);
}
diffcharge = here->VDIOtTransitTime*cdb;
*(ckt->CKTstate0 + here->VDIOcapCharge) =
diffcharge + deplcharge;
diffcap = here->VDIOtTransitTime*gdb;
capd = diffcap + deplcap;
here->VDIOcap = capd;
/*
* store small-signal parameters
*/
if ((!(ckt->CKTmode & MODETRANOP)) ||
(!(ckt->CKTmode & MODEUIC))) {
if (ckt->CKTmode & MODEINITSMSIG) {
*(ckt->CKTstate0 + here->VDIOcapCurrent) = capd;
continue;
}
/*
* transient analysis
*/
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->VDIOcapCharge) =
*(ckt->CKTstate0 + here->VDIOcapCharge);
}
error = NIintegrate(ckt, &geq, &ceq, capd, here->VDIOcapCharge);
if (error) return(error);
gd = gd + geq;
cd = cd + *(ckt->CKTstate0 + here->VDIOcapCurrent);
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->VDIOcapCurrent) =
*(ckt->CKTstate0 + here->VDIOcapCurrent);
}
}
}
/*
* check convergence
*/
if (Check == 1) {
ckt->CKTnoncon++;
ckt->CKTtroubleElt = (GENinstance *)here;
}
*(ckt->CKTstate0 + here->VDIOvoltage) = vd;
*(ckt->CKTstate0 + here->VDIOcurrent) = cd;
*(ckt->CKTstate0 + here->VDIOconduct) = gd;
#ifndef NOBYPASS
load :
#endif
/*
* load current vector
*/
cdeq = cd - gd*vd;
*(ckt->CKTrhs + here->VDMOSdNode) += cdeq;
*(ckt->CKTrhs + here->VDIOposPrimeNode) -= cdeq;
/*
* load matrix
*/
/*
*(here->DIOposPosPtr) += gspr;
*(here->DIOnegNegPtr) += gd;
*(here->DIOposPrimePosPrimePtr) += (gd + gspr);
*(here->DIOposPosPrimePtr) -= gspr;
*(here->DIOnegPosPrimePtr) -= gd;
*(here->DIOposPrimePosPtr) -= gspr;
*(here->DIOposPrimeNegPtr) -= gd;
*/
}
}
return(OK);

View File

@ -69,13 +69,16 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
value->rValue = model->VDIOresistance;
return(OK);
case VDMOS_MOD_IS:
value->rValue = model->VDMOSjctSatCur;
value->rValue = model->VDIOjctSatCur;
return(OK);
case VDMOS_MOD_N:
value->rValue = model->VDMOSDn;
return(OK);
case VDMOS_MOD_VJ:
value->rValue = model->VDMOSbulkJctPotential;
value->rValue = model->VDIOjunctionPot;
return(OK);
case VDMOS_MOD_CJ:
value->rValue = model->VDIOjunctionCap;
return(OK);
case VDMOS_MOD_MJ:
value->rValue = model->VDMOSbulkJctBotGradingCoeff;
@ -90,7 +93,7 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
value->rValue = model->VDIObrkdEmissionCoeff;
return(OK);
case VDMOS_MOD_FC:
value->rValue = model->VDMOSfwdCapDepCoeff;
value->rValue = model->VDIOdepletionCapCoeff;
return(OK);
case VDMOS_MOD_TT:
value->rValue = model->VDIOtransitTime;

View File

@ -54,20 +54,26 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
model->VDIOresistTemp2 = 0;
break;
case VDMOS_MOD_IS:
model->VDMOSjctSatCur = value->rValue;
model->VDMOSjctSatCurGiven = TRUE;
model->VDIOjctSatCur = value->rValue;
model->VDIOjctSatCurGiven = TRUE;
break;
case VDMOS_MOD_VJ:
model->VDMOSbulkJctPotential = value->rValue;
model->VDMOSbulkJctPotentialGiven = TRUE;
model->VDIOjunctionPot = value->rValue;
model->VDIOjunctionPotGiven = TRUE;
break;
case VDMOS_MOD_CJ:
model->VDIOjunctionCap = value->rValue;
model->VDIOjunctionCapGiven = TRUE;
break;
case VDMOS_MOD_MJ:
model->VDMOSbulkJctBotGradingCoeff = value->rValue;
model->VDMOSbulkJctBotGradingCoeffGiven = TRUE;
model->VDIOgradCoeffTemp1 = 0;
model->VDIOgradCoeffTemp2 = 0;
break;
case VDMOS_MOD_FC:
model->VDMOSfwdCapDepCoeff = value->rValue;
model->VDMOSfwdCapDepCoeffGiven = TRUE;
model->VDIOdepletionCapCoeff = value->rValue;
model->VDIOdepletionCapCoeffGiven = TRUE;
break;
case VDMOS_MOD_NMOS:
if(value->iValue) {
@ -130,6 +136,8 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
case VDMOS_MOD_TT:
model->VDIOtransitTime = value->rValue;
model->VDIOtransitTimeGiven = TRUE;
model->VDIOtranTimeTemp1 = 0;
model->VDIOtranTimeTemp2 = 0;
break;
case VDMOS_MOD_EG:
model->VDMOSDeg = value->rValue;

View File

@ -30,8 +30,8 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
if (!model->VDMOStypeGiven) {
model->VDMOStype = NMOS;
}
if (!model->VDMOSjctSatCurGiven) {
model->VDMOSjctSatCur = 1e-14;
if (!model->VDIOjctSatCurGiven) {
model->VDIOjctSatCur = 1e-14;
}
if (!model->VDMOStransconductanceGiven) {
model->VDMOStransconductance = 1;
@ -39,14 +39,14 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
if (!model->VDMOSvt0Given) {
model->VDMOSvt0 = 0;
}
if (!model->VDMOSbulkJctPotentialGiven) {
model->VDMOSbulkJctPotential = .8;
if (!model->VDIOjunctionPotGiven) {
model->VDIOjunctionPot = .8;
}
if (!model->VDMOSbulkJctBotGradingCoeffGiven) {
model->VDMOSbulkJctBotGradingCoeff = .5;
}
if (!model->VDMOSfwdCapDepCoeffGiven) {
model->VDMOSfwdCapDepCoeff = .5;
if (!model->VDIOdepletionCapCoeffGiven) {
model->VDIOdepletionCapCoeff = .5;
}
if (!model->VDMOSphiGiven) {
model->VDMOSphi = .6;
@ -185,6 +185,29 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
here->VDMOSgNodePrime = here->VDMOSgNode;
}
if (model->VDIOresistance != 0 ) {
if (here->VDIOposPrimeNode == 0) {
error = CKTmkVolt(ckt, &tmp, here->VDMOSname, "bulk diode");
if (error) return(error);
here->VDIOposPrimeNode = tmp->number;
if (ckt->CKTcopyNodesets) {
CKTnode *tmpNode;
IFuid tmpName;
if (CKTinst2Node(ckt, here, 3, &tmpNode, &tmpName) == OK) {
if (tmpNode->nsGiven) {
tmp->nodeset = tmpNode->nodeset;
tmp->nsGiven = tmpNode->nsGiven;
}
}
}
}
}
else {
here->VDIOposPrimeNode = here->VDMOSdNode;
}
/* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \
@ -274,6 +297,11 @@ VDMOSunsetup(GENmodel *inModel, CKTcircuit *ckt)
&& here->VDMOSgNodePrime != here->VDMOSgNode)
CKTdltNNum(ckt, here->VDMOSgNodePrime);
here->VDMOSgNodePrime = 0;
if (here->VDIOposPrimeNode > 0
&& here->VDIOposPrimeNode != here->VDMOSdNode)
CKTdltNNum(ckt, here->VDIOposPrimeNode);
here->VDIOposPrimeNode = 0;
}
}
return OK;

View File

@ -25,6 +25,8 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
double phio;
double pbfact1,pbfact;
double vt,vtnom;
double xfc;
/* loop through all the resistor models */
for( ; model != NULL; model = VDMOSnextModel(model)) {
@ -52,6 +54,31 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
model->VDMOSoxideCapFactor = 0;
/* bulk diode model */
/* limit activation energy to min of .1 */
if (model->VDMOSDeg<.1) {
SPfrontEnd->IFerrorf(ERR_WARNING,
"%s: bulk diode activation energy too small, limited to 0.1",
model->VDMOSmodName);
model->VDMOSDeg = .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;
if ((!model->VDIOresistanceGiven) || (model->VDIOresistance == 0)) {
model->VDIOconductance = 0.0;
}
else {
model->VDIOconductance = 1 / model->VDIOresistance;
}
xfc = log(1 - model->VDIOdepletionCapCoeff);
/* loop through all instances of the model */
for(here = VDMOSinstances(model); here!= NULL;
@ -133,6 +160,136 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt)
} else {
here->VDMOSgateConductance = 0;
}
/* bulk diode model */
double egfet1, arg1, fact1, pbfact1, pbo, gmaold;
double fact2, pbfact, arg2, egfet, gmanew, factor;
double tBreakdownVoltage, vte, cbv;
double xbv, xcbv, tol, iter, dt;
/* loop through all the instances */
if (!here->VDMOSdtempGiven) here->VDMOStemp = 0.0;
if (!here->VDMOStempGiven)
here->VDMOStemp = ckt->CKTtemp + here->VDMOStemp;
dt = here->VDMOStemp - model->VDMOStnom;
/* Junction grading temperature adjust */
factor = 1.0 + (model->VDIOgradCoeffTemp1 * dt)
+ (model->VDIOgradCoeffTemp2 * dt * dt);
here->VDIOtGradingCoeff = model->VDMOSbulkJctBotGradingCoeff * factor;
vt = CONSTKoverQ * here->VDMOStemp;
/* this part gets really ugly - I won't even try to
* explain these equations */
fact2 = here->VDMOStemp / REFTEMP;
egfet = 1.16 - (7.02e-4*here->VDMOStemp*here->VDMOStemp) /
(here->VDMOStemp + 1108);
arg2 = -egfet / (2 * CONSTboltz*here->VDMOStemp) +
1.1150877 / (CONSTboltz*(REFTEMP + REFTEMP));
pbfact = -2 * vt*(1.5*log(fact2) + CHARGE*arg2);
egfet1 = 1.16 - (7.02e-4*model->VDMOStnom*model->VDMOStnom) /
(model->VDMOStnom + 1108);
arg1 = -egfet1 / (CONSTboltz * 2 * model->VDMOStnom) +
1.1150877 / (2 * CONSTboltz*REFTEMP);
fact1 = model->VDMOStnom / REFTEMP;
pbfact1 = -2 * vtnom*(1.5*log(fact1) + CHARGE*arg1);
pbo = (model->VDIOjunctionPot - pbfact1) / fact1;
gmaold = (model->VDIOjunctionPot - pbo) / pbo;
here->VDIOtJctCap = 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 = model->VDIOjctSatCur * exp(
((here->VDMOStemp / model->VDMOStnom) - 1) *
model->VDMOSDeg / (model->VDMOSDn*vt) +
model->VDMOSDxti / model->VDMOSDn *
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->VDMOSDn*vt;
here->VDIOtVcrit = vte * log(vte / (CONSTroot2*here->VDIOtSatCur));
/* limit junction potential to max of 1/FC */
if (here->VDIOtDepCap > 1.0) {
here->VDIOtJctPot = 1.0 / model->VDMOSDn;
here->VDIOtDepCap = model->VDMOSDn*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->VDMOSDbvGiven) {
/* tlev == 0 */
tBreakdownVoltage = model->VDMOSDbv;
cbv = model->VDMOSDibv;
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->DIOname, 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->DIOname, 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 = model->VDIOconductance;
if (model->VDIOresistanceGiven && model->VDIOresistance != 0.0) {
factor = 1.0 + (model->VDIOresistTemp1) * dt
+ (model->VDIOresistTemp2 * dt * dt);
here->VDIOtConductance = model->VDIOconductance / factor;
}
here->VDIOtF2 = exp((1 + here->VDIOtGradingCoeff)*xfc);
here->VDIOtF3 = 1 - model->VDIOdepletionCapCoeff*
(1 + here->VDIOtGradingCoeff);
}
}
return(OK);