diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index 416cc8072..6369603b0 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -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; diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index d6d0de6d9..9ab1155af 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -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; diff --git a/src/spicelib/devices/dio/diotemp.c b/src/spicelib/devices/dio/diotemp.c index 456f891cd..49214aba5 100644 --- a/src/spicelib/devices/dio/diotemp.c +++ b/src/spicelib/devices/dio/diotemp.c @@ -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 */