diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index bbdfbab30..285cdedf2 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ #include "ngspice.h" @@ -11,14 +12,18 @@ Author: 1985 Thomas L. Quarles IFparm DIOpTable[] = { /* parameters */ IOPU("off", DIO_OFF, IF_FLAG, "Initially off"), IOPU("temp", DIO_TEMP, IF_REAL, "Instance temperature"), - IOPAU("ic", DIO_IC, IF_REAL, "Initial device voltage"), + IOPU("dtemp", DIO_DTEMP, IF_REAL, "Instance delta temperature"), + IOPAU("ic", DIO_IC, IF_REAL, "Initial device voltage"), IOPU("area", DIO_AREA, IF_REAL, "Area factor"), + IOPU("pj", DIO_PJ, IF_REAL, "Perimeter factor"), + IOPU("m", DIO_M, IF_REAL, "Multiplier"), + IP("sens_area",DIO_AREA_SENS,IF_FLAG,"flag to request sensitivity WRT area"), - OP("vd",DIO_VOLTAGE,IF_REAL, "Diode voltage"), + OP("vd", DIO_VOLTAGE,IF_REAL, "Diode voltage"), OP("id", DIO_CURRENT,IF_REAL, "Diode current"), OPR("c", DIO_CURRENT,IF_REAL, "Diode current"), OP("gd", DIO_CONDUCT,IF_REAL, "Diode conductance"), - OP("cd", DIO_CAP, IF_REAL, "Diode capacitance"), + OP("cd", DIO_CAP, IF_REAL, "Diode capacitance"), OPU("charge", DIO_CHARGE, IF_REAL, "Diode capacitor charge"), OPU("capcur", DIO_CAPCUR, IF_REAL, "Diode capacitor current"), OPU("p", DIO_POWER, IF_REAL, "Diode power"), @@ -32,15 +37,32 @@ IFparm DIOpTable[] = { /* parameters */ }; IFparm DIOmPTable[] = { /* model parameters */ - IOP( "is", DIO_MOD_IS, IF_REAL, "Saturation current"), + IOP( "is", DIO_MOD_IS, IF_REAL, "Saturation current"), + IOPR( "js", DIO_MOD_IS, IF_REAL, "Saturation current"), + IOP( "jsw", DIO_MOD_JSW, IF_REAL, "Sidewall Saturation current"), + IOPU( "tnom",DIO_MOD_TNOM,IF_REAL, "Parameter measurement temperature"), IOP( "rs", DIO_MOD_RS, IF_REAL, "Ohmic resistance"), + IOP( "trs", DIO_MOD_TRS, IF_REAL, "Ohmic resistance temp. coeff."), IOP( "n", DIO_MOD_N, IF_REAL, "Emission Coefficient"), IOPA( "tt", DIO_MOD_TT, IF_REAL, "Transit Time"), + IOPA( "ttt1", DIO_MOD_TTT1, IF_REAL, "Transit Time 1st order temp. coeff."), + IOPA( "ttt2", DIO_MOD_TTT2, IF_REAL, "Transit Time 2nd order temp. coeff."), IOPA( "cjo", DIO_MOD_CJO, IF_REAL, "Junction capacitance"), IOPR( "cj0", DIO_MOD_CJO, IF_REAL, "Junction capacitance"), IOP( "vj", DIO_MOD_VJ, IF_REAL, "Junction potential"), IOP( "m", DIO_MOD_M, IF_REAL, "Grading coefficient"), + IOPR("mj", DIO_MOD_M, IF_REAL, "Grading coefficient"), + IOP("tm1", DIO_MOD_TM1, IF_REAL, " Grading coefficient 1st temp. coeff."), + IOP("tm1", DIO_MOD_TM2, IF_REAL, " Grading coefficient 2nd temp. coeff."), + IOP( "cjp", DIO_MOD_CJSW, IF_REAL, "Sidewall junction capacitance"), + IOPR( "cjsw", DIO_MOD_CJSW, IF_REAL, "Sidewall junction capacitance"), + IOP( "php", DIO_MOD_VJSW, IF_REAL, "Sidewall junction potential"), + IOP( "mjsw", DIO_MOD_MJSW, IF_REAL, "Sidewall Grading coefficient"), + IOP( "ikf", DIO_MOD_IKF, IF_REAL, "Forward Knee current"), + IOPR( "ik", DIO_MOD_IKF, IF_REAL, "Forward Knee current"), + IOP("ikr", DIO_MOD_IKR, IF_REAL, "Reverse Knee current"), + IOP( "eg", DIO_MOD_EG, IF_REAL, "Activation energy"), IOP( "xti", DIO_MOD_XTI, IF_REAL, "Saturation current temperature exp."), IOP( "kf", DIO_MOD_KF, IF_REAL, "flicker noise coefficient"), diff --git a/src/spicelib/devices/dio/dioacld.c b/src/spicelib/devices/dio/dioacld.c index 3597b3a55..907b99b28 100644 --- a/src/spicelib/devices/dio/dioacld.c +++ b/src/spicelib/devices/dio/dioacld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ /* */ @@ -13,10 +14,7 @@ Author: 1985 Thomas L. Quarles int -DIOacLoad(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; - +DIOacLoad(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; double gspr; @@ -31,8 +29,7 @@ DIOacLoad(inModel,ckt) for (here = model->DIOinstances; here != NULL ; here=here->DIOnextInstance) { if (here->DIOowner != ARCHme) continue; - - gspr=model->DIOconductance*here->DIOarea; + gspr=here->DIOtConductance*here->DIOarea*here->DIOm; geq= *(ckt->CKTstate0 + here->DIOconduct); xceq= *(ckt->CKTstate0 + here->DIOcapCurrent) * ckt->CKTomega; *(here->DIOposPosPtr ) += gspr; diff --git a/src/spicelib/devices/dio/dioask.c b/src/spicelib/devices/dio/dioask.c index d59ca1796..7d5a2a622 100644 --- a/src/spicelib/devices/dio/dioask.c +++ b/src/spicelib/devices/dio/dioask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ #include "ngspice.h" @@ -14,12 +15,8 @@ Author: 1985 Thomas L. Quarles /* ARGSUSED */ int -DIOask (ckt,inst,which,value,select) - CKTcircuit *ckt; - GENinstance *inst; - int which; - IFvalue *value; - IFvalue *select; +DIOask (CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, + IFvalue *select) { DIOinstance *here = (DIOinstance*)inst; double vr; @@ -39,9 +36,19 @@ DIOask (ckt,inst,which,value,select) case DIO_AREA: value->rValue = here->DIOarea; return(OK); + case DIO_PJ: + value->rValue = here->DIOpj; + return(OK); + case DIO_M: + value->rValue = here->DIOm; + return(OK); + case DIO_TEMP: value->rValue = here->DIOtemp-CONSTCtoK; return(OK); + case DIO_DTEMP: + value->rValue = here->DIOdtemp; + return(OK); case DIO_VOLTAGE: value->rValue = *(ckt->CKTstate0+here->DIOvoltage); return(OK); diff --git a/src/spicelib/devices/dio/dioconv.c b/src/spicelib/devices/dio/dioconv.c index c9dc3b77c..56ce106ff 100644 --- a/src/spicelib/devices/dio/dioconv.c +++ b/src/spicelib/devices/dio/dioconv.c @@ -13,9 +13,7 @@ Author: 1985 Thomas L. Quarles #include "suffix.h" int -DIOconvTest(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOconvTest(GENmodel *inModel, CKTcircuit *ckt) /* Check the devices for convergence */ { diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index 01c473f17..9cdda6830 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ #ifndef DIO #define DIO @@ -52,23 +53,43 @@ typedef struct sDIOinstance { unsigned DIOoff : 1; /* 'off' flag for diode */ unsigned DIOareaGiven : 1; /* flag to indicate area was specified */ + unsigned DIOpjGiven : 1; /* flag to indicate perimeter was specified */ + unsigned DIOmGiven : 1; /* flag to indicate multiplier was specified */ + unsigned DIOinitCondGiven : 1; /* flag to indicate ic was specified */ unsigned DIOsenPertFlag :1; /* indictes whether the the parameter of the particular instance is to be perturbed */ unsigned DIOtempGiven : 1; /* flag to indicate temperature was specified */ - + unsigned DIOdtempGiven : 1; /* flag to indicate dtemp given */ double DIOarea; /* area factor for the diode */ - double DIOinitCond; /* initial condition */ - double DIOtemp; /* temperature of the instance */ - double DIOtJctPot; /* temperature adjusted junction potential */ - double DIOtJctCap; /* temperature adjusted junction capacitance */ + double DIOpj; /* perimeter for the diode */ + double DIOm; /* multiplier for the diode */ + + double DIOinitCond; /* initial condition */ + double DIOtemp; /* temperature of the instance */ + double DIOdtemp; /* delta temperature of instance */ + double DIOtJctPot; /* temperature adjusted junction potential */ + double DIOtJctCap; /* temperature adjusted junction capacitance */ + double DIOtJctSWPot; /* temperature adjusted sidewall junction potential */ + double DIOtJctSWCap; /* temperature adjusted sidewall junction capacitance */ + double DIOtTransitTime; /* temperature adjusted transit time */ + double DIOtGradingCoeff; /* temperature adjusted grading coefficient (MJ) */ + double DIOtConductance; /* temperature adjusted series conductance */ + double DIOtDepCap; /* temperature adjusted transition point in */ /* the curve matching (Fc * Vj ) */ double DIOtSatCur; /* temperature adjusted saturation current */ + double DIOtSatSWCur; /* temperature adjusted side wall saturation current */ + double DIOtVcrit; /* temperature adjusted V crit */ double DIOtF1; /* temperature adjusted f1 */ double DIOtBrkdwnV; /* temperature adjusted breakdown voltage */ + + double DIOtF2; /* coeff. for capacitance equation precomputation */ + double DIOtF3; /* coeff. for capacitance equation precomputation */ + double DIOtF2SW; /* coeff. for capacitance equation precomputation */ + double DIOtF3SW; /* coeff. for capacitance equation precomputation */ /* * naming convention: @@ -139,15 +160,29 @@ typedef struct sDIOmodel { /* model structure for a diode */ IFuid DIOmodName; /* pointer to character string naming this model */ unsigned DIOsatCurGiven : 1; + unsigned DIOsatSWCurGiven : 1; + unsigned DIOresistGiven : 1; + unsigned DIOresistTemp1Given : 1; unsigned DIOemissionCoeffGiven : 1; unsigned DIOtransitTimeGiven : 1; + unsigned DIOtranTimeTemp1Given : 1; + unsigned DIOtranTimeTemp2Given : 1; unsigned DIOjunctionCapGiven : 1; unsigned DIOjunctionPotGiven : 1; unsigned DIOgradingCoeffGiven : 1; + unsigned DIOgradCoeffTemp1Given : 1; + unsigned DIOgradCoeffTemp2Given : 1; + unsigned DIOjunctionSWCapGiven : 1; + unsigned DIOjunctionSWPotGiven : 1; + unsigned DIOgradingSWCoeffGiven : 1; + unsigned DIOforwardKneeCurrentGiven : 1; + unsigned DIOreverseKneeCurrentGiven : 1; + unsigned DIOactivationEnergyGiven : 1; unsigned DIOsaturationCurrentExpGiven : 1; unsigned DIOdepletionCapCoeffGiven : 1; + unsigned DIOdepletionSWcapCoeffGiven :1; unsigned DIObreakdownVoltageGiven : 1; unsigned DIObreakdownCurrentGiven : 1; unsigned DIOnomTempGiven : 1; @@ -155,20 +190,33 @@ typedef struct sDIOmodel { /* model structure for a diode */ unsigned DIOfNexpGiven : 1; double DIOsatCur; /* saturation current */ - double DIOresist; /* ohmic series resistance */ - double DIOconductance; /* conductance corresponding to ohmic R */ - double DIOemissionCoeff; /* emission coefficient (N) */ - double DIOtransitTime; /* transit time (TT) */ - double DIOjunctionCap; /* Junction Capacitance (Cj0) */ - double DIOjunctionPot; /* Junction Potential (Vj) or (PB) */ - double DIOgradingCoeff; /* grading coefficient (m) */ + double DIOsatSWCur; /* Sidewall saturation current */ + + double DIOresist; /* ohmic series resistance */ + double DIOresistTemp1; /* series resistance 1st order temp. coeff. */ + double DIOconductance; /* conductance corresponding to ohmic R */ + double DIOemissionCoeff; /* emission coefficient (N) */ + double DIOtransitTime; /* transit time (TT) */ + double DIOtranTimeTemp1; /* transit time 1st order coefficient */ + double DIOtranTimeTemp2; /* transit time 2nd order coefficient */ + double DIOjunctionCap; /* Junction Capacitance (Cj0) */ + double DIOjunctionPot; /* Junction Potential (Vj) or (PB) */ + double DIOgradingCoeff; /* grading coefficient (m) or (mj) */ + double DIOgradCoeffTemp1; /* grading coefficient 1st order temp. coeff.*/ + double DIOgradCoeffTemp2; /* grading coefficient 2nd order temp. coeff.*/ + double DIOjunctionSWCap; /* Sidewall Junction Capacitance (Cjsw) */ + double DIOjunctionSWPot; /* Sidewall Junction Potential (Vjsw) or (PBSW) */ + double DIOgradingSWCoeff; /* Sidewall grading coefficient (mjsw) */ + double DIOforwardKneeCurrent; /* Forward Knee current */ + double DIOreverseKneeCurrent; /* Reverse Knee current */ + double DIOactivationEnergy; /* activation energy (EG) */ double DIOsaturationCurrentExp; /* Saturation current exponential (XTI) */ double DIOdepletionCapCoeff; /* Depletion Cap fraction coefficient (FC)*/ + double DIOdepletionSWcapCoeff; /* Depletion sw-Cap fraction coefficient (FCS)*/ double DIObreakdownVoltage; /* Voltage at reverse breakdown */ double DIObreakdownCurrent; /* Current at above voltage */ - double DIOf2; /* coefficient for capacitance equation precomputation */ - double DIOf3; /* coefficient for capacitance equation precomputation */ + double DIOnomTemp; /* nominal temperature (temp at which parms measured */ double DIOfNcoef; double DIOfNexp; @@ -195,6 +243,9 @@ typedef struct sDIOmodel { /* model structure for a diode */ #define DIO_QUEST_SENS_CPLX 16 #define DIO_QUEST_SENS_DC 17 #define DIO_CAP 18 +#define DIO_PJ 19 +#define DIO_M 20 +#define DIO_DTEMP 21 /* model parameters */ #define DIO_MOD_IS 101 @@ -214,6 +265,18 @@ typedef struct sDIOmodel { /* model structure for a diode */ #define DIO_MOD_TNOM 115 #define DIO_MOD_KF 116 #define DIO_MOD_AF 117 +#define DIO_MOD_JSW 118 +#define DIO_MOD_CJSW 119 +#define DIO_MOD_VJSW 120 +#define DIO_MOD_MJSW 121 +#define DIO_MOD_IKF 122 +#define DIO_MOD_IKR 123 +#define DIO_MOD_FCS 124 +#define DIO_MOD_TTT1 125 +#define DIO_MOD_TTT2 126 +#define DIO_MOD_TM1 127 +#define DIO_MOD_TM2 128 +#define DIO_MOD_TRS 129 #include "dioext.h" #endif /*DIO*/ diff --git a/src/spicelib/devices/dio/diodel.c b/src/spicelib/devices/dio/diodel.c index 14330f1b9..98e272e02 100644 --- a/src/spicelib/devices/dio/diodel.c +++ b/src/spicelib/devices/dio/diodel.c @@ -12,10 +12,7 @@ Author: 1985 Thomas L. Quarles int -DIOdelete(inModel,name,kill) - GENmodel *inModel; - IFuid name; - GENinstance **kill; +DIOdelete(GENmodel *inModel, IFuid name, GENinstance **kill) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance **fast = (DIOinstance**)kill; diff --git a/src/spicelib/devices/dio/diodest.c b/src/spicelib/devices/dio/diodest.c index 095716d50..527e930f6 100644 --- a/src/spicelib/devices/dio/diodest.c +++ b/src/spicelib/devices/dio/diodest.c @@ -11,8 +11,7 @@ Author: 1985 Thomas L. Quarles void -DIOdestroy(inModel) - GENmodel **inModel; +DIOdestroy(GENmodel **inModel) { DIOmodel **model = (DIOmodel**)inModel; DIOinstance *here; diff --git a/src/spicelib/devices/dio/diodisto.c b/src/spicelib/devices/dio/diodisto.c index 477b2ec98..56c5c4d54 100644 --- a/src/spicelib/devices/dio/diodisto.c +++ b/src/spicelib/devices/dio/diodisto.c @@ -11,11 +11,7 @@ Author: 1988 Jaijeet S Roychowdhury #include "suffix.h" int -DIOdisto(mode,genmodel,ckt) - GENmodel *genmodel; - CKTcircuit *ckt; - int mode; - +DIOdisto( int mode, GENmodel *genmodel, CKTcircuit *ckt) /* assuming here that ckt->CKTomega has been initialised to * the correct value */ diff --git a/src/spicelib/devices/dio/diodset.c b/src/spicelib/devices/dio/diodset.c index 5883a34a6..16cb6b6f8 100644 --- a/src/spicelib/devices/dio/diodset.c +++ b/src/spicelib/devices/dio/diodset.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Jaijeet S Roychowdhury +Modified by Dietmar Warning 2003 **********/ #include "ngspice.h" @@ -12,7 +13,7 @@ Author: 1988 Jaijeet S Roychowdhury /* actually load the current resistance value into the sparse matrix - * previously provided */ + * previously provided - for distortion analysis */ int DIOdSetup(DIOmodel *model, CKTcircuit *ckt) { @@ -31,6 +32,13 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt) double g2,g3; double cdiff2,cdiff3; double cjunc1,cjunc2,cjunc3; + double cd; + double sqrt_ikf; + double ikf_area_m; + double sqrt_ikr; + double ikr_area_m; + double czeroSW; + double cjunc1SW,cjunc2SW,cjunc3SW; /* loop through all the diode models */ for( ; model != NULL; model = model->DIOnextModel ) { @@ -44,10 +52,7 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt) * this routine loads diodes for dc and transient analyses. */ - - - - csat=here->DIOtSatCur*here->DIOarea; + csat=(here->DIOtSatCur*here->DIOarea+here->DIOtSatSWCur*here->DIOpj)*here->DIOm; vt = CONSTKoverQ * here->DIOtemp; vte=model->DIOemissionCoeff * vt; vd = *(ckt->CKTrhsOld + (here->DIOposPrimeNode)) - @@ -58,11 +63,17 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt) */ if (vd >= -5*vte) { evd = exp(vd/vte); + cd = csat*(evd-1)+ckt->CKTgmin*vd; gd = csat*evd/vte+ckt->CKTgmin; + if((model->DIOforwardKneeCurrentGiven) && (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) { + ikf_area_m = model->DIOforwardKneeCurrent*here->DIOarea*here->DIOm; + sqrt_ikf = sqrt(cd/ikf_area_m); + gd = ((1+sqrt_ikf)*gd - cd*gd/(2*sqrt_ikf*ikf_area_m))/(1+2*sqrt_ikf+cd/ikf_area_m)+ckt->CKTgmin; + } g2 = 0.5*(gd-ckt->CKTgmin)/vte; - cdiff2 = g2*model->DIOtransitTime; + cdiff2 = g2 * here->DIOtTransitTime; g3 = g2/3/vte; - cdiff3 = g3*model->DIOtransitTime; + cdiff3 = g3 * here->DIOtTransitTime; } else if((!(here->DIOtBrkdwnV))|| (vd >= -here->DIOtBrkdwnV)) { @@ -86,35 +97,54 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt) /* * junction charge storage elements */ - czero=here->DIOtJctCap*here->DIOarea; + czero=here->DIOtJctCap*here->DIOarea*here->DIOm; if (czero != 0.0) { - if (vd < here->DIOtDepCap){ - arg=1-vd/model->DIOjunctionPot; - sarg=exp(-model->DIOgradingCoeff*log(arg)); - /* the expression for depletion charge - model->DIOjunctionPot*czero* - (1-arg*sarg)/(1-model->DIOgradingCoeff); - */ - cjunc1 = czero*sarg; - cjunc2 = cjunc1/2/model->DIOjunctionPot*model->DIOgradingCoeff/arg; - cjunc3 = cjunc2/3/model->DIOjunctionPot/arg*(model->DIOgradingCoeff + 1); + if (vd < here->DIOtDepCap){ + arg=1-vd/model->DIOjunctionPot; + sarg=exp(-here->DIOtGradingCoeff*log(arg)); + /* the expression for depletion charge + model->DIOjunctionPot*czero* + (1-arg*sarg)/(1-here->DIOtGradingCoeff); + */ + cjunc1 = czero*sarg; + cjunc2 = cjunc1/2/model->DIOjunctionPot*here->DIOtGradingCoeff/arg; + cjunc3 = cjunc2/3/model->DIOjunctionPot/arg*(here->DIOtGradingCoeff + 1); + } + else { + czof2=czero/here->DIOtF2; + /* depletion charge equation + czero*here->DIOtF1+czof2* + (model->DIOtF3*(vd-here->DIOtDepCap)+ + (here->DIOtGradingCoeff/(model->DIOjunctionPot+ + model->DIOjunctionPot))*(vd*vd-here->DIOtDepCap* + here->DIOtDepCap)); + */ + cjunc2 = czof2/2/model->DIOjunctionPot*here->DIOtGradingCoeff; + cjunc3 =0.0; + } } - else { - czof2=czero/model->DIOf2; - /* depletion charge equation - czero*here->DIOtF1+czof2* - (model->DIOf3*(vd-here->DIOtDepCap)+ - (model->DIOgradingCoeff/(model->DIOjunctionPot+ - model->DIOjunctionPot))*(vd*vd-here->DIOtDepCap* - here->DIOtDepCap)); - */ - cjunc2 = czof2/2/model->DIOjunctionPot*model->DIOgradingCoeff; - cjunc3 =0.0; + else + { + cjunc1 = cjunc2 = cjunc3 = 0.0; } + czeroSW=+here->DIOtJctSWCap*here->DIOpj*here->DIOm; + if (czeroSW != 0.0) { + if (vd < here->DIOtDepCap){ + arg=1-vd/model->DIOjunctionSWPot; + sarg=exp(-model->DIOgradingSWCoeff*log(arg)); + cjunc1SW = czeroSW*sarg; + cjunc2SW = cjunc1SW/2/model->DIOjunctionSWPot*model->DIOgradingSWCoeff/arg; + cjunc3SW = cjunc2SW/3/model->DIOjunctionSWPot/arg*(model->DIOgradingSWCoeff + 1); + } + else { + czof2=czeroSW/here->DIOtF2SW; + cjunc2SW = czof2/2/model->DIOjunctionSWPot*model->DIOgradingSWCoeff; + cjunc3SW = 0.0; + } } else { - cjunc1 = cjunc2 = cjunc3 = 0.0; + cjunc1SW = cjunc2SW = cjunc3SW = 0.0; } /* @@ -125,8 +155,8 @@ DIOdSetup(DIOmodel *model, CKTcircuit *ckt) here->id_x3 = g3; here->cdif_x2 = cdiff2; here->cdif_x3 = cdiff3; - here->cjnc_x2 = cjunc2; - here->cjnc_x3 = cjunc3; + here->cjnc_x2 = cjunc2+cjunc2SW; + here->cjnc_x3 = cjunc3+cjunc3SW; } } return(OK); diff --git a/src/spicelib/devices/dio/dioext.h b/src/spicelib/devices/dio/dioext.h index 86109c14e..bb0a132d0 100644 --- a/src/spicelib/devices/dio/dioext.h +++ b/src/spicelib/devices/dio/dioext.h @@ -4,8 +4,6 @@ Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes **********/ -#ifdef __STDC__ - extern int DIOacLoad(GENmodel*,CKTcircuit*); extern int DIOask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); extern int DIOconvTest(GENmodel *,CKTcircuit*); @@ -29,34 +27,5 @@ extern int DIOtemp(GENmodel*,CKTcircuit*); extern int DIOtrunc(GENmodel*,CKTcircuit*,double*); extern int DIOdisto(int,GENmodel*,CKTcircuit*); extern int DIOnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); - extern int DIOdSetup(DIOmodel*,CKTcircuit*); - -#else /* stdc */ - -extern int DIOacLoad(); -extern int DIOask(); -extern int DIOconvTest(); -extern int DIOdelete(); -extern void DIOdestroy(); -extern int DIOgetic(); -extern int DIOload(); -extern int DIOmAsk(); -extern int DIOmDelete(); -extern int DIOmParam(); -extern int DIOparam(); -extern int DIOpzLoad(); -extern int DIOsAcLoad(); -extern int DIOsLoad(); -extern int DIOsSetup(); -extern void DIOsPrint(); -extern int DIOsUpdate(); -extern int DIOsetup(); -extern int DIOunsetup(); -extern int DIOtemp(); -extern int DIOtrunc(); -extern int DIOdisto(); -extern int DIOnoise(); -#endif /* stdc */ - diff --git a/src/spicelib/devices/dio/diogetic.c b/src/spicelib/devices/dio/diogetic.c index 70efe67a2..c89a945b0 100644 --- a/src/spicelib/devices/dio/diogetic.c +++ b/src/spicelib/devices/dio/diogetic.c @@ -13,9 +13,7 @@ Author: 1985 Thomas L. Quarles int -DIOgetic(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOgetic(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; diff --git a/src/spicelib/devices/dio/dioinit.c b/src/spicelib/devices/dio/dioinit.c index 48196b343..3750190b8 100644 --- a/src/spicelib/devices/dio/dioinit.c +++ b/src/spicelib/devices/dio/dioinit.c @@ -1,7 +1,7 @@ -#include +#include "config.h" -#include -#include +#include "devdefs.h" +#include "cktdefs.h" #include "diodefs.h" #include "dioitf.h" @@ -72,7 +72,7 @@ SPICEdev DIOinfo = { #ifdef CIDER DEVdump : NULL, DEVacct : NULL, -#endif +#endif DEVinstSize : &DIOiSize, DEVmodSize : &DIOmSize }; diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index 8f3483665..a5822137e 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes +Modified by Dietmar Warning 2003 **********/ #include "ngspice.h" @@ -14,9 +15,7 @@ Modified: 2000 AlansFixes #include "suffix.h" int -DIOload(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOload(GENmodel *inModel, CKTcircuit *ckt) /* actually load the current resistance value into the * sparse matrix previously provided */ @@ -32,6 +31,16 @@ DIOload(inModel,ckt) double csat; /* area-scaled saturation current */ double czero; double czof2; + double argSW; + double czeroSW; + double czof2SW; + double sargSW; + double cd_new; + double sqrt_ikr; + double sqrt_ikf; + double ikf_area_m; + double ikr_area_m; + double delvd; /* change in diode voltage temporary */ double evd; double evrev; @@ -71,9 +80,8 @@ DIOload(inModel,ckt) #endif /* SENSDEBUG */ } - - csat=here->DIOtSatCur*here->DIOarea; - gspr=model->DIOconductance*here->DIOarea; + csat=(here->DIOtSatCur*here->DIOarea+here->DIOtSatSWCur*here->DIOpj)*here->DIOm; + gspr=here->DIOtConductance*here->DIOarea*here->DIOm; vt = CONSTKoverQ * here->DIOtemp; vte=model->DIOemissionCoeff * vt; /* @@ -172,44 +180,86 @@ DIOload(inModel,ckt) /* * compute dc current and derivitives */ -next1: if (vd >= -3*vte) { - evd = exp(vd/vte); - cd = csat*(evd-1)+ckt->CKTgmin*vd; - gd = csat*evd/vte+ckt->CKTgmin; - } else if((!(model->DIObreakdownVoltageGiven)) || +next1: if (vd >= -3*vte) { /* forward */ + + evd = exp(vd/vte); + cd = csat*(evd-1); + gd = csat*evd/vte; + + if( (model->DIOforwardKneeCurrentGiven) && (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) { + ikf_area_m = model->DIOforwardKneeCurrent*here->DIOarea*here->DIOm; + sqrt_ikf = sqrt(cd/ikf_area_m); + cd_new = cd/(1+sqrt_ikf); + gd = ((1+sqrt_ikf)*gd - cd*gd/(2*sqrt_ikf*ikf_area_m))/(1+2*sqrt_ikf+cd/ikf_area_m); + cd = cd_new; + } + + cd = cd + ckt->CKTgmin*vd; + gd = gd + ckt->CKTgmin; + + } else if((!(model->DIObreakdownVoltageGiven)) || /* reverse*/ vd >= -here->DIOtBrkdwnV) { - arg=3*vte/(vd*CONSTe); + + arg=3*vte/(vd*CONSTe); arg = arg * arg * arg; - cd = -csat*(1+arg)+ckt->CKTgmin*vd; - gd = csat*3*arg/vd+ckt->CKTgmin; - } else { + cd = -csat*(1+arg); + gd = csat*3*arg/vd; + + if( (model->DIOreverseKneeCurrentGiven) && (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { + ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; + sqrt_ikr = sqrt(cd/(-ikr_area_m)); + cd_new = cd/(1+sqrt_ikr); + gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m); + cd = cd_new; + } + + cd = cd + ckt->CKTgmin*vd; + gd = gd + ckt->CKTgmin; + + + } else { /* breakdown */ evrev=exp(-(here->DIOtBrkdwnV+vd)/vte); - cd = -csat*evrev+ckt->CKTgmin*vd; - gd=csat*evrev/vte + ckt->CKTgmin; + cd = -csat*evrev; + gd = csat*evrev/vte; + + if( (model->DIOreverseKneeCurrentGiven) && (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { + ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; + sqrt_ikr = sqrt(cd/(-ikr_area_m)); + cd_new = cd/(1+sqrt_ikr); + gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m); + cd = cd_new; + } + + cd = cd + ckt->CKTgmin*vd; + gd = gd + ckt->CKTgmin; } if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) { /* * charge storage elements */ - czero=here->DIOtJctCap*here->DIOarea; + czero=here->DIOtJctCap*here->DIOarea*here->DIOm; + czeroSW=here->DIOtJctSWCap*here->DIOpj*here->DIOm; if (vd < here->DIOtDepCap){ arg=1-vd/here->DIOtJctPot; - sarg=exp(-model->DIOgradingCoeff*log(arg)); + argSW=1-vd/here->DIOtJctSWPot; + sarg=exp(-here->DIOtGradingCoeff*log(arg)); + sargSW=exp(-model->DIOgradingSWCoeff*log(argSW)); *(ckt->CKTstate0 + here->DIOcapCharge) = - model->DIOtransitTime*cd+here->DIOtJctPot* - czero* (1-arg*sarg)/(1-model->DIOgradingCoeff); - capd=model->DIOtransitTime*gd+czero*sarg; + here->DIOtTransitTime*cd+ + here->DIOtJctPot*czero*(1-arg*sarg)/(1-here->DIOtGradingCoeff)+ + here->DIOtJctSWPot*czeroSW*(1-argSW*sargSW)/(1-model->DIOgradingSWCoeff); + capd=here->DIOtTransitTime*gd+czero*sarg+czeroSW*sargSW; } else { - czof2=czero/model->DIOf2; + czof2=czero/here->DIOtF2; + czof2SW=czeroSW/here->DIOtF2SW; *(ckt->CKTstate0 + here->DIOcapCharge) = - model->DIOtransitTime*cd+czero*here->DIOtF1+czof2* - (model->DIOf3*(vd-here->DIOtDepCap)+ - (model->DIOgradingCoeff/(here->DIOtJctPot+ - here->DIOtJctPot))*(vd*vd-here->DIOtDepCap* - here->DIOtDepCap)); - capd=model->DIOtransitTime*gd+czof2*(model->DIOf3+ - model->DIOgradingCoeff*vd/here->DIOtJctPot); + here->DIOtTransitTime*cd+czero*here->DIOtF1+ + czof2*(here->DIOtF3*(vd-here->DIOtDepCap)+(here->DIOtGradingCoeff/(here->DIOtJctPot+here->DIOtJctPot))*(vd*vd-here->DIOtDepCap*here->DIOtDepCap))+ + czof2SW*(here->DIOtF3SW*(vd-here->DIOtDepCap)+(model->DIOgradingSWCoeff/(here->DIOtJctSWPot+here->DIOtJctSWPot))*(vd*vd-here->DIOtDepCap*here->DIOtDepCap)); + capd=here->DIOtTransitTime*gd+ + czof2*(here->DIOtF3+here->DIOtGradingCoeff*vd/here->DIOtJctPot)+ + czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vd/here->DIOtJctSWPot); } here->DIOcap = capd; diff --git a/src/spicelib/devices/dio/diomask.c b/src/spicelib/devices/dio/diomask.c index a8f5f1748..f76bb2439 100644 --- a/src/spicelib/devices/dio/diomask.c +++ b/src/spicelib/devices/dio/diomask.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ /* */ @@ -16,29 +17,38 @@ Author: 1985 Thomas L. Quarles /* ARGSUSED */ int -DIOmAsk (ckt,inModel,which, value) - CKTcircuit *ckt; - int which; - IFvalue *value; - GENmodel *inModel; +DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) { DIOmodel *model = (DIOmodel*)inModel; switch (which) { case DIO_MOD_IS: value->rValue = model->DIOsatCur; return(OK); + case DIO_MOD_JSW: + value->rValue = model->DIOsatSWCur; + return(OK); + case DIO_MOD_TNOM: value->rValue = model->DIOnomTemp-CONSTCtoK; return(OK); case DIO_MOD_RS: value->rValue = model->DIOresist; return(OK); + case DIO_MOD_TRS: + value->rValue = model->DIOresistTemp1; + return(OK); case DIO_MOD_N: value->rValue = model->DIOemissionCoeff; return(OK); case DIO_MOD_TT: value->rValue = model->DIOtransitTime; return(OK); + case DIO_MOD_TTT1: + value->rValue = model->DIOtranTimeTemp1; + return(OK); + case DIO_MOD_TTT2: + value->rValue = model->DIOtranTimeTemp2; + return(OK); case DIO_MOD_CJO: value->rValue = model->DIOjunctionCap; return(OK); @@ -48,6 +58,28 @@ DIOmAsk (ckt,inModel,which, value) case DIO_MOD_M: value->rValue = model->DIOgradingCoeff; return(OK); + case DIO_MOD_TM1: + value->rValue = model->DIOgradCoeffTemp1; + return(OK); + case DIO_MOD_TM2: + value->rValue = model->DIOgradCoeffTemp2; + return(OK); + case DIO_MOD_CJSW: + value->rValue = model->DIOjunctionSWCap; + return(OK); + case DIO_MOD_VJSW: + value->rValue = model->DIOjunctionSWPot; + return(OK); + case DIO_MOD_MJSW: + value->rValue = model->DIOgradingSWCoeff; + return(OK); + case DIO_MOD_IKF: + value->rValue = model->DIOforwardKneeCurrent; + return(OK); + case DIO_MOD_IKR: + value->rValue = model->DIOreverseKneeCurrent; + return(OK); + case DIO_MOD_EG: value->rValue = model->DIOactivationEnergy; return (OK); @@ -57,6 +89,9 @@ DIOmAsk (ckt,inModel,which, value) case DIO_MOD_FC: value->rValue = model->DIOdepletionCapCoeff; return(OK); + case DIO_MOD_FCS: + value->rValue = model->DIOdepletionSWcapCoeff; + return(OK); case DIO_MOD_KF: value->rValue = model->DIOfNcoef; return(OK); diff --git a/src/spicelib/devices/dio/diomdel.c b/src/spicelib/devices/dio/diomdel.c index 31eb18c26..cb77c1cd2 100644 --- a/src/spicelib/devices/dio/diomdel.c +++ b/src/spicelib/devices/dio/diomdel.c @@ -12,10 +12,7 @@ Author: 1985 Thomas L. Quarles int -DIOmDelete(inModel,modname,kill) - GENmodel **inModel; - IFuid modname; - GENmodel *kill; +DIOmDelete(GENmodel **inModel, IFuid modname, GENmodel *kill) { DIOmodel **model = (DIOmodel**)inModel; DIOmodel *modfast = (DIOmodel*)kill; diff --git a/src/spicelib/devices/dio/diompar.c b/src/spicelib/devices/dio/diompar.c index 4abd43314..0296dd09f 100644 --- a/src/spicelib/devices/dio/diompar.c +++ b/src/spicelib/devices/dio/diompar.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ /* */ @@ -14,10 +15,7 @@ Author: 1985 Thomas L. Quarles int -DIOmParam(param,value,inModel) - int param; - IFvalue *value; - GENmodel *inModel; +DIOmParam(int param, IFvalue *value, GENmodel *inModel) { DIOmodel *model = (DIOmodel*)inModel; switch(param) { @@ -25,6 +23,11 @@ DIOmParam(param,value,inModel) model->DIOsatCur = value->rValue; model->DIOsatCurGiven = TRUE; break; + case DIO_MOD_JSW: + model->DIOsatSWCur = value->rValue; + model->DIOsatSWCurGiven = TRUE; + break; + case DIO_MOD_TNOM: model->DIOnomTemp = value->rValue+CONSTCtoK; model->DIOnomTempGiven = TRUE; @@ -33,6 +36,10 @@ DIOmParam(param,value,inModel) model->DIOresist = value->rValue; model->DIOresistGiven = TRUE; break; + case DIO_MOD_TRS: + model->DIOresistTemp1 = value->rValue; + model->DIOresistTemp1Given = TRUE; + break; case DIO_MOD_N: model->DIOemissionCoeff = value->rValue; model->DIOemissionCoeffGiven = TRUE; @@ -41,6 +48,14 @@ DIOmParam(param,value,inModel) model->DIOtransitTime = value->rValue; model->DIOtransitTimeGiven = TRUE; break; + case DIO_MOD_TTT1: + model->DIOtranTimeTemp1 = value->rValue; + model->DIOtranTimeTemp1Given = TRUE; + break; + case DIO_MOD_TTT2: + model->DIOtranTimeTemp2 = value->rValue; + model->DIOtranTimeTemp2Given = TRUE; + break; case DIO_MOD_CJO: model->DIOjunctionCap = value->rValue; model->DIOjunctionCapGiven = TRUE; @@ -53,6 +68,35 @@ DIOmParam(param,value,inModel) model->DIOgradingCoeff = value->rValue; model->DIOgradingCoeffGiven = TRUE; break; + case DIO_MOD_TM1: + model->DIOgradCoeffTemp1 = value->rValue; + model->DIOgradCoeffTemp1Given = TRUE; + break; + case DIO_MOD_TM2: + model->DIOgradCoeffTemp2 = value->rValue; + model->DIOgradCoeffTemp2Given = TRUE; + break; + case DIO_MOD_CJSW: + model->DIOjunctionSWCap = value->rValue; + model->DIOjunctionSWCapGiven = TRUE; + break; + case DIO_MOD_VJSW: + model->DIOjunctionSWPot = value->rValue; + model->DIOjunctionSWPotGiven = TRUE; + break; + case DIO_MOD_MJSW: + model->DIOgradingSWCoeff = value->rValue; + model->DIOgradingSWCoeffGiven = TRUE; + break; + case DIO_MOD_IKF: + model->DIOforwardKneeCurrent = value->rValue; + model->DIOforwardKneeCurrentGiven = TRUE; + break; + case DIO_MOD_IKR: + model->DIOreverseKneeCurrent = value->rValue; + model->DIOreverseKneeCurrentGiven = TRUE; + break; + case DIO_MOD_EG: model->DIOactivationEnergy = value->rValue; model->DIOactivationEnergyGiven = TRUE; @@ -65,7 +109,11 @@ DIOmParam(param,value,inModel) model->DIOdepletionCapCoeff = value->rValue; model->DIOdepletionCapCoeffGiven = TRUE; break; - case DIO_MOD_BV: + case DIO_MOD_FCS: + model->DIOdepletionSWcapCoeff = value->rValue; + model->DIOdepletionSWcapCoeffGiven = TRUE; + break; + case DIO_MOD_BV: model->DIObreakdownVoltage = value->rValue; model->DIObreakdownVoltageGiven = TRUE; break; diff --git a/src/spicelib/devices/dio/dionoise.c b/src/spicelib/devices/dio/dionoise.c index 75bd8b79c..42c7c4dde 100644 --- a/src/spicelib/devices/dio/dionoise.c +++ b/src/spicelib/devices/dio/dionoise.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1987 Gary W. Ng +Modified by Dietmar Warning 2003 **********/ #include "ngspice.h" @@ -24,13 +25,8 @@ extern void NevalSrc(); extern double Nintegrate(); int -DIOnoise (mode, operation, genmodel, ckt, data, OnDens) - int mode; - int operation; - GENmodel *genmodel; - CKTcircuit *ckt; - Ndata *data; - double *OnDens; +DIOnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, + Ndata *data, double *OnDens) { DIOmodel *firstModel = (DIOmodel *) genmodel; DIOmodel *model; @@ -69,12 +65,10 @@ DIOnoise (mode, operation, genmodel, ckt, data, OnDens) for (i=0; i < DIONSRCS; i++) { (void)sprintf(name,"onoise_%s%s",inst->DIOname,DIOnNames[i]); - -data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); -if (!data->namelist) return(E_NOMEM); - (*(SPfrontEnd->IFnewUid))(ckt, - &(data->namelist[data->numPlots++]), - (IFuid)NULL,name,UID_OTHER,(void **)NULL); + data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); + if (!data->namelist) return(E_NOMEM); + (*(SPfrontEnd->IFnewUid))(ckt, &(data->namelist[data->numPlots++]), + (IFuid)NULL,name,UID_OTHER,(void **)NULL); /* we've added one more plot */ } @@ -84,26 +78,20 @@ if (!data->namelist) return(E_NOMEM); for (i=0; i < DIONSRCS; i++) { (void)sprintf(name,"onoise_total_%s%s",inst->DIOname,DIOnNames[i]); - -data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); -if (!data->namelist) return(E_NOMEM); - (*(SPfrontEnd->IFnewUid))(ckt, - &(data->namelist[data->numPlots++]), - (IFuid)NULL,name,UID_OTHER,(void **)NULL); + data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); + if (!data->namelist) return(E_NOMEM); + (*(SPfrontEnd->IFnewUid))(ckt, &(data->namelist[data->numPlots++]), + (IFuid)NULL,name,UID_OTHER,(void **)NULL); /* we've added one more plot */ - (void)sprintf(name,"inoise_total_%s%s",inst->DIOname,DIOnNames[i]); - -data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); -if (!data->namelist) return(E_NOMEM); - (*(SPfrontEnd->IFnewUid))(ckt, - &(data->namelist[data->numPlots++]), - (IFuid)NULL,name,UID_OTHER,(void **)NULL); + data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); + if (!data->namelist) return(E_NOMEM); + (*(SPfrontEnd->IFnewUid))(ckt, &(data->namelist[data->numPlots++]), + (IFuid)NULL,name,UID_OTHER,(void **)NULL); /* we've added one more plot */ - } break; } @@ -116,8 +104,7 @@ if (!data->namelist) return(E_NOMEM); case N_DENS: NevalSrc(&noizDens[DIORSNOIZ],&lnNdens[DIORSNOIZ], ckt,THERMNOISE,inst->DIOposPrimeNode,inst->DIOposNode, - model->DIOconductance * inst->DIOarea); - + inst->DIOtConductance * inst->DIOarea * inst->DIOm); NevalSrc(&noizDens[DIOIDNOIZ],&lnNdens[DIOIDNOIZ], ckt,SHOTNOISE,inst->DIOposPrimeNode, inst->DIOnegNode, *(ckt->CKTstate0 + inst->DIOcurrent)); @@ -127,8 +114,8 @@ if (!data->namelist) return(E_NOMEM); (double)0.0); noizDens[DIOFLNOIZ] *= model->DIOfNcoef * exp(model->DIOfNexp * - log(MAX(fabs(*(ckt->CKTstate0 + inst->DIOcurrent)),N_MINLOG))) / - data->freq; + log(MAX(fabs(*(ckt->CKTstate0 + inst->DIOcurrent)/inst->DIOm),N_MINLOG))) / + data->freq * inst->DIOm; lnNdens[DIOFLNOIZ] = log(MAX(noizDens[DIOFLNOIZ],N_MINLOG)); diff --git a/src/spicelib/devices/dio/dioparam.c b/src/spicelib/devices/dio/dioparam.c index 445d996c9..df438f389 100644 --- a/src/spicelib/devices/dio/dioparam.c +++ b/src/spicelib/devices/dio/dioparam.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ /* */ @@ -15,11 +16,7 @@ Author: 1985 Thomas L. Quarles /* ARGSUSED */ int -DIOparam(param,value,inst,select) - int param; - IFvalue *value; - GENinstance *inst; - IFvalue *select; +DIOparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) { DIOinstance *here = (DIOinstance*)inst; switch(param) { @@ -27,10 +24,23 @@ DIOparam(param,value,inst,select) here->DIOarea = value->rValue; here->DIOareaGiven = TRUE; break; + case DIO_PJ: + here->DIOpj = value->rValue; + here->DIOpjGiven = TRUE; + break; + case DIO_M: + here->DIOm = value->rValue; + here->DIOmGiven = TRUE; + break; + case DIO_TEMP: here->DIOtemp = value->rValue+CONSTCtoK; here->DIOtempGiven = TRUE; break; + case DIO_DTEMP: + here->DIOdtemp = value->rValue; + here->DIOdtempGiven = TRUE; + break; case DIO_OFF: here->DIOoff = value->iValue; break; diff --git a/src/spicelib/devices/dio/diopzld.c b/src/spicelib/devices/dio/diopzld.c index 5c7433842..313d75c2e 100644 --- a/src/spicelib/devices/dio/diopzld.c +++ b/src/spicelib/devices/dio/diopzld.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles +Modified by Dietmar Warning 2003 **********/ /* */ @@ -14,10 +15,7 @@ Author: 1985 Thomas L. Quarles int -DIOpzLoad(inModel,ckt,s) - GENmodel *inModel; - CKTcircuit *ckt; - SPcomplex *s; +DIOpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) { DIOmodel *model = (DIOmodel*)inModel; double gspr; @@ -32,8 +30,7 @@ DIOpzLoad(inModel,ckt,s) for (here = model->DIOinstances; here != NULL ; here=here->DIOnextInstance) { if (here->DIOowner != ARCHme) continue; - - gspr=model->DIOresist*here->DIOarea; + gspr=here->DIOtConductance*here->DIOarea*here->DIOm; geq= *(ckt->CKTstate0 + here->DIOconduct); xceq= *(ckt->CKTstate0 + here->DIOcapCurrent); *(here->DIOposPosPtr ) += gspr; diff --git a/src/spicelib/devices/dio/diosacl.c b/src/spicelib/devices/dio/diosacl.c index 086b106ee..cb25b5425 100644 --- a/src/spicelib/devices/dio/diosacl.c +++ b/src/spicelib/devices/dio/diosacl.c @@ -19,9 +19,7 @@ Author: 1985 Thomas L. Quarles int -DIOsAcLoad(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOsAcLoad(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; @@ -111,7 +109,7 @@ DIOsAcLoad(inModel,ckt) geq0 = *(here->DIOsenGeq); xceq0 = *(here->DIOsenCeq) * ckt->CKTomega; A0 = here->DIOarea; - gspr0=model->DIOconductance*A0; + gspr0=here->DIOtConductance*A0; cpos0 = gspr0 * vspr; icpos0 = gspr0 * ivspr; cposprm0 = geq0 * vd - xceq0 * ivd - cpos0; @@ -146,7 +144,7 @@ DIOsAcLoad(inModel,ckt) *(here->DIOsenCeq + 1)= *(ckt->CKTstate0 + here->DIOcapCurrent); here->DIOarea = A0; } - gspr=model->DIOconductance*Apert; + gspr=here->DIOtConductance*Apert; geq = *(here->DIOsenGeq + 1); xceq = *(here->DIOsenCeq + 1) * ckt->CKTomega; flag = 0; @@ -173,7 +171,7 @@ pertvd: /* Perturbation of Diode Voltage */ *(here->DIOsenCeq + 2)= *(ckt->CKTstate0 + here->DIOcapCurrent); *(ckt->CKTstate0 + here->DIOvoltage) = A0; } - gspr=model->DIOconductance*here->DIOarea; + gspr=here->DIOtConductance*here->DIOarea; geq = *(here->DIOsenGeq + 2); xceq = *(here->DIOsenCeq + 2) * ckt->CKTomega; diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index 737c4ef8a..e2d727c29 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes +Modified by Dietmar Warning 2003 **********/ /* load the diode structure with those pointers needed later @@ -16,11 +17,7 @@ Modified: 2000 AlansFixes #include "suffix.h" int -DIOsetup(matrix,inModel,ckt,states) - SMPmatrix *matrix; - GENmodel *inModel; - CKTcircuit *ckt; - int *states; +DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; @@ -36,6 +33,10 @@ DIOsetup(matrix,inModel,ckt,states) if(!model->DIOsatCurGiven) { model->DIOsatCur = 1e-14; } + if(!model->DIOsatSWCurGiven) { + model->DIOsatSWCur = 0.0; + } + if(!model->DIObreakdownCurrentGiven) { model->DIObreakdownCurrent = 1e-3; } @@ -45,15 +46,45 @@ DIOsetup(matrix,inModel,ckt,states) if(!model->DIOgradingCoeffGiven) { model->DIOgradingCoeff = .5; } + if(!model->DIOgradCoeffTemp1Given) { + model->DIOgradCoeffTemp1 = 0.0; + } + if(!model->DIOgradCoeffTemp2Given) { + model->DIOgradCoeffTemp2 = 0.0; + } if(!model->DIOdepletionCapCoeffGiven) { model->DIOdepletionCapCoeff = .5; } + if(!model->DIOdepletionSWcapCoeffGiven) { + model->DIOdepletionSWcapCoeff = .5; + } if(!model->DIOtransitTimeGiven) { model->DIOtransitTime = 0; } + if(!model->DIOtranTimeTemp1Given) { + model->DIOtranTimeTemp1 = 0.0; + } + if(!model->DIOtranTimeTemp2Given) { + model->DIOtranTimeTemp2 = 0.0; + } if(!model->DIOjunctionCapGiven) { model->DIOjunctionCap = 0; } + if(!model->DIOjunctionSWCapGiven) { + model->DIOjunctionSWCap = 0; + } + if(!model->DIOjunctionSWPotGiven){ + model->DIOjunctionSWPot = 1; + } + if(!model->DIOgradingSWCoeffGiven) { + model->DIOgradingSWCoeff = .33; + } + if(!model->DIOforwardKneeCurrentGiven) { + model->DIOforwardKneeCurrent = 1e-3; + } + if(!model->DIOreverseKneeCurrentGiven) { + model->DIOreverseKneeCurrent = 1e-3; + } if(!model->DIOactivationEnergyGiven) { model->DIOactivationEnergy = 1.11; } @@ -66,6 +97,9 @@ DIOsetup(matrix,inModel,ckt,states) if(!model->DIOfNexpGiven) { model->DIOfNexp = 1.0; } + if(!model->DIOresistTemp1Given) { + model->DIOresistTemp1 = 0.0; + } /* loop through all the instances of the model */ for (here = model->DIOinstances; here != NULL ; @@ -75,6 +109,12 @@ DIOsetup(matrix,inModel,ckt,states) if(!here->DIOareaGiven) { here->DIOarea = 1; } + if(!here->DIOpjGiven) { + here->DIOpj = 0; + } + if(!here->DIOmGiven) { + here->DIOm = 1; + } here->DIOstate = *states; *states += 5; diff --git a/src/spicelib/devices/dio/diosload.c b/src/spicelib/devices/dio/diosload.c index 20051addb..ce6d37c92 100644 --- a/src/spicelib/devices/dio/diosload.c +++ b/src/spicelib/devices/dio/diosload.c @@ -18,9 +18,7 @@ Author: 1985 Thomas L. Quarles int -DIOsLoad(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOsLoad(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; diff --git a/src/spicelib/devices/dio/diosprt.c b/src/spicelib/devices/dio/diosprt.c index 635701381..7ddfb1dd7 100644 --- a/src/spicelib/devices/dio/diosprt.c +++ b/src/spicelib/devices/dio/diosprt.c @@ -18,9 +18,7 @@ Author: 1985 Thomas L. Quarles void -DIOsPrint(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOsPrint(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; diff --git a/src/spicelib/devices/dio/diosset.c b/src/spicelib/devices/dio/diosset.c index 86098414f..5cebd88e3 100644 --- a/src/spicelib/devices/dio/diosset.c +++ b/src/spicelib/devices/dio/diosset.c @@ -18,9 +18,7 @@ Author: 1985 Thomas L. Quarles int -DIOsSetup(info,inModel) - SENstruct *info; - GENmodel *inModel; +DIOsSetup(SENstruct *info, GENmodel *inModel) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; diff --git a/src/spicelib/devices/dio/diosupd.c b/src/spicelib/devices/dio/diosupd.c index c1829564a..ea6d3acd3 100644 --- a/src/spicelib/devices/dio/diosupd.c +++ b/src/spicelib/devices/dio/diosupd.c @@ -16,9 +16,7 @@ Author: 1985 Thomas L. Quarles int -DIOsUpdate(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOsUpdate(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; diff --git a/src/spicelib/devices/dio/diotemp.c b/src/spicelib/devices/dio/diotemp.c index 7a6e70446..3934aa5f7 100644 --- a/src/spicelib/devices/dio/diotemp.c +++ b/src/spicelib/devices/dio/diotemp.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes +Modified by Dietmar Warning 2003 **********/ /* perform the temperature update to the diode */ @@ -14,12 +15,10 @@ Modified: 2000 AlansFixes #include "suffix.h" int -DIOtemp(inModel,ckt) - GENmodel *inModel; - CKTcircuit *ckt; +DIOtemp(GENmodel *inModel, CKTcircuit *ckt) { DIOmodel *model = (DIOmodel*)inModel; - double xfc; + double xfc, xfcs; double vte; double cbv; double xbv; @@ -27,6 +26,8 @@ DIOtemp(inModel,ckt) double tol; double vt; double vtnom; + double difference; + double factor; DIOinstance *here; int iter; char *emsg; @@ -58,22 +59,53 @@ DIOtemp(inModel,ckt) &(model->DIOmodName)); model->DIOdepletionCapCoeff=.95; } - if(!model->DIOresistGiven || model->DIOresist==0) { - model->DIOconductance = 0; + /* limit sidewall depletion cap coeff to max of .95 */ + if(model->DIOdepletionSWcapCoeff>.95) { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "%s: coefficient Fcs too large, limited to 0.95", + &(model->DIOmodName)); + model->DIOdepletionSWcapCoeff=.95; + } + if((!model->DIOresistGiven) || (model->DIOresist==0)) { + model->DIOconductance = 0.0; } else { model->DIOconductance = 1/model->DIOresist; } xfc=log(1-model->DIOdepletionCapCoeff); + xfcs=log(1-model->DIOdepletionSWcapCoeff); + for(here=model->DIOinstances;here;here=here->DIOnextInstance) { - double egfet1,arg1,fact1,pbfact1,pbo,gmaold; - double fact2,pbfact,arg,egfet,gmanew; + double egfet1,arg1,fact1,pbfact1,pbo,gmaold,pboSW,gmaSWold; + double fact2,pbfact,arg,egfet,gmanew,gmaSWnew; + if (here->DIOowner != ARCHme) continue; /* loop through all the instances */ - if(!here->DIOtempGiven) here->DIOtemp = ckt->CKTtemp; + + if(!here->DIOdtempGiven) here->DIOdtemp = 0.0; + + if(!here->DIOtempGiven) + here->DIOtemp = ckt->CKTtemp + here->DIOdtemp; + + /* Junction grading temperature adjust */ + difference = here->DIOtemp - model->DIOnomTemp; + factor = 1.0 + (model->DIOgradCoeffTemp1 * difference) + + (model->DIOgradCoeffTemp2 * difference * difference); + here->DIOtGradingCoeff = model->DIOgradingCoeff * factor; + + /* limit temperature adjusted grading coeff + * to max of .9 + */ + if(here->DIOtGradingCoeff>.9) { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "%s: temperature adjusted grading coefficient too large, limited to 0.9", + &(here->DIOname)); + here->DIOtGradingCoeff=.9; + } + vt = CONSTKoverQ * here->DIOtemp; /* this part gets really ugly - I won't even try to - * explain these equations */ + * explain these equations */ fact2 = here->DIOtemp/REFTEMP; egfet = 1.16-(7.02e-4*here->DIOtemp*here->DIOtemp)/ (here->DIOtemp+1108); @@ -86,26 +118,42 @@ DIOtemp(inModel,ckt) 1.1150877/(2*CONSTboltz*REFTEMP); fact1 = model->DIOnomTemp/REFTEMP; pbfact1 = -2 * vtnom*(1.5*log(fact1)+CHARGE*arg1); + pbo = (model->DIOjunctionPot-pbfact1)/fact1; gmaold = (model->DIOjunctionPot -pbo)/pbo; here->DIOtJctCap = model->DIOjunctionCap/ - (1+model->DIOgradingCoeff* + (1+here->DIOtGradingCoeff* (400e-6*(model->DIOnomTemp-REFTEMP)-gmaold) ); here->DIOtJctPot = pbfact+fact2*pbo; gmanew = (here->DIOtJctPot-pbo)/pbo; - here->DIOtJctCap *= 1+model->DIOgradingCoeff* + here->DIOtJctCap *= 1+here->DIOtGradingCoeff* (400e-6*(here->DIOtemp-REFTEMP)-gmanew); + pboSW = (model->DIOjunctionSWPot-pbfact1)/fact1; + gmaSWold = (model->DIOjunctionSWPot -pboSW)/pboSW; + here->DIOtJctSWCap = model->DIOjunctionSWCap/ + (1+model->DIOgradingSWCoeff* + (400e-6*(model->DIOnomTemp-REFTEMP)-gmaSWold) ); + here->DIOtJctSWPot = pbfact+fact2*pboSW; + gmaSWnew = (here->DIOtJctSWPot-pboSW)/pboSW; + here->DIOtJctSWCap *= 1+model->DIOgradingSWCoeff* + (400e-6*(here->DIOtemp-REFTEMP)-gmaSWnew); here->DIOtSatCur = model->DIOsatCur * exp( ((here->DIOtemp/model->DIOnomTemp)-1) * model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) + model->DIOsaturationCurrentExp/model->DIOemissionCoeff* log(here->DIOtemp/model->DIOnomTemp) ); + here->DIOtSatSWCur = model->DIOsatSWCur * exp( + ((here->DIOtemp/model->DIOnomTemp)-1) * + model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) + + model->DIOsaturationCurrentExp/model->DIOemissionCoeff* + log(here->DIOtemp/model->DIOnomTemp) ); + /* the defintion of f1, just recompute after temperature adjusting * all the variables used in it */ here->DIOtF1=here->DIOtJctPot* - (1-exp((1-model->DIOgradingCoeff)*xfc))/ - (1-model->DIOgradingCoeff); + (1-exp((1-here->DIOtGradingCoeff)*xfc))/ + (1-here->DIOtGradingCoeff); /* same for Depletion Capacitance */ here->DIOtDepCap=model->DIOdepletionCapCoeff* here->DIOtJctPot; @@ -118,35 +166,37 @@ DIOtemp(inModel,ckt) /* and now to copute the breakdown voltage, again, using * temperature adjusted basic parameters */ if (model->DIObreakdownVoltageGiven){ - cbv=model->DIObreakdownCurrent; - if (cbv < here->DIOtSatCur*model->DIObreakdownVoltage/vt){ - cbv=here->DIOtSatCur*model->DIObreakdownVoltage/vt; + cbv=model->DIObreakdownCurrent*here->DIOarea*here->DIOm; + if (cbv < here->DIOtSatCur*here->DIOarea*here->DIOm * + model->DIObreakdownVoltage/vt) { + cbv=here->DIOtSatCur*here->DIOarea*here->DIOm * + model->DIObreakdownVoltage/vt; emsg = MALLOC(100); if(emsg == (char *)NULL) return(E_NOMEM); (void)sprintf(emsg, - "%%s: breakdown current increased to %g to resolve", + "%%s: breakdown current increased to %g to resolve", cbv); (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&(here->DIOname)); FREE(emsg); (*(SPfrontEnd->IFerror))(ERR_WARNING, - "incompatibility with specified saturation current",(IFuid*)NULL); + "incompatibility with specified saturation current",(IFuid*)NULL); xbv=model->DIObreakdownVoltage; } else { tol=ckt->CKTreltol*cbv; xbv=model->DIObreakdownVoltage-vt*log(1+cbv/ - here->DIOtSatCur); + (here->DIOtSatCur*here->DIOarea*here->DIOm)); iter=0; for(iter=0 ; iter < 25 ; iter++) { xbv=model->DIObreakdownVoltage-vt*log(cbv/ - here->DIOtSatCur+1-xbv/vt); - xcbv=here->DIOtSatCur*(exp((model->DIObreakdownVoltage - -xbv)/vt)-1+xbv/vt); + (here->DIOtSatCur*here->DIOarea*here->DIOm)+1-xbv/vt); + xcbv=here->DIOtSatCur*here->DIOarea*here->DIOm * + (exp((model->DIObreakdownVoltage-xbv)/vt)-1+xbv/vt); if (fabs(xcbv-cbv) <= tol) goto matched; } emsg = MALLOC(100); if(emsg == (char *)NULL) return(E_NOMEM); (void)sprintf(emsg, -"%%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", + "%%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", xbv,xcbv); (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&here->DIOname); FREE(emsg); @@ -154,10 +204,30 @@ DIOtemp(inModel,ckt) matched: here->DIOtBrkdwnV = xbv; } - } - model->DIOf2=exp((1+model->DIOgradingCoeff)*xfc); - model->DIOf3=1-model->DIOdepletionCapCoeff* - (1+model->DIOgradingCoeff); - } + + /* transit time temperature adjust */ + difference = here->DIOtemp - model->DIOnomTemp; + factor = 1.0 + (model->DIOtranTimeTemp1 * difference) + + (model->DIOtranTimeTemp2 * difference * difference); + here->DIOtTransitTime = model->DIOtransitTime * factor; + + /* Series resistance temperature adjust */ + here->DIOtConductance = model->DIOconductance; + if(model->DIOresistGiven && model->DIOresist!=0.0) { + difference = here->DIOtemp - model->DIOnomTemp; + factor = 1.0 + (model->DIOresistTemp1)*difference; + here->DIOtConductance = model->DIOconductance / factor; + } + + here->DIOtF2=exp((1+here->DIOtGradingCoeff)*xfc); + here->DIOtF3=1-model->DIOdepletionCapCoeff* + (1+here->DIOtGradingCoeff); + here->DIOtF2SW=exp((1+model->DIOgradingSWCoeff)*xfcs); + here->DIOtF3SW=1-model->DIOdepletionSWcapCoeff* + (1+model->DIOgradingSWCoeff); + + } /* instance */ + + } /* model */ return(OK); } diff --git a/src/spicelib/devices/dio/diotrunc.c b/src/spicelib/devices/dio/diotrunc.c index 501d3d74f..68c7dc797 100644 --- a/src/spicelib/devices/dio/diotrunc.c +++ b/src/spicelib/devices/dio/diotrunc.c @@ -13,10 +13,7 @@ Author: 1985 Thomas L. Quarles int -DIOtrunc(inModel,ckt,timeStep) - GENmodel *inModel; - CKTcircuit *ckt; - double *timeStep; +DIOtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep) { DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here;