From dcc22ada6097ae3db5da6fe3b47fef9efb30e1b7 Mon Sep 17 00:00:00 2001 From: dwarning Date: Wed, 4 Jul 2012 08:14:33 +0200 Subject: [PATCH] new scalable diode model including tunnel component --- src/spicelib/devices/dio/dio.c | 40 ++++-- src/spicelib/devices/dio/dioacld.c | 4 +- src/spicelib/devices/dio/dioask.c | 10 +- src/spicelib/devices/dio/diodefs.h | 101 ++++++++++----- src/spicelib/devices/dio/dioload.c | 183 +++++++++++++++++++++------- src/spicelib/devices/dio/diomask.c | 32 ++++- src/spicelib/devices/dio/diompar.c | 50 +++++++- src/spicelib/devices/dio/dioparam.c | 12 +- src/spicelib/devices/dio/diopzld.c | 4 +- src/spicelib/devices/dio/diosetup.c | 61 +++++++++- src/spicelib/devices/dio/diotemp.c | 52 ++++---- 11 files changed, 427 insertions(+), 122 deletions(-) diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index f0df6666b..2ac0cf599 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ #include "ngspice/ngspice.h" @@ -10,13 +10,15 @@ Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 #include "ngspice/suffix.h" IFparm DIOpTable[] = { /* parameters */ - IOPU("off", DIO_OFF, IF_FLAG, "Initially off"), - IOPU("temp", DIO_TEMP, IF_REAL, "Instance temperature"), - 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"), + IOPU("off", DIO_OFF, IF_FLAG, "Initially off"), + IOPU("temp", DIO_TEMP, IF_REAL, "Instance temperature"), + 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("w", DIO_W, IF_REAL, "Diode width"), + IOPU("l", DIO_L, IF_REAL, "Diode length"), + 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"), @@ -37,6 +39,7 @@ IFparm DIOpTable[] = { /* parameters */ }; IFparm DIOmPTable[] = { /* model parameters */ + IOP( "level", DIO_MOD_LEVEL, IF_INTEGER, "Diode level selector"), 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"), @@ -48,6 +51,7 @@ IFparm DIOmPTable[] = { /* model parameters */ IOPR( "trs1", DIO_MOD_TRS, IF_REAL, "Ohmic resistance 1st order temp. coeff."), IOP( "trs2", DIO_MOD_TRS2, IF_REAL, "Ohmic resistance 2nd order temp. coeff."), IOP( "n", DIO_MOD_N, IF_REAL, "Emission Coefficient"), + IOP( "ns", DIO_MOD_NS, IF_REAL, "Sidewall 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."), @@ -63,10 +67,13 @@ IFparm DIOmPTable[] = { /* model parameters */ 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( "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( "nbv", DIO_MOD_NBV, IF_REAL, "Breakdown Emission Coefficient"), + IOP("area", DIO_MOD_AREA, IF_REAL, "Area factor"), + IOP( "pj", DIO_MOD_PJ, IF_REAL, "Perimeter factor"), IOP( "tlev", DIO_MOD_TLEV, IF_INTEGER, "Diode temperature equation selector"), IOP( "tlevc", DIO_MOD_TLEVC, IF_INTEGER, "Diode temperature equation selector"), @@ -76,16 +83,25 @@ IFparm DIOmPTable[] = { /* model parameters */ IOPR( "ctc", DIO_MOD_CTA, IF_REAL, "Area junction capacitance temperature coefficient"), IOP( "ctp", DIO_MOD_CTP, IF_REAL, "Perimeter junction capacitance temperature coefficient"), + IOP( "ctp", DIO_MOD_CTP, IF_REAL, "Perimeter junction capacitance temperature coefficient"), + IOP( "tpb", DIO_MOD_TPB, IF_REAL, "Area junction potential temperature coefficient"), IOPR( "tvj", DIO_MOD_TPB, IF_REAL, "Area junction potential temperature coefficient"), IOP( "tphp", DIO_MOD_TPHP, IF_REAL, "Perimeter junction potential temperature coefficient"), + IOP( "jtun", DIO_MOD_JTUN, IF_REAL, "Tunneling saturation current"), + IOP( "jtunsw", DIO_MOD_JTUNSW, IF_REAL, "Tunneling sidewall saturation current"), + IOP( "ntun", DIO_MOD_NTUN, IF_REAL, "Tunneling emission coefficient"), + IOP( "xtitun", DIO_MOD_XTITUN, IF_REAL, "Tunneling saturation current exponential"), + IOP( "keg", DIO_MOD_KEG, IF_REAL, "EG correction factor for tunneling"), + IOP( "kf", DIO_MOD_KF, IF_REAL, "flicker noise coefficient"), IOP( "af", DIO_MOD_AF, IF_REAL, "flicker noise exponent"), IOP( "fc", DIO_MOD_FC, IF_REAL, "Forward bias junction fit parameter"), IOP( "fcs", DIO_MOD_FCS, IF_REAL, "Forward bias sidewall junction fit parameter"), IOP( "bv", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage"), IOP( "ibv", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"), + IOPR( "ib", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"), IOP( "tcv", DIO_MOD_TCV, IF_REAL, "Reverse breakdown voltage temperature coefficient"), OPU( "cond", DIO_MOD_COND,IF_REAL, "Ohmic conductance"), IP( "d", DIO_MOD_D, IF_FLAG, "Diode model") diff --git a/src/spicelib/devices/dio/dioacld.c b/src/spicelib/devices/dio/dioacld.c index 2c0074029..87e954f03 100644 --- a/src/spicelib/devices/dio/dioacld.c +++ b/src/spicelib/devices/dio/dioacld.c @@ -28,8 +28,8 @@ DIOacLoad(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = model->DIOinstances; here != NULL ; here=here->DIOnextInstance) { - if (here->DIOowner != ARCHme) continue; - gspr=here->DIOtConductance*here->DIOarea*here->DIOm; + if (here->DIOowner != ARCHme) continue; + gspr=here->DIOtConductance*here->DIOarea; 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 23f09a2aa..1aeccab09 100644 --- a/src/spicelib/devices/dio/dioask.c +++ b/src/spicelib/devices/dio/dioask.c @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ #include "ngspice/ngspice.h" @@ -39,6 +39,12 @@ DIOask (CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, case DIO_PJ: value->rValue = here->DIOpj; return(OK); + case DIO_W: + value->rValue = here->DIOw; + return(OK); + case DIO_L: + value->rValue = here->DIOl; + return(OK); case DIO_M: value->rValue = here->DIOm; return(OK); @@ -46,7 +52,7 @@ DIOask (CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, case DIO_TEMP: value->rValue = here->DIOtemp-CONSTCtoK; return(OK); - case DIO_DTEMP: + case DIO_DTEMP: value->rValue = here->DIOdtemp; return(OK); case DIO_VOLTAGE: diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index 6b7d5fd98..b88b70f53 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ #ifndef DIO #define DIO @@ -54,6 +54,8 @@ 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 DIOwGiven : 1; /* flag to indicate width was specified */ + unsigned DIOlGiven : 1; /* flag to indicate length was specified */ unsigned DIOmGiven : 1; /* flag to indicate multiplier was specified */ unsigned DIOinitCondGiven : 1; /* flag to indicate ic was specified */ @@ -63,8 +65,10 @@ typedef struct sDIOinstance { unsigned DIOdtempGiven : 1; /* flag to indicate dtemp given */ double DIOarea; /* area factor for the diode */ - double DIOpj; /* perimeter for the diode */ - double DIOm; /* multiplier for the diode */ + double DIOpj; /* perimeter for the diode */ + double DIOw; /* width for the diode */ + double DIOl; /* length for the diode */ + double DIOm; /* multiplier for the diode */ double DIOinitCond; /* initial condition */ double DIOtemp; /* temperature of the instance */ @@ -81,6 +85,8 @@ typedef struct sDIOinstance { /* the curve matching (Fc * Vj ) */ double DIOtSatCur; /* temperature adjusted saturation current */ double DIOtSatSWCur; /* temperature adjusted side wall saturation current */ + double DIOtTunSatCur; /* tunneling saturation current */ + double DIOtTunSatSWCur; /* sidewall tunneling saturation current */ double DIOtVcrit; /* temperature adjusted V crit */ double DIOtF1; /* temperature adjusted f1 */ @@ -91,6 +97,11 @@ typedef struct sDIOinstance { double DIOtF2SW; /* coeff. for capacitance equation precomputation */ double DIOtF3SW; /* coeff. for capacitance equation precomputation */ + double DIOforwardKneeCurrent; /* Forward Knee current */ + double DIOreverseKneeCurrent; /* Reverse Knee current */ + double DIOjunctionCap; /* geometry adjusted junction capacitance */ + double DIOjunctionSWCap; /* geometry adjusted junction sidewall capacitance */ + /* * naming convention: * x = vdiode @@ -98,38 +109,38 @@ typedef struct sDIOinstance { /* the following are relevant to s.s. sinusoidal distortion analysis */ -#define DIONDCOEFFS 6 +#define DIONDCOEFFS 6 #ifndef NODISTO - double DIOdCoeffs[DIONDCOEFFS]; + double DIOdCoeffs[DIONDCOEFFS]; #else /* NODISTO */ - double *DIOdCoeffs; + double *DIOdCoeffs; #endif /* NODISTO */ #ifndef CONFIG -#define id_x2 DIOdCoeffs[0] -#define id_x3 DIOdCoeffs[1] -#define cdif_x2 DIOdCoeffs[2] -#define cdif_x3 DIOdCoeffs[3] -#define cjnc_x2 DIOdCoeffs[4] -#define cjnc_x3 DIOdCoeffs[5] +#define id_x2 DIOdCoeffs[0] +#define id_x3 DIOdCoeffs[1] +#define cdif_x2 DIOdCoeffs[2] +#define cdif_x3 DIOdCoeffs[3] +#define cjnc_x2 DIOdCoeffs[4] +#define cjnc_x3 DIOdCoeffs[5] #endif /* indices to array of diode noise sources */ -#define DIORSNOIZ 0 -#define DIOIDNOIZ 1 -#define DIOFLNOIZ 2 -#define DIOTOTNOIZ 3 +#define DIORSNOIZ 0 +#define DIOIDNOIZ 1 +#define DIOFLNOIZ 2 +#define DIOTOTNOIZ 3 #define DIONSRCS 4 #ifndef NONOISE double DIOnVar[NSTATVARS][DIONSRCS]; #else /* NONOISE */ - double **DIOnVar; + double **DIOnVar; #endif /* NONOISE */ } DIOinstance ; @@ -159,6 +170,7 @@ typedef struct sDIOmodel { /* model structure for a diode */ * that have this model */ IFuid DIOmodName; /* pointer to character string naming this model */ + unsigned DIOlevelGiven : 1; unsigned DIOsatCurGiven : 1; unsigned DIOsatSWCurGiven : 1; @@ -166,6 +178,8 @@ typedef struct sDIOmodel { /* model structure for a diode */ unsigned DIOresistTemp1Given : 1; unsigned DIOresistTemp2Given : 1; unsigned DIOemissionCoeffGiven : 1; + unsigned DIOswEmissionCoeffGiven : 1; + unsigned DIObrkdEmissionCoeffGiven : 1; unsigned DIOtransitTimeGiven : 1; unsigned DIOtranTimeTemp1Given : 1; unsigned DIOtranTimeTemp2Given : 1; @@ -196,7 +210,16 @@ typedef struct sDIOmodel { /* model structure for a diode */ unsigned DIOnomTempGiven : 1; unsigned DIOfNcoefGiven : 1; unsigned DIOfNexpGiven : 1; + unsigned DIOareaGiven : 1; + unsigned DIOpjGiven : 1; + + unsigned DIOtunSatCurGiven : 1; + unsigned DIOtunSatSWCurGiven : 1; + unsigned DIOtunEmissionCoeffGiven : 1; + unsigned DIOtunSaturationCurrentExpGiven : 1; + unsigned DIOtunEGcorrectionFactorGiven : 1; + int DIOlevel; /* level selector */ double DIOsatCur; /* saturation current */ double DIOsatSWCur; /* Sidewall saturation current */ @@ -205,6 +228,8 @@ typedef struct sDIOmodel { /* model structure for a diode */ double DIOresistTemp2; /* series resistance 2nd order temp. coeff. */ double DIOconductance; /* conductance corresponding to ohmic R */ double DIOemissionCoeff; /* emission coefficient (N) */ + double DIOswEmissionCoeff; /* Sidewall emission coefficient (NS) */ + double DIObrkdEmissionCoeff; /* Breakdown emission coefficient (NBV) */ double DIOtransitTime; /* transit time (TT) */ double DIOtranTimeTemp1; /* transit time 1st order coefficient */ double DIOtranTimeTemp2; /* transit time 2nd order coefficient */ @@ -216,8 +241,8 @@ typedef struct sDIOmodel { /* model structure for a diode */ 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 DIOforwardKneeCurrent; /* Forward Knee current (IKF) */ + double DIOreverseKneeCurrent; /* Reverse Knee current (IKR) */ int DIOtlev; /* Diode temperature equation selector */ int DIOtlevc; /* Diode temperature equation selector */ @@ -232,11 +257,19 @@ typedef struct sDIOmodel { /* model structure for a diode */ double DIObreakdownVoltage; /* Voltage at reverse breakdown */ double DIObreakdownCurrent; /* Current at above voltage */ double DIOtcv; /* Reverse breakdown voltage temperature coefficient */ + double DIOarea; /* area factor for the diode */ + double DIOpj; /* perimeter for the diode */ - double DIOnomTemp; /* nominal temperature (temp at which parms measured */ + double DIOnomTemp; /* nominal temperature at which parms measured */ double DIOfNcoef; double DIOfNexp; + double DIOtunSatCur; /* tunneling saturation current (JTUN) */ + double DIOtunSatSWCur; /* sidewall tunneling saturation current (JTUNSW) */ + double DIOtunEmissionCoeff; /* tunneling emission coefficient (NTUN) */ + double DIOtunSaturationCurrentExp; /* exponent for the tunneling current temperature (XTITUN) */ + double DIOtunEGcorrectionFactor; /* EG correction factor for tunneling (KEG) */ + } DIOmodel; /* device parameters */ @@ -251,18 +284,21 @@ typedef struct sDIOmodel { /* model structure for a diode */ #define DIO_AREA_SENS 9 #define DIO_POWER 10 #define DIO_TEMP 11 -#define DIO_QUEST_SENS_REAL 12 -#define DIO_QUEST_SENS_IMAG 13 -#define DIO_QUEST_SENS_MAG 14 -#define DIO_QUEST_SENS_PH 15 -#define DIO_QUEST_SENS_CPLX 16 -#define DIO_QUEST_SENS_DC 17 +#define DIO_QUEST_SENS_REAL 12 +#define DIO_QUEST_SENS_IMAG 13 +#define DIO_QUEST_SENS_MAG 14 +#define DIO_QUEST_SENS_PH 15 +#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 +#define DIO_W 20 +#define DIO_L 21 +#define DIO_M 22 +#define DIO_DTEMP 23 /* model parameters */ +#define DIO_MOD_LEVEL 100 #define DIO_MOD_IS 101 #define DIO_MOD_RS 102 #define DIO_MOD_N 103 @@ -300,6 +336,15 @@ typedef struct sDIOmodel { /* model structure for a diode */ #define DIO_MOD_TPB 135 #define DIO_MOD_TPHP 136 #define DIO_MOD_TCV 137 +#define DIO_MOD_NBV 138 +#define DIO_MOD_AREA 139 +#define DIO_MOD_PJ 140 +#define DIO_MOD_NS 141 +#define DIO_MOD_JTUN 142 +#define DIO_MOD_JTUNSW 143 +#define DIO_MOD_NTUN 144 +#define DIO_MOD_XTITUN 145 +#define DIO_MOD_KEG 146 #include "dioext.h" #endif /*DIO*/ diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index a8842f1fb..e9c87ebb0 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -2,7 +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 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ #include "ngspice/ngspice.h" @@ -23,12 +23,14 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) DIOmodel *model = (DIOmodel*)inModel; DIOinstance *here; double arg; + double argsw; double capd; - double cd; + double cd, cdsw=0.0; double cdeq; double cdhat; double ceq; double csat; /* area-scaled saturation current */ + double csatsw; /* perimeter-scaled saturation current */ double czero; double czof2; double argSW; @@ -42,8 +44,9 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) double delvd; /* change in diode voltage temporary */ double evd; + double evdsw; double evrev; - double gd; + double gd, gdsw=0.0; double geq; double gspr; /* area-scaled conductance */ double sarg; @@ -53,7 +56,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) double vd; /* current diode voltage */ double vdtemp; double vt; /* K t / Q */ - double vte; + double vte, vtesw, vtetun; + double vtebrk; int Check; int error; int SenCond=0; /* sensitivity condition */ @@ -81,10 +85,12 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) #endif /* SENSDEBUG */ } - csat=(here->DIOtSatCur*here->DIOarea+here->DIOtSatSWCur*here->DIOpj)*here->DIOm; - gspr=here->DIOtConductance*here->DIOarea*here->DIOm; + csat = here->DIOtSatCur; + csatsw = here->DIOtSatSWCur; + gspr = here->DIOtConductance * here->DIOarea; vt = CONSTKoverQ * here->DIOtemp; - vte=model->DIOemissionCoeff * vt; + vte = model->DIOemissionCoeff * vt; + vtebrk = model->DIObrkdEmissionCoeff * vt; /* * initialization */ @@ -167,11 +173,11 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) * limit new junction voltage */ if ( (model->DIObreakdownVoltageGiven) && - (vd < MIN(0,-here->DIOtBrkdwnV+10*vte))) { + (vd < MIN(0,-here->DIOtBrkdwnV+10*vtebrk))) { vdtemp = -(vd+here->DIOtBrkdwnV); vdtemp = DEVpnjlim(vdtemp, -(*(ckt->CKTstate0 + here->DIOvoltage) + - here->DIOtBrkdwnV),vte, + here->DIOtBrkdwnV),vtebrk, here->DIOtVcrit,&Check); vd = -(vdtemp+here->DIOtBrkdwnV); } else { @@ -182,61 +188,152 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) /* * compute dc current and derivitives */ -next1: if (vd >= -3*vte) { /* forward */ +next1: if (model->DIOsatSWCurGiven) { /* consider sidewall currents */ - evd = exp(vd/vte); - cd = csat*(evd-1) + ckt->CKTgmin*vd; - gd = csat*evd/vte + ckt->CKTgmin; + if (model->DIOswEmissionCoeffGiven) { /* sidewall currents with own characteristic */ + + vtesw = model->DIOswEmissionCoeff * vt; + + if (vd >= -3*vtesw) { /* sidewall 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; + } + + } else if((!(model->DIObreakdownVoltageGiven)) || /* sidewall reverse */ + vd >= -here->DIOtBrkdwnV) { + + 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; + } + + } else { /* sidewall 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; + } + + } + + } else { /* merge the current densities and use same characteristic as bottom diode */ + + csat = csat + csatsw; - if( (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) { - gd = gd-ckt->CKTgmin; - cd = cd-ckt->CKTgmin*vd; - 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; - cd = cd/(1+sqrt_ikf)+ckt->CKTgmin*vd; } - } else if((!(model->DIObreakdownVoltageGiven)) || /* reverse */ + } + + if (vd >= -3*vte) { /* bottom 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; + } + + } else if((!(model->DIObreakdownVoltageGiven)) || /* bottom reverse */ vd >= -here->DIOtBrkdwnV) { - arg = 3*vte/(vd*CONSTe); - arg = arg * arg * arg; - cd = -csat*(1+arg) + ckt->CKTgmin*vd ; - gd = csat*3*arg/vd + ckt->CKTgmin; + 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; + } - if( (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { - gd = gd-ckt->CKTgmin; - cd = cd-ckt->CKTgmin*vd; - ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; - sqrt_ikr = sqrt(cd/(-ikr_area_m)); - gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m)+ckt->CKTgmin; - cd = cd/(1+sqrt_ikr)+ckt->CKTgmin*vd; + } else { /* bottom 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; } - } else { /* breakdown */ + } + + if (model->DIOsatSWCurGiven) { + + if (model->DIOswEmissionCoeffGiven) { - evrev = exp(-(here->DIOtBrkdwnV+vd)/vte); - cd = -csat*evrev + ckt->CKTgmin*vd; - gd = csat*evrev/vte + ckt->CKTgmin; + cd = cdsw + cd; + gd = gdsw + gd; + + } + + } + + if (vd >= -3*vte) { /* limit forward */ + + if( (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) { + ikf_area_m = here->DIOforwardKneeCurrent; + 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*vd; + cd = cd/(1+sqrt_ikf) + ckt->CKTgmin; + } + + } else { /* limit reverse */ if( (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { - gd = gd-ckt->CKTgmin; - cd = cd-ckt->CKTgmin*vd; - ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; + ikr_area_m = here->DIOreverseKneeCurrent; sqrt_ikr = sqrt(cd/(-ikr_area_m)); - gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m)+ckt->CKTgmin; - cd = cd/(1+sqrt_ikr)+ckt->CKTgmin*vd; + gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m) + ckt->CKTgmin*vd; + cd = cd/(1+sqrt_ikr) + ckt->CKTgmin; } } + if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) { /* * charge storage elements */ - czero=here->DIOtJctCap*here->DIOarea*here->DIOm; - czeroSW=here->DIOtJctSWCap*here->DIOpj*here->DIOm; + czero=here->DIOtJctCap*here->DIOarea; + czeroSW=here->DIOtJctSWCap*here->DIOpj; if (vd < here->DIOtDepCap){ arg=1-vd/here->DIOtJctPot; argSW=1-vd/here->DIOtJctSWPot; diff --git a/src/spicelib/devices/dio/diomask.c b/src/spicelib/devices/dio/diomask.c index aa925c1d8..916b24a85 100644 --- a/src/spicelib/devices/dio/diomask.c +++ b/src/spicelib/devices/dio/diomask.c @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ /* */ @@ -24,6 +24,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) NG_IGNORE(ckt); switch (which) { + case DIO_MOD_LEVEL: + value->iValue = model->DIOlevel; + return (OK); case DIO_MOD_IS: value->rValue = model->DIOsatCur; return(OK); @@ -46,6 +49,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case DIO_MOD_N: value->rValue = model->DIOemissionCoeff; return(OK); + case DIO_MOD_NS: + value->rValue = model->DIOswEmissionCoeff; + return(OK); case DIO_MOD_TT: value->rValue = model->DIOtransitTime; return(OK); @@ -85,6 +91,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case DIO_MOD_IKR: value->rValue = model->DIOreverseKneeCurrent; return(OK); + case DIO_MOD_NBV: + value->rValue = model->DIObrkdEmissionCoeff; + return(OK); case DIO_MOD_TLEV: value->iValue = model->DIOtlev; @@ -131,9 +140,30 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case DIO_MOD_TCV: value->rValue = model->DIOtcv; return(OK); + case DIO_MOD_AREA: + value->rValue = model->DIOarea; + return(OK); + case DIO_MOD_PJ: + value->rValue = model->DIOpj; + return(OK); case DIO_MOD_COND: value->rValue = model->DIOconductance; return(OK); + case DIO_MOD_JTUN: + value->rValue = model->DIOtunSatCur; + return(OK); + case DIO_MOD_JTUNSW: + value->rValue = model->DIOtunSatSWCur; + return(OK); + case DIO_MOD_NTUN: + value->rValue = model->DIOtunEmissionCoeff; + return(OK); + case DIO_MOD_XTITUN: + value->rValue = model->DIOtunSaturationCurrentExp; + return(OK); + case DIO_MOD_KEG: + value->rValue = model->DIOtunEGcorrectionFactor; + return(OK); default: return(E_BADPARM); } diff --git a/src/spicelib/devices/dio/diompar.c b/src/spicelib/devices/dio/diompar.c index 57287f393..225815e0f 100644 --- a/src/spicelib/devices/dio/diompar.c +++ b/src/spicelib/devices/dio/diompar.c @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ /* */ @@ -19,6 +19,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) { DIOmodel *model = (DIOmodel*)inModel; switch(param) { + case DIO_MOD_LEVEL: + model->DIOlevel = value->iValue; + model->DIOlevelGiven = TRUE; + break; case DIO_MOD_IS: model->DIOsatCur = value->rValue; model->DIOsatCurGiven = TRUE; @@ -48,6 +52,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) model->DIOemissionCoeff = value->rValue; model->DIOemissionCoeffGiven = TRUE; break; + case DIO_MOD_NS: + model->DIOswEmissionCoeff = value->rValue; + model->DIOswEmissionCoeffGiven = TRUE; + break; case DIO_MOD_TT: model->DIOtransitTime = value->rValue; model->DIOtransitTimeGiven = TRUE; @@ -100,6 +108,18 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) model->DIOreverseKneeCurrent = value->rValue; model->DIOreverseKneeCurrentGiven = TRUE; break; + case DIO_MOD_NBV: + model->DIObrkdEmissionCoeff = value->rValue; + model->DIObrkdEmissionCoeffGiven = TRUE; + break; + case DIO_MOD_AREA: + model->DIOarea = value->rValue; + model->DIOareaGiven = TRUE; + break; + case DIO_MOD_PJ: + model->DIOpj = value->rValue; + model->DIOpjGiven = TRUE; + break; case DIO_MOD_TLEV: model->DIOtlev = value->iValue; @@ -153,10 +173,6 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) model->DIOtcv = value->rValue; model->DIOtcvGiven = TRUE; break; - case DIO_MOD_D: - /* no action - we already know we are a diode, but this */ - /* makes life easier for spice-2 like parsers */ - break; case DIO_MOD_KF: model->DIOfNcoef = value->rValue; model->DIOfNcoefGiven = TRUE; @@ -165,6 +181,30 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) model->DIOfNexp = value->rValue; model->DIOfNexpGiven = TRUE; break; + case DIO_MOD_JTUN: + model->DIOtunSatCur = value->rValue; + model->DIOtunSatCurGiven = TRUE; + break; + case DIO_MOD_JTUNSW: + model->DIOtunSatSWCur = value->rValue; + model->DIOtunSatSWCurGiven = TRUE; + break; + case DIO_MOD_NTUN: + model->DIOtunEmissionCoeff = value->rValue; + model->DIOtunEmissionCoeffGiven = TRUE; + break; + case DIO_MOD_XTITUN: + model->DIOtunSaturationCurrentExp = value->rValue; + model->DIOtunSaturationCurrentExpGiven = TRUE; + break; + case DIO_MOD_KEG: + model->DIOtunEGcorrectionFactor = value->rValue; + model->DIOtunEGcorrectionFactorGiven = TRUE; + break; + case DIO_MOD_D: + /* no action - we already know we are a diode, but this */ + /* makes life easier for spice-2 like parsers */ + break; default: return(E_BADPARM); } diff --git a/src/spicelib/devices/dio/dioparam.c b/src/spicelib/devices/dio/dioparam.c index c11ed122c..6847d284d 100644 --- a/src/spicelib/devices/dio/dioparam.c +++ b/src/spicelib/devices/dio/dioparam.c @@ -1,7 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles -Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ /* */ @@ -31,6 +31,14 @@ DIOparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) here->DIOpj = value->rValue; here->DIOpjGiven = TRUE; break; + case DIO_W: + here->DIOw = value->rValue; + here->DIOwGiven = TRUE; + break; + case DIO_L: + here->DIOl = value->rValue; + here->DIOlGiven = TRUE; + break; case DIO_M: here->DIOm = value->rValue; here->DIOmGiven = TRUE; @@ -40,7 +48,7 @@ DIOparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) here->DIOtemp = value->rValue+CONSTCtoK; here->DIOtempGiven = TRUE; break; - case DIO_DTEMP: + case DIO_DTEMP: here->DIOdtemp = value->rValue; here->DIOdtempGiven = TRUE; break; diff --git a/src/spicelib/devices/dio/diopzld.c b/src/spicelib/devices/dio/diopzld.c index d2bc0bf4c..5ac1313d6 100644 --- a/src/spicelib/devices/dio/diopzld.c +++ b/src/spicelib/devices/dio/diopzld.c @@ -29,8 +29,8 @@ DIOpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) /* loop through all the instances of the model */ for (here = model->DIOinstances; here != NULL ; here=here->DIOnextInstance) { - if (here->DIOowner != ARCHme) continue; - gspr=here->DIOtConductance*here->DIOarea*here->DIOm; + if (here->DIOowner != ARCHme) continue; + gspr=here->DIOtConductance*here->DIOarea; geq= *(ckt->CKTstate0 + here->DIOconduct); xceq= *(ckt->CKTstate0 + here->DIOcapCurrent); *(here->DIOposPosPtr ) += gspr; diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index 62d2a1444..d6d0de6d9 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -2,7 +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 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ /* load the diode structure with those pointers needed later @@ -27,6 +27,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) /* loop through all the diode models */ for( ; model != NULL; model = model->DIOnextModel ) { + if(!model->DIOlevelGiven) { + model->DIOlevel = 1; + } if(!model->DIOemissionCoeffGiven) { model->DIOemissionCoeff = 1; } @@ -36,6 +39,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->DIOsatSWCurGiven) { model->DIOsatSWCur = 0.0; } + if(!model->DIOswEmissionCoeffGiven) { + model->DIOswEmissionCoeff = 1; + } if(!model->DIObreakdownCurrentGiven) { model->DIObreakdownCurrent = 1e-3; } @@ -84,6 +90,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->DIOreverseKneeCurrentGiven) { model->DIOreverseKneeCurrent = 0.0; } + if(!model->DIObrkdEmissionCoeffGiven) { + model->DIObrkdEmissionCoeff = model->DIOemissionCoeff; + } if(!model->DIOtlevGiven) { model->DIOtlev = 0; } @@ -123,21 +132,65 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->DIOtcvGiven) { model->DIOtcv = 0.0; } + if(!model->DIOareaGiven) { + model->DIOarea = 1.0; + } + if(!model->DIOpjGiven) { + model->DIOpj = 0.0; + } + if(!model->DIOtunSatCurGiven) { + model->DIOtunSatCur = 0.0; + } + if(!model->DIOtunSatSWCurGiven) { + model->DIOtunSatSWCur = 0.0; + } + if(!model->DIOtunEmissionCoeffGiven) { + model->DIOtunEmissionCoeff = 30.0; + } + if(!model->DIOtunSaturationCurrentExpGiven) { + model->DIOtunSaturationCurrentExp = 3.0; + } + if(!model->DIOtunEGcorrectionFactorGiven) { + model->DIOtunEGcorrectionFactor = 1.0; + } + /* loop through all the instances of the model */ for (here = model->DIOinstances; here != NULL ; here=here->DIOnextInstance) { if (here->DIOowner != ARCHme) goto matrixpointers; if(!here->DIOareaGiven) { - here->DIOarea = 1; + if((!here->DIOwGiven) && (!here->DIOlGiven)) { + here->DIOarea = model->DIOarea; + } else { + here->DIOarea = 1; + } } if(!here->DIOpjGiven) { - here->DIOpj = 0; + if((!here->DIOwGiven) && (!here->DIOlGiven)) { + here->DIOpj = model->DIOpj; + } else { + here->DIOpj = 0; + } } if(!here->DIOmGiven) { here->DIOm = 1; } + here->DIOarea = here->DIOarea * here->DIOm; + if (model->DIOlevel == 1) { + here->DIOpj = here->DIOpj * here->DIOm; + } else { /* level=3 */ + if((here->DIOwGiven) && (here->DIOlGiven)) { + here->DIOarea = here->DIOw * here->DIOl * here->DIOm; + here->DIOpj = (2 * here->DIOw + 2 * here->DIOl) * here->DIOm; + } + } + here->DIOforwardKneeCurrent = model->DIOforwardKneeCurrent * here->DIOarea; + here->DIOreverseKneeCurrent = model->DIOreverseKneeCurrent * here->DIOarea; + here->DIOjunctionCap = model->DIOjunctionCap * here->DIOarea; + here->DIOjunctionSWCap = model->DIOjunctionSWCap * here->DIOpj; + here->DIOstate = *states; *states += 5; if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) ){ @@ -146,7 +199,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) matrixpointers: if(model->DIOresist == 0) { + here->DIOposPrimeNode = here->DIOposNode; + } else if(here->DIOposPrimeNode == 0) { CKTnode *tmpNode; diff --git a/src/spicelib/devices/dio/diotemp.c b/src/spicelib/devices/dio/diotemp.c index 5fc93efec..456f891cd 100644 --- a/src/spicelib/devices/dio/diotemp.c +++ b/src/spicelib/devices/dio/diotemp.c @@ -2,7 +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 and Paolo Nenzi 2003 +Modified by Paolo Nenzi 2003 and Dietmar Warning 2012 **********/ /* perform the temperature update to the diode */ @@ -124,7 +124,7 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt) if (model->DIOtlevc == 0) { pbo = (model->DIOjunctionPot-pbfact1)/fact1; gmaold = (model->DIOjunctionPot-pbo)/pbo; - here->DIOtJctCap = model->DIOjunctionCap / + here->DIOtJctCap = here->DIOjunctionCap / (1+here->DIOtGradingCoeff* (400e-6*(model->DIOnomTemp-REFTEMP)-gmaold) ); here->DIOtJctPot = pbfact+fact2*pbo; @@ -133,14 +133,14 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt) (400e-6*(here->DIOtemp-REFTEMP)-gmanew); } else if (model->DIOtlevc == 1) { here->DIOtJctPot = model->DIOjunctionPot - model->DIOtpb*(here->DIOtemp-REFTEMP); - here->DIOtJctCap = model->DIOjunctionCap * + here->DIOtJctCap = here->DIOjunctionCap * (model->DIOcta*(here->DIOtemp-REFTEMP)); } if (model->DIOtlevc == 0) { pboSW = (model->DIOjunctionSWPot-pbfact1)/fact1; gmaSWold = (model->DIOjunctionSWPot-pboSW)/pboSW; - here->DIOtJctSWCap = model->DIOjunctionSWCap / + here->DIOtJctSWCap = here->DIOjunctionSWCap / (1+model->DIOgradingSWCoeff* (400e-6*(model->DIOnomTemp-REFTEMP)-gmaSWold) ); here->DIOtJctSWPot = pbfact+fact2*pboSW; @@ -149,19 +149,30 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt) (400e-6*(here->DIOtemp-REFTEMP)-gmaSWnew); } else if (model->DIOtlevc == 1) { here->DIOtJctSWPot = model->DIOjunctionSWPot - model->DIOtphp*(here->DIOtemp-REFTEMP); - here->DIOtJctSWCap = model->DIOjunctionSWCap * + here->DIOtJctSWCap = here->DIOjunctionSWCap * (model->DIOctp*(here->DIOtemp-REFTEMP)); } - here->DIOtSatCur = model->DIOsatCur * exp( + here->DIOtSatCur = model->DIOsatCur * here->DIOarea * 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->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp( ((here->DIOtemp/model->DIOnomTemp)-1) * - model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) + - model->DIOsaturationCurrentExp/model->DIOemissionCoeff* + model->DIOactivationEnergy/(model->DIOswEmissionCoeff*vt) + + 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* + 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* log(here->DIOtemp/model->DIOnomTemp) ); /* the defintion of f1, just recompute after temperature adjusting @@ -175,17 +186,14 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt) /* and Vcrit */ vte=model->DIOemissionCoeff*vt; - here->DIOtVcrit=vte* - log(vte/(CONSTroot2*here->DIOtSatCur*here->DIOarea)); + here->DIOtVcrit = vte * log(vte/(CONSTroot2*here->DIOtSatCur)); /* and now to compute the breakdown voltage, again, using * temperature adjusted basic parameters */ if (model->DIObreakdownVoltageGiven){ - 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; + cbv=model->DIObreakdownCurrent * here->DIOarea; + if (cbv < here->DIOtSatCur * model->DIObreakdownVoltage/vt) { + cbv=here->DIOtSatCur * model->DIObreakdownVoltage/vt; #ifdef TRACE emsg = TMALLOC(char, 100); if(emsg == NULL) return(E_NOMEM); @@ -200,14 +208,14 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt) xbv=model->DIObreakdownVoltage; } else { tol=ckt->CKTreltol*cbv; - xbv=model->DIObreakdownVoltage-vt*log(1+cbv/ - (here->DIOtSatCur*here->DIOarea*here->DIOm)); + xbv=model->DIObreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(1+cbv/ + (here->DIOtSatCur)); iter=0; for(iter=0 ; iter < 25 ; iter++) { - xbv=model->DIObreakdownVoltage-vt*log(cbv/ - (here->DIOtSatCur*here->DIOarea*here->DIOm)+1-xbv/vt); - xcbv=here->DIOtSatCur*here->DIOarea*here->DIOm * - (exp((model->DIObreakdownVoltage-xbv)/vt)-1+xbv/vt); + xbv=model->DIObreakdownVoltage-model->DIObrkdEmissionCoeff*vt*log(cbv/ + (here->DIOtSatCur)+1-xbv/vt); + xcbv=here->DIOtSatCur * + (exp((model->DIObreakdownVoltage-xbv)/(model->DIObrkdEmissionCoeff*vt))-1+xbv/vt); if (fabs(xcbv-cbv) <= tol) goto matched; } #ifdef TRACE