Fixed the diode scaling bug reported by A. Buermen

This commit is contained in:
dwarning 2024-12-10 14:04:13 +01:00 committed by Holger Vogt
parent 727f11edf0
commit 4bd5ebe3e3
5 changed files with 23 additions and 25 deletions

View File

@ -60,7 +60,7 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt)
* This is an old analysis anyway.... * This is an old analysis anyway....
*/ */
csat=(here->DIOtSatCur*here->DIOarea+here->DIOtSatSWCur*here->DIOpj)*here->DIOm; csat=here->DIOtSatCur+here->DIOtSatSWCur; // area and multiplier are already counted in tSatCur and tSatSWCur
vt = CONSTKoverQ * here->DIOtemp; vt = CONSTKoverQ * here->DIOtemp;
vte=model->DIOemissionCoeff * vt; vte=model->DIOemissionCoeff * vt;
vd = *(ckt->CKTrhsOld + (here->DIOposPrimeNode)) - vd = *(ckt->CKTrhsOld + (here->DIOposPrimeNode)) -
@ -113,7 +113,7 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt)
/* /*
* junction charge storage elements * junction charge storage elements
*/ */
czero=here->DIOtJctCap*here->DIOarea*here->DIOm; czero=here->DIOtJctCap; // area and multiplier are already counted in DIOtJctCap
if (czero != 0.0) { if (czero != 0.0) {
if (vd < here->DIOtDepCap){ if (vd < here->DIOtDepCap){
arg=1-vd/model->DIOjunctionPot; arg=1-vd/model->DIOjunctionPot;
@ -143,7 +143,7 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt)
{ {
cjunc1 = cjunc2 = cjunc3 = 0.0; cjunc1 = cjunc2 = cjunc3 = 0.0;
} }
czeroSW=+here->DIOtJctSWCap*here->DIOpj*here->DIOm; czeroSW=+here->DIOtJctSWCap; // pj and multiplier are already counted in DIOtJctSWCap
if (czeroSW != 0.0) { if (czeroSW != 0.0) {
if (vd < here->DIOtDepCap){ if (vd < here->DIOtDepCap){
arg=1-vd/model->DIOjunctionSWPot; arg=1-vd/model->DIOjunctionSWPot;

View File

@ -89,7 +89,7 @@ DIOnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
NevalSrcInstanceTemp(&noizDens[DIORSNOIZ],&lnNdens[DIORSNOIZ], NevalSrcInstanceTemp(&noizDens[DIORSNOIZ],&lnNdens[DIORSNOIZ],
ckt, THERMNOISE, inst->DIOposPrimeNode, inst->DIOposNode, ckt, THERMNOISE, inst->DIOposPrimeNode, inst->DIOposNode,
inst->DIOtConductance * inst->DIOarea * inst->DIOm, dtemp); inst->DIOtConductance, dtemp);
NevalSrc(&noizDens[DIOIDNOIZ],&lnNdens[DIOIDNOIZ], NevalSrc(&noizDens[DIOIDNOIZ],&lnNdens[DIOIDNOIZ],
ckt, SHOTNOISE, inst->DIOposPrimeNode, inst->DIOnegNode, ckt, SHOTNOISE, inst->DIOposPrimeNode, inst->DIOnegNode,

View File

@ -172,7 +172,7 @@ pertvd: /* Perturbation of Diode Voltage */
*(here->DIOsenCeq + 2)= *(ckt->CKTstate0 + here->DIOcapCurrent); *(here->DIOsenCeq + 2)= *(ckt->CKTstate0 + here->DIOcapCurrent);
*(ckt->CKTstate0 + here->DIOvoltage) = A0; *(ckt->CKTstate0 + here->DIOvoltage) = A0;
} }
gspr=here->DIOtConductance*here->DIOarea; gspr=here->DIOtConductance;
geq = *(here->DIOsenGeq + 2); geq = *(here->DIOsenGeq + 2);
xceq = *(here->DIOsenCeq + 2) * ckt->CKTomega; xceq = *(here->DIOsenCeq + 2) * ckt->CKTomega;

View File

@ -296,8 +296,6 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
here->DIOm = 1; here->DIOm = 1;
} }
here->DIOarea = here->DIOarea * here->DIOm;
here->DIOpj = here->DIOpj * here->DIOm;
here->DIOcmetal = 0.0; here->DIOcmetal = 0.0;
here->DIOcpoly = 0.0; here->DIOcpoly = 0.0;
if (model->DIOlevel == 3) { if (model->DIOlevel == 3) {
@ -331,10 +329,10 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
* (wp * scale + model->DIOpolyMaskOffset) * (wp * scale + model->DIOpolyMaskOffset)
* (lp * scale + model->DIOpolyMaskOffset); * (lp * scale + model->DIOpolyMaskOffset);
} }
here->DIOforwardKneeCurrent = model->DIOforwardKneeCurrent * here->DIOarea; here->DIOforwardKneeCurrent = model->DIOforwardKneeCurrent * here->DIOarea * here->DIOm;
here->DIOreverseKneeCurrent = model->DIOreverseKneeCurrent * here->DIOarea; here->DIOreverseKneeCurrent = model->DIOreverseKneeCurrent * here->DIOarea * here->DIOm;
here->DIOjunctionCap = model->DIOjunctionCap * here->DIOarea; here->DIOjunctionCap = model->DIOjunctionCap * here->DIOarea * here->DIOm;
here->DIOjunctionSWCap = model->DIOjunctionSWCap * here->DIOpj; here->DIOjunctionSWCap = model->DIOjunctionSWCap * here->DIOpj * here->DIOm;
here->DIOstate = *states; here->DIOstate = *states;
*states += DIOnumStates; *states += DIOnumStates;

View File

@ -116,7 +116,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vte*Temp); - model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vte*Temp);
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio; arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio;
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp; arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(arg1 + arg2); here->DIOtSatCur = model->DIOsatCur * here->DIOarea * here->DIOm * exp(arg1 + arg2);
here->DIOtSatCur_dT = here->DIOtSatCur * (arg1_dT + arg2_dT); here->DIOtSatCur_dT = here->DIOtSatCur * (arg1_dT + arg2_dT);
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vts; arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vts;
@ -124,7 +124,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vts*Temp); - model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vts*Temp);
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio; arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio;
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp; arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2); here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * here->DIOm * exp(arg1 + arg2);
here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (arg1_dT + arg2_dT); here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (arg1_dT + arg2_dT);
arg1 = ((Temp/model->DIOnomTemp)-1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt; arg1 = ((Temp/model->DIOnomTemp)-1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
@ -132,10 +132,10 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtt*Temp); - model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtt*Temp);
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio; arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio;
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp; arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2); here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * here->DIOm * exp(arg1 + arg2);
here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (arg1_dT + arg2_dT); here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (arg1_dT + arg2_dT);
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(arg1 + arg2); here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * here->DIOm * exp(arg1 + arg2);
here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (arg1_dT + arg2_dT); here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (arg1_dT + arg2_dT);
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vtr; arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vtr;
@ -143,7 +143,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtr*Temp); - model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtr*Temp);
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio; arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio;
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp; arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2); here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * here->DIOm * exp(arg1 + arg2);
here->DIOtRecSatCur_dT = here->DIOtRecSatCur * (arg1_dT + arg2_dT); here->DIOtRecSatCur_dT = here->DIOtRecSatCur * (arg1_dT + arg2_dT);
} else { } else {
arg0 = egfet1 / (model->DIOemissionCoeff * vtnom); arg0 = egfet1 / (model->DIOemissionCoeff * vtnom);
@ -151,7 +151,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
arg1_dT = (egfet_dT * vte - egfet * vte_dT) / (egfet*egfet); arg1_dT = (egfet_dT * vte - egfet * vte_dT) / (egfet*egfet);
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio; arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio;
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp; arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(arg0 - arg1 + arg2); here->DIOtSatCur = model->DIOsatCur * here->DIOarea * here->DIOm * exp(arg0 - arg1 + arg2);
here->DIOtSatCur_dT = here->DIOtSatCur * (-arg1_dT + arg2_dT); here->DIOtSatCur_dT = here->DIOtSatCur * (-arg1_dT + arg2_dT);
arg0 = egfet1 / (model->DIOswEmissionCoeff * vtnom); arg0 = egfet1 / (model->DIOswEmissionCoeff * vtnom);
@ -159,7 +159,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
arg1_dT = (egfet_dT * vts - egfet * vts_dT) / (egfet*egfet); arg1_dT = (egfet_dT * vts - egfet * vts_dT) / (egfet*egfet);
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio; arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio;
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp; arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg0 - arg1 + arg2); here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * here->DIOm * exp(arg0 - arg1 + arg2);
here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (-arg1_dT + arg2_dT); here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (-arg1_dT + arg2_dT);
arg0 = model->DIOtunEGcorrectionFactor * egfet1 / (model->DIOtunEmissionCoeff * vtnom); arg0 = model->DIOtunEGcorrectionFactor * egfet1 / (model->DIOtunEmissionCoeff * vtnom);
@ -167,10 +167,10 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
arg1_dT = model->DIOtunEGcorrectionFactor * (egfet_dT * vtt - egfet * vtt_dT) / (egfet*egfet); arg1_dT = model->DIOtunEGcorrectionFactor * (egfet_dT * vtt - egfet * vtt_dT) / (egfet*egfet);
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio; arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio;
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp; arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg0 - arg1 + arg2); here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * here->DIOm * exp(arg0 - arg1 + arg2);
here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (-arg1_dT + arg2_dT); here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (-arg1_dT + arg2_dT);
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(arg0 - arg1 + arg2); here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * here->DIOm * exp(arg0 - arg1 + arg2);
here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (-arg1_dT + arg2_dT); here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (-arg1_dT + arg2_dT);
arg0 = egfet1 / (model->DIOrecEmissionCoeff * vtnom); arg0 = egfet1 / (model->DIOrecEmissionCoeff * vtnom);
@ -178,7 +178,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
arg1_dT = (egfet_dT * vtr - egfet * vtr_dT) / (egfet*egfet); arg1_dT = (egfet_dT * vtr - egfet * vtr_dT) / (egfet*egfet);
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio; arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio;
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp; arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg0 - arg1 + arg2); here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * here->DIOm * exp(arg0 - arg1 + arg2);
here->DIOtRecSatCur_dT = here->DIOtRecSatCur * (-arg1_dT + arg2_dT); here->DIOtRecSatCur_dT = here->DIOtRecSatCur * (-arg1_dT + arg2_dT);
} }
@ -209,7 +209,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
if (model->DIOlevel == 1) { if (model->DIOlevel == 1) {
cbv = here->DIOm * model->DIObreakdownCurrent; cbv = here->DIOm * model->DIObreakdownCurrent;
} else { /* level=3 */ } else { /* level=3 */
cbv = model->DIObreakdownCurrent * here->DIOarea; cbv = model->DIObreakdownCurrent * here->DIOarea * here->DIOm;
} }
if (cbv < here->DIOtSatCur * tBreakdownVoltage/vt) { if (cbv < here->DIOtSatCur * tBreakdownVoltage/vt) {
#ifdef TRACE #ifdef TRACE
@ -244,12 +244,12 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
here->DIOtTransitTime = model->DIOtransitTime * factor; here->DIOtTransitTime = model->DIOtransitTime * factor;
/* Series resistance temperature adjust */ /* Series resistance temperature adjust */
here->DIOtConductance = model->DIOconductance * here->DIOarea; here->DIOtConductance = model->DIOconductance * here->DIOarea * here->DIOm;
if(model->DIOresistGiven && model->DIOresist!=0.0) { if(model->DIOresistGiven && model->DIOresist!=0.0) {
factor = 1.0 + (model->DIOresistTemp1) * dt factor = 1.0 + (model->DIOresistTemp1) * dt
+ (model->DIOresistTemp2 * dt * dt); + (model->DIOresistTemp2 * dt * dt);
here->DIOtConductance = model->DIOconductance * here->DIOarea / factor; here->DIOtConductance = model->DIOconductance * here->DIOarea * here->DIOm / factor;
here->DIOtConductance_dT = -model->DIOconductance * here->DIOarea * here->DIOtConductance_dT = -model->DIOconductance * here->DIOarea * here->DIOm *
(model->DIOresistTemp1 + model->DIOresistTemp2 * dt) / (factor*factor); (model->DIOresistTemp1 + model->DIOresistTemp2 * dt) / (factor*factor);
} }