diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index af82ce9b6..1943e4ff6 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -106,6 +106,8 @@ IFparm DIOmPTable[] = { /* model parameters */ IOP( "fv_max", DIO_MOD_FV_MAX, IF_REAL, "maximum voltage in forward direction"), IOP( "bv_max", DIO_MOD_BV_MAX, IF_REAL, "maximum voltage in reverse direction"), + IOP( "isr", DIO_MOD_ISR, IF_REAL, "Recombination saturation current"), + IOP( "nr", DIO_MOD_NR, IF_REAL, "Recombination current emission coefficient"), IP( "d", DIO_MOD_D, IF_FLAG, "Diode model") }; diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index fbc936b7b..77ac2f35f 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -115,6 +115,7 @@ typedef struct sDIOinstance { double DIOreverseKneeCurrent; /* Reverse Knee current */ double DIOjunctionCap; /* geometry adjusted junction capacitance */ double DIOjunctionSWCap; /* geometry adjusted junction sidewall capacitance */ + double DIOtRecSatCur; /* temperature adjusted recombination saturation current */ /* * naming convention: @@ -231,6 +232,8 @@ typedef struct sDIOmodel { /* model structure for a diode */ unsigned DIOtunEGcorrectionFactorGiven : 1; unsigned DIOfv_maxGiven : 1; unsigned DIObv_maxGiven : 1; + unsigned DIOrecSatCurGiven : 1; + unsigned DIOrecEmissionCoeffGiven : 1; int DIOlevel; /* level selector */ double DIOsatCur; /* saturation current */ @@ -284,6 +287,8 @@ typedef struct sDIOmodel { /* model structure for a diode */ double DIOtunEGcorrectionFactor; /* EG correction factor for tunneling (KEG) */ double DIOfv_max; /* maximum voltage in forward direction */ double DIObv_max; /* maximum voltage in reverse direction */ + double DIOrecSatCur; /* Recombination saturation current */ + double DIOrecEmissionCoeff; /* Recombination emission coefficient */ } DIOmodel; @@ -365,6 +370,8 @@ enum { DIO_MOD_KEG, DIO_MOD_FV_MAX, DIO_MOD_BV_MAX, + DIO_MOD_ISR, + DIO_MOD_NR, }; #include "dioext.h" diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index bc2bb94c9..e991cd302 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -45,7 +45,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) double delvd; /* change in diode voltage temporary */ double evd; double evrev; - double gd, gdb, gdsw; + double gd, gdb, gdsw, gen_fac, gen_fac_vd; + double evd_rec, cdb_rec, gdb_rec; double geq; double gspr; /* area-scaled conductance */ double sarg; @@ -234,6 +235,15 @@ next1: if (model->DIOsatSWCurGiven) { /* sidewall current */ evd = exp(vd/vte); cdb = csat*(evd-1); gdb = csat*evd/vte; + evd_rec = exp(vd/(model->DIOrecEmissionCoeff*vt)); /* recombination current */ + cdb_rec = here->DIOtRecSatCur*(evd_rec-1); + gdb_rec = here->DIOtRecSatCur*evd_rec/vt; + gen_fac = pow((pow((1-vd/here->DIOtJctPot), 2) + 0.005), here->DIOtGradingCoeff/2); + gen_fac_vd = here->DIOtGradingCoeff * (1-vd/here->DIOtJctPot) * pow((pow((1-vd/here->DIOtJctPot), 2) + 0.005), here->DIOtGradingCoeff/2-1); + cdb_rec = cdb_rec * gen_fac; + gdb_rec = gdb_rec * gen_fac + cdb_rec * gen_fac_vd; + cdb = cdb + cdb_rec; + gdb = gdb + gdb_rec; } else if((!(model->DIObreakdownVoltageGiven)) || vd >= -here->DIOtBrkdwnV) { /* reverse */ diff --git a/src/spicelib/devices/dio/diomask.c b/src/spicelib/devices/dio/diomask.c index 78e621bf6..38d1d8601 100644 --- a/src/spicelib/devices/dio/diomask.c +++ b/src/spicelib/devices/dio/diomask.c @@ -172,6 +172,12 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case DIO_MOD_BV_MAX: value->rValue = model->DIObv_max; return(OK); + case DIO_MOD_ISR: + value->rValue = model->DIOrecSatCur; + return(OK); + case DIO_MOD_NR: + value->rValue = model->DIOrecEmissionCoeff; + return(OK); default: return(E_BADPARM); } diff --git a/src/spicelib/devices/dio/diompar.c b/src/spicelib/devices/dio/diompar.c index f65236267..282423070 100644 --- a/src/spicelib/devices/dio/diompar.c +++ b/src/spicelib/devices/dio/diompar.c @@ -209,6 +209,14 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel) model->DIObv_max = value->rValue; model->DIObv_maxGiven = TRUE; break; + case DIO_MOD_ISR: + model->DIOrecSatCur = value->rValue; + model->DIOrecSatCurGiven = TRUE; + break; + case DIO_MOD_NR: + model->DIOrecEmissionCoeff = value->rValue; + model->DIOrecEmissionCoeffGiven = 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 */ diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index fa2c14127..d956c4e03 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -159,6 +159,12 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->DIObv_maxGiven) { model->DIObv_max = 1e99; } + if(!model->DIOrecEmissionCoeffGiven) { + model->DIOrecEmissionCoeff = 1; + } + if(!model->DIOrecSatCurGiven) { + model->DIOrecSatCur = 1e-14; + } /* loop through all the instances of the model */ for (here = DIOinstances(model); here != NULL ; diff --git a/src/spicelib/devices/dio/diotemp.c b/src/spicelib/devices/dio/diotemp.c index ef588e25d..10b6b370d 100644 --- a/src/spicelib/devices/dio/diotemp.c +++ b/src/spicelib/devices/dio/diotemp.c @@ -157,6 +157,12 @@ DIOtemp(GENmodel *inModel, CKTcircuit *ckt) model->DIOtunSaturationCurrentExp * log(here->DIOtemp/model->DIOnomTemp) ); + here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp( + ((here->DIOtemp/model->DIOnomTemp)-1) * + model->DIOactivationEnergy/(model->DIOrecEmissionCoeff*vt) + + model->DIOsaturationCurrentExp/model->DIOrecEmissionCoeff * + log(here->DIOtemp/model->DIOnomTemp) ); + /* the defintion of f1, just recompute after temperature adjusting * all the variables used in it */ here->DIOtF1=here->DIOtJctPot*