correct the diode temperature model

This commit is contained in:
dwarning 2012-09-20 21:06:34 +02:00
parent c0e2d4abef
commit fb23e1f024
3 changed files with 76 additions and 110 deletions

View File

@ -25,7 +25,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
double arg;
double argsw;
double capd;
double cd, cdsw=0.0;
double cd;
double cdeq;
double cdhat;
double ceq;
@ -44,9 +44,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
double delvd; /* change in diode voltage temporary */
double evd;
double evdsw;
double evrev;
double gd, gdsw=0.0;
double gd;
double geq;
double gspr; /* area-scaled conductance */
double sarg;
@ -85,6 +84,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
#endif /* SENSDEBUG */
}
cd = 0.0;
gd = 0.0;
csat = here->DIOtSatCur;
csatsw = here->DIOtSatSWCur;
gspr = here->DIOtConductance * here->DIOarea;
@ -188,60 +189,35 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
/*
* 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;
if (vd >= -3*vtesw) { /* sidewall forward */
if (vd >= -3*vtesw) { /* forward */
evdsw = exp(vd/vtesw);
cdsw = csatsw*(evdsw-1);
gdsw = csatsw*evdsw/vtesw;
if (model->DIOtunSatSWCurGiven) {
vtetun = model->DIOtunEmissionCoeff * vt;
evd = exp(-vd/vtetun);
cdsw = cdsw - here->DIOtTunSatSWCur * (evd - 1);
gdsw = gdsw + here->DIOtTunSatSWCur * evd / vtetun;
}
evd = exp(vd/vtesw);
cd = csatsw*(evd-1);
gd = csatsw*evd/vtesw;
} else if((!(model->DIObreakdownVoltageGiven)) || /* sidewall reverse */
vd >= -here->DIOtBrkdwnV) {
} else if((!(model->DIObreakdownVoltageGiven)) ||
vd >= -here->DIOtBrkdwnV) { /* reverse */
if (model->DIOtunSatSWCurGiven) {
evdsw = exp(vd/vtesw);
cdsw = csatsw*(evdsw-1);
gdsw = csatsw*evdsw/vtesw;
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;
}
argsw = 3*vtesw/(vd*CONSTe);
argsw = argsw * argsw * argsw;
cd = -csatsw*(1+argsw);
gd = csatsw*3*argsw/vd;
} else { /* sidewall breakdown */
} else { /* breakdown */
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
cdsw = -csatsw*evrev;
gdsw = 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;
}
cd = -csatsw*evrev;
gd = csatsw*evrev/vtebrk;
}
} 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;
@ -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);
cd = csat*(evd-1);
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;
}
cd = cd + csat*(evd-1);
gd = gd + csat*evd/vte;
} else if((!(model->DIObreakdownVoltageGiven)) || /* bottom reverse */
vd >= -here->DIOtBrkdwnV) {
} else if((!(model->DIObreakdownVoltageGiven)) ||
vd >= -here->DIOtBrkdwnV) { /* reverse */
if (model->DIOtunSatCurGiven) {
evd = exp(vd/vte);
cd = csat*(evd-1);
gd = csat*evd/vte;
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;
}
arg = 3*vte/(vd*CONSTe);
arg = arg * arg * arg;
cd = cd - csat*(1+arg);
gd = gd + csat*3*arg/vd;
} else { /* bottom breakdown */
} else { /* breakdown */
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
cd = -csat*evrev;
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;
}
cd = cd - csat*evrev;
gd = gd + csat*evrev/vtebrk;
}
if (model->DIOsatSWCurGiven) {
if (model->DIOtunSatSWCurGiven) { /* tunnel sidewall current */
if (model->DIOswEmissionCoeffGiven) {
vtetun = model->DIOtunEmissionCoeff * vt;
evd = exp(-vd/vtetun);
cd = cdsw + cd;
gd = gdsw + gd;
}
cd = cd - here->DIOtTunSatSWCur * (evd - 1);
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) ) {
ikf_area_m = here->DIOforwardKneeCurrent;
@ -316,7 +277,7 @@ next1: if (model->DIOsatSWCurGiven) { /* consider sidewall currents */
cd = cd/(1+sqrt_ikf) + ckt->CKTgmin;
}
} else { /* limit reverse */
} else { /* limit reverse */
if( (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) {
ikr_area_m = here->DIOreverseKneeCurrent;

View File

@ -178,9 +178,8 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
}
here->DIOarea = here->DIOarea * here->DIOm;
if (model->DIOlevel == 1) {
here->DIOpj = here->DIOpj * here->DIOm;
} else { /* level=3 */
here->DIOpj = here->DIOpj * here->DIOm;
if (model->DIOlevel == 3) {
if((here->DIOwGiven) && (here->DIOlGiven)) {
here->DIOarea = here->DIOw * here->DIOl * here->DIOm;
here->DIOpj = (2 * here->DIOw + 2 * here->DIOl) * here->DIOm;

View File

@ -33,6 +33,7 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
#endif
double dt;
double factor;
double tBreakdownVoltage;
/* loop through all the diode models */
for( ; model != NULL; model = model->DIOnextModel ) {
@ -156,23 +157,23 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(
((here->DIOtemp/model->DIOnomTemp)-1) *
model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) +
model->DIOsaturationCurrentExp/model->DIOemissionCoeff*
model->DIOsaturationCurrentExp/model->DIOemissionCoeff *
log(here->DIOtemp/model->DIOnomTemp) );
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(
((here->DIOtemp/model->DIOnomTemp)-1) *
model->DIOactivationEnergy/(model->DIOswEmissionCoeff*vt) +
model->DIOsaturationCurrentExp/model->DIOswEmissionCoeff*
model->DIOsaturationCurrentExp/model->DIOswEmissionCoeff *
log(here->DIOtemp/model->DIOnomTemp) );
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(
((here->DIOtemp/model->DIOnomTemp)-1) *
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/(model->DIOtunEmissionCoeff*vt) +
model->DIOtunSaturationCurrentExp/model->DIOtunEmissionCoeff*
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/vt +
model->DIOtunSaturationCurrentExp *
log(here->DIOtemp/model->DIOnomTemp) );
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(
((here->DIOtemp/model->DIOnomTemp)-1) *
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/(model->DIOtunEmissionCoeff*vt) +
model->DIOtunSaturationCurrentExp/model->DIOtunEmissionCoeff*
model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy/vt +
model->DIOtunSaturationCurrentExp *
log(here->DIOtemp/model->DIOnomTemp) );
/* 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
* temperature adjusted basic parameters */
if (model->DIObreakdownVoltageGiven){
cbv=model->DIObreakdownCurrent * here->DIOarea;
if (cbv < here->DIOtSatCur * model->DIObreakdownVoltage/vt) {
cbv=here->DIOtSatCur * model->DIObreakdownVoltage/vt;
if (model->DIOtlev == 0) {
tBreakdownVoltage = model->DIObreakdownVoltage - model->DIOtcv * dt;
} 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
emsg = TMALLOC(char, 100);
if(emsg == NULL) return(E_NOMEM);
@ -205,17 +215,17 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
SPfrontEnd->IFerror (ERR_WARNING,
"incompatibility with specified saturation current", NULL);
#endif
xbv=model->DIObreakdownVoltage;
xbv=tBreakdownVoltage;
} else {
tol=ckt->CKTreltol*cbv;
xbv=model->DIObreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(1+cbv/
xbv=tBreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(1+cbv/
(here->DIOtSatCur));
iter=0;
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);
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;
}
#ifdef TRACE
@ -229,11 +239,7 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt)
#endif
}
matched:
if (model->DIOtlev == 0) {
here->DIOtBrkdwnV = xbv - model->DIOtcv * dt;
} else if (model->DIOtlev == 1) {
here->DIOtBrkdwnV = xbv * (1 - model->DIOtcv * dt);
}
here->DIOtBrkdwnV = xbv;
}
/* transit time temperature adjust */