correct the diode temperature model
This commit is contained in:
parent
c0e2d4abef
commit
fb23e1f024
|
|
@ -25,7 +25,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
double arg;
|
double arg;
|
||||||
double argsw;
|
double argsw;
|
||||||
double capd;
|
double capd;
|
||||||
double cd, cdsw=0.0;
|
double cd;
|
||||||
double cdeq;
|
double cdeq;
|
||||||
double cdhat;
|
double cdhat;
|
||||||
double ceq;
|
double ceq;
|
||||||
|
|
@ -44,9 +44,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
|
|
||||||
double delvd; /* change in diode voltage temporary */
|
double delvd; /* change in diode voltage temporary */
|
||||||
double evd;
|
double evd;
|
||||||
double evdsw;
|
|
||||||
double evrev;
|
double evrev;
|
||||||
double gd, gdsw=0.0;
|
double gd;
|
||||||
double geq;
|
double geq;
|
||||||
double gspr; /* area-scaled conductance */
|
double gspr; /* area-scaled conductance */
|
||||||
double sarg;
|
double sarg;
|
||||||
|
|
@ -85,6 +84,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
#endif /* SENSDEBUG */
|
#endif /* SENSDEBUG */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
cd = 0.0;
|
||||||
|
gd = 0.0;
|
||||||
csat = here->DIOtSatCur;
|
csat = here->DIOtSatCur;
|
||||||
csatsw = here->DIOtSatSWCur;
|
csatsw = here->DIOtSatSWCur;
|
||||||
gspr = here->DIOtConductance * here->DIOarea;
|
gspr = here->DIOtConductance * here->DIOarea;
|
||||||
|
|
@ -188,60 +189,35 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
/*
|
/*
|
||||||
* compute dc current and derivitives
|
* compute dc current and derivitives
|
||||||
*/
|
*/
|
||||||
next1: if (model->DIOsatSWCurGiven) { /* consider sidewall currents */
|
next1: if (model->DIOsatSWCurGiven) { /* sidewall current */
|
||||||
|
|
||||||
if (model->DIOswEmissionCoeffGiven) { /* sidewall currents with own characteristic */
|
if (model->DIOswEmissionCoeffGiven) { /* current with own characteristic */
|
||||||
|
|
||||||
vtesw = model->DIOswEmissionCoeff * vt;
|
vtesw = model->DIOswEmissionCoeff * vt;
|
||||||
|
|
||||||
if (vd >= -3*vtesw) { /* sidewall forward */
|
if (vd >= -3*vtesw) { /* forward */
|
||||||
|
|
||||||
evdsw = exp(vd/vtesw);
|
evd = exp(vd/vtesw);
|
||||||
cdsw = csatsw*(evdsw-1);
|
cd = csatsw*(evd-1);
|
||||||
gdsw = csatsw*evdsw/vtesw;
|
gd = csatsw*evd/vtesw;
|
||||||
if (model->DIOtunSatSWCurGiven) {
|
|
||||||
vtetun = model->DIOtunEmissionCoeff * vt;
|
|
||||||
evd = exp(-vd/vtetun);
|
|
||||||
cdsw = cdsw - here->DIOtTunSatSWCur * (evd - 1);
|
|
||||||
gdsw = gdsw + here->DIOtTunSatSWCur * evd / vtetun;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if((!(model->DIObreakdownVoltageGiven)) || /* sidewall reverse */
|
} else if((!(model->DIObreakdownVoltageGiven)) ||
|
||||||
vd >= -here->DIOtBrkdwnV) {
|
vd >= -here->DIOtBrkdwnV) { /* reverse */
|
||||||
|
|
||||||
if (model->DIOtunSatSWCurGiven) {
|
argsw = 3*vtesw/(vd*CONSTe);
|
||||||
evdsw = exp(vd/vtesw);
|
argsw = argsw * argsw * argsw;
|
||||||
cdsw = csatsw*(evdsw-1);
|
cd = -csatsw*(1+argsw);
|
||||||
gdsw = csatsw*evdsw/vtesw;
|
gd = csatsw*3*argsw/vd;
|
||||||
vtetun = model->DIOtunEmissionCoeff * vt;
|
|
||||||
evdsw = exp(-vd/vtetun);
|
|
||||||
cdsw = cdsw - here->DIOtTunSatSWCur * (evdsw - 1);
|
|
||||||
gdsw = gdsw + here->DIOtTunSatSWCur * evdsw / vtetun;
|
|
||||||
} else {
|
|
||||||
argsw = 3*vtesw/(vd*CONSTe);
|
|
||||||
argsw = argsw * argsw * argsw;
|
|
||||||
cdsw = -csatsw*(1+argsw);
|
|
||||||
gdsw = csatsw*3*argsw/vd;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* sidewall breakdown */
|
} else { /* breakdown */
|
||||||
|
|
||||||
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
|
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
|
||||||
cdsw = -csatsw*evrev;
|
cd = -csatsw*evrev;
|
||||||
gdsw = csatsw*evrev/vtebrk;
|
gd = csatsw*evrev/vtebrk;
|
||||||
if (model->DIOtunSatSWCurGiven) {
|
|
||||||
evd = exp(vd/vte);
|
|
||||||
cdsw = cdsw - csatsw*(evd-1);
|
|
||||||
gdsw = gdsw - csatsw*evd/vte;
|
|
||||||
vtetun = model->DIOtunEmissionCoeff * vt;
|
|
||||||
evd = exp(-vd/vtetun);
|
|
||||||
cdsw = cdsw - here->DIOtTunSatSWCur * (evd - 1);
|
|
||||||
gdsw = gdsw + here->DIOtTunSatSWCur * evd / vtetun;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { /* merge the current densities and use same characteristic as bottom diode */
|
} else { /* merge saturation currents and use same characteristic as bottom diode */
|
||||||
|
|
||||||
csat = csat + csatsw;
|
csat = csat + csatsw;
|
||||||
|
|
||||||
|
|
@ -249,65 +225,50 @@ next1: if (model->DIOsatSWCurGiven) { /* consider sidewall currents */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd >= -3*vte) { /* bottom forward */
|
if (vd >= -3*vte) { /* bottom current forward */
|
||||||
|
|
||||||
evd = exp(vd/vte);
|
evd = exp(vd/vte);
|
||||||
cd = csat*(evd-1);
|
cd = cd + csat*(evd-1);
|
||||||
gd = csat*evd/vte;
|
gd = gd + csat*evd/vte;
|
||||||
if (model->DIOtunSatCurGiven) {
|
|
||||||
vtetun = model->DIOtunEmissionCoeff * vt;
|
|
||||||
evd = exp(-vd/vtetun);
|
|
||||||
cd = cd - here->DIOtTunSatCur * (evd - 1);
|
|
||||||
gd = gd + here->DIOtTunSatCur * evd / vtetun;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if((!(model->DIObreakdownVoltageGiven)) || /* bottom reverse */
|
} else if((!(model->DIObreakdownVoltageGiven)) ||
|
||||||
vd >= -here->DIOtBrkdwnV) {
|
vd >= -here->DIOtBrkdwnV) { /* reverse */
|
||||||
|
|
||||||
if (model->DIOtunSatCurGiven) {
|
arg = 3*vte/(vd*CONSTe);
|
||||||
evd = exp(vd/vte);
|
arg = arg * arg * arg;
|
||||||
cd = csat*(evd-1);
|
cd = cd - csat*(1+arg);
|
||||||
gd = csat*evd/vte;
|
gd = gd + csat*3*arg/vd;
|
||||||
vtetun = model->DIOtunEmissionCoeff * vt;
|
|
||||||
evd = exp(-vd/vtetun);
|
|
||||||
cd = cd - here->DIOtTunSatCur * (evd - 1);
|
|
||||||
gd = gd + here->DIOtTunSatCur * evd / vtetun;
|
|
||||||
} else {
|
|
||||||
arg = 3*vte/(vd*CONSTe);
|
|
||||||
arg = arg * arg * arg;
|
|
||||||
cd = -csat*(1+arg);
|
|
||||||
gd = csat*3*arg/vd;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* bottom breakdown */
|
} else { /* breakdown */
|
||||||
|
|
||||||
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
|
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
|
||||||
cd = -csat*evrev;
|
cd = cd - csat*evrev;
|
||||||
gd = csat*evrev/vtebrk;
|
gd = gd + csat*evrev/vtebrk;
|
||||||
if (model->DIOtunSatCurGiven) {
|
|
||||||
evd = exp(vd/vte);
|
|
||||||
cd = cd - csat*(evd-1);
|
|
||||||
gd = gd - csat*evd/vte;
|
|
||||||
vtetun = model->DIOtunEmissionCoeff * vt;
|
|
||||||
evd = exp(-vd/vtetun);
|
|
||||||
cd = cd - here->DIOtTunSatCur * (evd - 1);
|
|
||||||
gd = gd + here->DIOtTunSatCur * evd / vtetun;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model->DIOsatSWCurGiven) {
|
if (model->DIOtunSatSWCurGiven) { /* tunnel sidewall current */
|
||||||
|
|
||||||
if (model->DIOswEmissionCoeffGiven) {
|
vtetun = model->DIOtunEmissionCoeff * vt;
|
||||||
|
evd = exp(-vd/vtetun);
|
||||||
|
|
||||||
cd = cdsw + cd;
|
cd = cd - here->DIOtTunSatSWCur * (evd - 1);
|
||||||
gd = gdsw + gd;
|
gd = gd + here->DIOtTunSatSWCur * evd / vtetun;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd >= -3*vte) { /* limit forward */
|
if (model->DIOtunSatCurGiven) { /* tunnel bottom current */
|
||||||
|
|
||||||
|
vtetun = model->DIOtunEmissionCoeff * vt;
|
||||||
|
evd = exp(-vd/vtetun);
|
||||||
|
|
||||||
|
cd = cd - here->DIOtTunSatCur * (evd - 1);
|
||||||
|
gd = gd + here->DIOtTunSatCur * evd / vtetun;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (vd >= -3*vte) { /* limit forward */
|
||||||
|
|
||||||
if( (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) {
|
if( (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) {
|
||||||
ikf_area_m = here->DIOforwardKneeCurrent;
|
ikf_area_m = here->DIOforwardKneeCurrent;
|
||||||
|
|
@ -316,7 +277,7 @@ next1: if (model->DIOsatSWCurGiven) { /* consider sidewall currents */
|
||||||
cd = cd/(1+sqrt_ikf) + ckt->CKTgmin;
|
cd = cd/(1+sqrt_ikf) + ckt->CKTgmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { /* limit reverse */
|
} else { /* limit reverse */
|
||||||
|
|
||||||
if( (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) {
|
if( (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) {
|
||||||
ikr_area_m = here->DIOreverseKneeCurrent;
|
ikr_area_m = here->DIOreverseKneeCurrent;
|
||||||
|
|
|
||||||
|
|
@ -178,9 +178,8 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||||
}
|
}
|
||||||
|
|
||||||
here->DIOarea = here->DIOarea * here->DIOm;
|
here->DIOarea = here->DIOarea * here->DIOm;
|
||||||
if (model->DIOlevel == 1) {
|
here->DIOpj = here->DIOpj * here->DIOm;
|
||||||
here->DIOpj = here->DIOpj * here->DIOm;
|
if (model->DIOlevel == 3) {
|
||||||
} else { /* level=3 */
|
|
||||||
if((here->DIOwGiven) && (here->DIOlGiven)) {
|
if((here->DIOwGiven) && (here->DIOlGiven)) {
|
||||||
here->DIOarea = here->DIOw * here->DIOl * here->DIOm;
|
here->DIOarea = here->DIOw * here->DIOl * here->DIOm;
|
||||||
here->DIOpj = (2 * here->DIOw + 2 * here->DIOl) * here->DIOm;
|
here->DIOpj = (2 * here->DIOw + 2 * here->DIOl) * here->DIOm;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
#endif
|
#endif
|
||||||
double dt;
|
double dt;
|
||||||
double factor;
|
double factor;
|
||||||
|
double tBreakdownVoltage;
|
||||||
|
|
||||||
/* loop through all the diode models */
|
/* loop through all the diode models */
|
||||||
for( ; model != NULL; model = model->DIOnextModel ) {
|
for( ; model != NULL; model = model->DIOnextModel ) {
|
||||||
|
|
@ -156,23 +157,23 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(
|
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(
|
||||||
((here->DIOtemp/model->DIOnomTemp)-1) *
|
((here->DIOtemp/model->DIOnomTemp)-1) *
|
||||||
model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) +
|
model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) +
|
||||||
model->DIOsaturationCurrentExp/model->DIOemissionCoeff*
|
model->DIOsaturationCurrentExp/model->DIOemissionCoeff *
|
||||||
log(here->DIOtemp/model->DIOnomTemp) );
|
log(here->DIOtemp/model->DIOnomTemp) );
|
||||||
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(
|
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(
|
||||||
((here->DIOtemp/model->DIOnomTemp)-1) *
|
((here->DIOtemp/model->DIOnomTemp)-1) *
|
||||||
model->DIOactivationEnergy/(model->DIOswEmissionCoeff*vt) +
|
model->DIOactivationEnergy/(model->DIOswEmissionCoeff*vt) +
|
||||||
model->DIOsaturationCurrentExp/model->DIOswEmissionCoeff*
|
model->DIOsaturationCurrentExp/model->DIOswEmissionCoeff *
|
||||||
log(here->DIOtemp/model->DIOnomTemp) );
|
log(here->DIOtemp/model->DIOnomTemp) );
|
||||||
|
|
||||||
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(
|
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(
|
||||||
((here->DIOtemp/model->DIOnomTemp)-1) *
|
((here->DIOtemp/model->DIOnomTemp)-1) *
|
||||||
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/(model->DIOtunEmissionCoeff*vt) +
|
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/vt +
|
||||||
model->DIOtunSaturationCurrentExp/model->DIOtunEmissionCoeff*
|
model->DIOtunSaturationCurrentExp *
|
||||||
log(here->DIOtemp/model->DIOnomTemp) );
|
log(here->DIOtemp/model->DIOnomTemp) );
|
||||||
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(
|
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(
|
||||||
((here->DIOtemp/model->DIOnomTemp)-1) *
|
((here->DIOtemp/model->DIOnomTemp)-1) *
|
||||||
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/(model->DIOtunEmissionCoeff*vt) +
|
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/vt +
|
||||||
model->DIOtunSaturationCurrentExp/model->DIOtunEmissionCoeff*
|
model->DIOtunSaturationCurrentExp *
|
||||||
log(here->DIOtemp/model->DIOnomTemp) );
|
log(here->DIOtemp/model->DIOnomTemp) );
|
||||||
|
|
||||||
/* the defintion of f1, just recompute after temperature adjusting
|
/* the defintion of f1, just recompute after temperature adjusting
|
||||||
|
|
@ -191,9 +192,18 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
/* and now to compute the breakdown voltage, again, using
|
/* and now to compute the breakdown voltage, again, using
|
||||||
* temperature adjusted basic parameters */
|
* temperature adjusted basic parameters */
|
||||||
if (model->DIObreakdownVoltageGiven){
|
if (model->DIObreakdownVoltageGiven){
|
||||||
cbv=model->DIObreakdownCurrent * here->DIOarea;
|
if (model->DIOtlev == 0) {
|
||||||
if (cbv < here->DIOtSatCur * model->DIObreakdownVoltage/vt) {
|
tBreakdownVoltage = model->DIObreakdownVoltage - model->DIOtcv * dt;
|
||||||
cbv=here->DIOtSatCur * model->DIObreakdownVoltage/vt;
|
} else {
|
||||||
|
tBreakdownVoltage = model->DIObreakdownVoltage * (1 - model->DIOtcv * dt);
|
||||||
|
}
|
||||||
|
if (model->DIOlevel == 1) {
|
||||||
|
cbv = model->DIObreakdownCurrent;
|
||||||
|
} else { /* level=3 */
|
||||||
|
cbv = model->DIObreakdownCurrent * here->DIOarea;
|
||||||
|
}
|
||||||
|
if (cbv < here->DIOtSatCur * tBreakdownVoltage/vt) {
|
||||||
|
cbv=here->DIOtSatCur * tBreakdownVoltage/vt;
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
emsg = TMALLOC(char, 100);
|
emsg = TMALLOC(char, 100);
|
||||||
if(emsg == NULL) return(E_NOMEM);
|
if(emsg == NULL) return(E_NOMEM);
|
||||||
|
|
@ -205,17 +215,17 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
SPfrontEnd->IFerror (ERR_WARNING,
|
SPfrontEnd->IFerror (ERR_WARNING,
|
||||||
"incompatibility with specified saturation current", NULL);
|
"incompatibility with specified saturation current", NULL);
|
||||||
#endif
|
#endif
|
||||||
xbv=model->DIObreakdownVoltage;
|
xbv=tBreakdownVoltage;
|
||||||
} else {
|
} else {
|
||||||
tol=ckt->CKTreltol*cbv;
|
tol=ckt->CKTreltol*cbv;
|
||||||
xbv=model->DIObreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(1+cbv/
|
xbv=tBreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(1+cbv/
|
||||||
(here->DIOtSatCur));
|
(here->DIOtSatCur));
|
||||||
iter=0;
|
iter=0;
|
||||||
for(iter=0 ; iter < 25 ; iter++) {
|
for(iter=0 ; iter < 25 ; iter++) {
|
||||||
xbv=model->DIObreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(cbv/
|
xbv=tBreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(cbv/
|
||||||
(here->DIOtSatCur)+1-xbv/vt);
|
(here->DIOtSatCur)+1-xbv/vt);
|
||||||
xcbv=here->DIOtSatCur *
|
xcbv=here->DIOtSatCur *
|
||||||
(exp((model->DIObreakdownVoltage-xbv)/(model->DIObrkdEmissionCoeff*vt))-1+xbv/vt);
|
(exp((tBreakdownVoltage-xbv)/(model->DIObrkdEmissionCoeff*vt))-1+xbv/vt);
|
||||||
if (fabs(xcbv-cbv) <= tol) goto matched;
|
if (fabs(xcbv-cbv) <= tol) goto matched;
|
||||||
}
|
}
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
|
|
@ -229,11 +239,7 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
matched:
|
matched:
|
||||||
if (model->DIOtlev == 0) {
|
here->DIOtBrkdwnV = xbv;
|
||||||
here->DIOtBrkdwnV = xbv - model->DIOtcv * dt;
|
|
||||||
} else if (model->DIOtlev == 1) {
|
|
||||||
here->DIOtBrkdwnV = xbv * (1 - model->DIOtcv * dt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* transit time temperature adjust */
|
/* transit time temperature adjust */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue