From c8fa54ce1cb964669a82401f13f023f3d34a925e Mon Sep 17 00:00:00 2001 From: dwarning Date: Wed, 9 Sep 2020 09:24:20 +0200 Subject: [PATCH] BJT Kull Quasi-Saturation model --- src/spicelib/devices/bjt/bjt.c | 8 ++ src/spicelib/devices/bjt/bjtacld.c | 31 ++++- src/spicelib/devices/bjt/bjtask.c | 3 + src/spicelib/devices/bjt/bjtconv.c | 11 +- src/spicelib/devices/bjt/bjtdefs.h | 105 ++++++++++++---- src/spicelib/devices/bjt/bjtload.c | 187 ++++++++++++++++++++++++++-- src/spicelib/devices/bjt/bjtmask.c | 24 ++++ src/spicelib/devices/bjt/bjtmpar.c | 32 +++++ src/spicelib/devices/bjt/bjtnoise.c | 2 +- src/spicelib/devices/bjt/bjtpzld.c | 34 ++++- src/spicelib/devices/bjt/bjtsetup.c | 81 +++++++++--- src/spicelib/devices/bjt/bjttemp.c | 16 +++ src/spicelib/devices/bjt/bjttrunc.c | 3 + 13 files changed, 477 insertions(+), 60 deletions(-) diff --git a/src/spicelib/devices/bjt/bjt.c b/src/spicelib/devices/bjt/bjt.c index 33374b14f..794b5ff75 100644 --- a/src/spicelib/devices/bjt/bjt.c +++ b/src/spicelib/devices/bjt/bjt.c @@ -154,6 +154,10 @@ IFparm BJTmPTable[] = { /* model parameters */ OPU("excessphasefactor",BJT_MOD_EXCESSPHASEFACTOR,IF_REAL, "Excess phase fact."), IOP("iss", BJT_MOD_ISS, IF_REAL, "Substrate Jct. Saturation Current"), IOP("ns", BJT_MOD_NS, IF_REAL, "Substrate current emission coefficient"), + IOP("rco", BJT_MOD_RCO, IF_REAL, "Intrinsic coll. resistance"), + IOP("vo", BJT_MOD_VO, IF_REAL, "Epi drift saturation voltage"), + IOP("gamma", BJT_MOD_GAMMA, IF_REAL, "Epi doping parameter"), + IOP("qco", BJT_MOD_QCO, IF_REAL, "Epi Charge parameter"), IOP("tlev", BJT_MOD_TLEV, IF_INTEGER, "Temperature equation selector"), IOP("tlevc", BJT_MOD_TLEVC, IF_INTEGER, "Temperature equation selector"), IOP("tbf1", BJT_MOD_TBF1, IF_REAL, "BF 1. temperature coefficient"), @@ -216,6 +220,10 @@ IFparm BJTmPTable[] = { /* model parameters */ IOP("tise2", BJT_MOD_TISE2, IF_REAL, "ISE 2. temperature coefficient"), IOP("tisc1", BJT_MOD_TISC1, IF_REAL, "ISC 1. temperature coefficient"), IOP("tisc2", BJT_MOD_TISC2, IF_REAL, "ISC 2. temperature coefficient"), + IOP("quasimod", BJT_MOD_QUASIMOD, IF_INTEGER, "Temperature equation selector"), + IOP("vg", BJT_MOD_EGQS, IF_REAL, "Energy gap for QS temp. dependency"), + IOP("cn", BJT_MOD_XRCI, IF_REAL, "Temperature exponent of RCI"), + IOP("d", BJT_MOD_XD, IF_REAL, "Temperature exponent of VO"), IOP("vbe_max", BJT_MOD_VBE_MAX, IF_REAL, "maximum voltage B-E junction"), IOP("vbc_max", BJT_MOD_VBC_MAX, IF_REAL, "maximum voltage B-C junction"), IOP("vce_max", BJT_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch") diff --git a/src/spicelib/devices/bjt/bjtacld.c b/src/spicelib/devices/bjt/bjtacld.c index fcdfa7cb3..901ad5f57 100644 --- a/src/spicelib/devices/bjt/bjtacld.c +++ b/src/spicelib/devices/bjt/bjtacld.c @@ -36,6 +36,7 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt) double xcsub; double xcmcb; double m; + double Irci_Vrci, Irci_Vbci, Irci_Vbcx, xcbcx; for( ; model != NULL; model = BJTnextModel(model)) { for( here = BJTinstances(model); here!= NULL; @@ -49,6 +50,9 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt) gmu= *(ckt->CKTstate0 + here->BJTgmu); gm= *(ckt->CKTstate0 + here->BJTgm); go= *(ckt->CKTstate0 + here->BJTgo); + Irci_Vrci = *(ckt->CKTstate0 + here->BJTirci_Vrci); + Irci_Vbci = *(ckt->CKTstate0 + here->BJTirci_Vbci); + Irci_Vbcx = *(ckt->CKTstate0 + here->BJTirci_Vbcx); xgm=0; td=model->BJTexcessPhaseFactor; if(td != 0) { @@ -63,21 +67,24 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt) xcbx= *(ckt->CKTstate0 + here->BJTcqbx) * ckt->CKTomega; xcsub= *(ckt->CKTstate0 + here->BJTcqsub) * ckt->CKTomega; xcmcb= *(ckt->CKTstate0 + here->BJTcexbc) * ckt->CKTomega; + xcbcx= *(ckt->CKTstate0 + here->BJTcqbcx) * ckt->CKTomega; + *(here->BJTcolColPtr) += m * (gcpr); *(here->BJTbaseBasePtr) += m * (gx); *(here->BJTbaseBasePtr + 1) += m * (xcbx); *(here->BJTemitEmitPtr) += m * (gepr); - *(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+gcpr); + *(here->BJTcolPrimeColPrimePtr) += m * (gmu+go); + *(here->BJTcollCXcollCXPtr) += m * (gcpr); *(here->BJTcolPrimeColPrimePtr + 1) += m * (xcmu+xcbx); *(here->BJTsubstConSubstConPtr + 1) += m * (xcsub); *(here->BJTbasePrimeBasePrimePtr) += m * (gx+gpi+gmu); *(here->BJTbasePrimeBasePrimePtr + 1) += m * (xcpi+xcmu+xcmcb); *(here->BJTemitPrimeEmitPrimePtr) += m * (gpi+gepr+gm+go); *(here->BJTemitPrimeEmitPrimePtr + 1) += m * (xcpi+xgm); - *(here->BJTcolColPrimePtr) += m * (-gcpr); + *(here->BJTcollCollCXPtr) += m * (-gcpr); *(here->BJTbaseBasePrimePtr) += m * (-gx); *(here->BJTemitEmitPrimePtr) += m * (-gepr); - *(here->BJTcolPrimeColPtr) += m * (-gcpr); + *(here->BJTcollCXCollPtr) += m * (-gcpr); *(here->BJTcolPrimeBasePrimePtr) += m * (-gmu+gm); *(here->BJTcolPrimeBasePrimePtr + 1) += m * (-xcmu+xgm); *(here->BJTcolPrimeEmitPrimePtr) += m * (-gm-go); @@ -97,6 +104,24 @@ BJTacLoad(GENmodel *inModel, CKTcircuit *ckt) *(here->BJTsubstSubstConPtr + 1) += m * (-xcsub); *(here->BJTbaseColPrimePtr + 1) += m * (-xcbx); *(here->BJTcolPrimeBasePtr + 1) += m * (-xcbx); + if (model->BJTintCollResistGiven) { + *(here->BJTcollCXcollCXPtr) += m * Irci_Vrci; + *(here->BJTcollCXColPrimePtr) += m * -Irci_Vrci; + *(here->BJTcollCXBasePrimePtr) += m * Irci_Vbci; + *(here->BJTcollCXColPrimePtr) += m * -Irci_Vbci; + *(here->BJTcollCXBasePrimePtr) += m * Irci_Vbcx; + *(here->BJTcollCXcollCXPtr) += m * -Irci_Vbcx; + *(here->BJTcolPrimeCollCXPtr) += m * -Irci_Vrci; + *(here->BJTcolPrimeColPrimePtr) += m * Irci_Vrci; + *(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbci; + *(here->BJTcolPrimeColPrimePtr) += m * Irci_Vbci; + *(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbcx; + *(here->BJTcolPrimeCollCXPtr) += m * Irci_Vbcx; + *(here->BJTbasePrimeBasePrimePtr + 1) += m * xcbcx; + *(here->BJTcollCXcollCXPtr + 1) += m * xcbcx; + *(here->BJTbasePrimeCollCXPtr + 1) += m * -xcbcx; + *(here->BJTcollCXBasePrimePtr + 1) += m * -xcbcx; + } } } return(OK); diff --git a/src/spicelib/devices/bjt/bjtask.c b/src/spicelib/devices/bjt/bjtask.c index f40676907..5b1ae876f 100644 --- a/src/spicelib/devices/bjt/bjtask.c +++ b/src/spicelib/devices/bjt/bjtask.c @@ -78,6 +78,9 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue case BJT_QUEST_COLPRIMENODE: value->iValue = here->BJTcolPrimeNode; return(OK); + case BJT_QUEST_COLLCXNODE: + value->iValue = here->BJTcollCXNode; + return(OK); case BJT_QUEST_BASEPRIMENODE: value->iValue = here->BJTbasePrimeNode; return(OK); diff --git a/src/spicelib/devices/bjt/bjtconv.c b/src/spicelib/devices/bjt/bjtconv.c index 515499e81..c30a47cc8 100644 --- a/src/spicelib/devices/bjt/bjtconv.c +++ b/src/spicelib/devices/bjt/bjtconv.c @@ -27,9 +27,10 @@ BJTconvTest(GENmodel *inModel, CKTcircuit *ckt) double cbhat; double vbe; double vbc; + double vbcx; double delvbe; double delvbc; - + double delvbcx; for( ; model != NULL; model = BJTnextModel(model)) { @@ -41,8 +42,12 @@ BJTconvTest(GENmodel *inModel, CKTcircuit *ckt) vbc=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbasePrimeNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + vbcx=model->BJTtype*( + *(ckt->CKTrhsOld+here->BJTbasePrimeNode)- + *(ckt->CKTrhsOld+here->BJTcollCXNode)); delvbe=vbe- *(ckt->CKTstate0 + here->BJTvbe); delvbc=vbc- *(ckt->CKTstate0 + here->BJTvbc); + delvbcx=vbcx- *(ckt->CKTstate0 + here->BJTvbcx); cchat= *(ckt->CKTstate0 + here->BJTcc)+(*(ckt->CKTstate0 + here->BJTgm)+ *(ckt->CKTstate0 + here->BJTgo))*delvbe- (*(ckt->CKTstate0 + here->BJTgo)+*(ckt->CKTstate0 + @@ -58,14 +63,14 @@ BJTconvTest(GENmodel *inModel, CKTcircuit *ckt) tol=ckt->CKTreltol*MAX(fabs(cchat),fabs(cc))+ckt->CKTabstol; if (fabs(cchat-cc) > tol) { ckt->CKTnoncon++; - ckt->CKTtroubleElt = (GENinstance *) here; + ckt->CKTtroubleElt = (GENinstance *) here; return(OK); /* no reason to continue - we've failed... */ } else { tol=ckt->CKTreltol*MAX(fabs(cbhat),fabs(cb))+ ckt->CKTabstol; if (fabs(cbhat-cb) > tol) { ckt->CKTnoncon++; - ckt->CKTtroubleElt = (GENinstance *) here; + ckt->CKTtroubleElt = (GENinstance *) here; return(OK); /* no reason to continue - we've failed... */ } } diff --git a/src/spicelib/devices/bjt/bjtdefs.h b/src/spicelib/devices/bjt/bjtdefs.h index 4d1870763..625db4772 100644 --- a/src/spicelib/devices/bjt/bjtdefs.h +++ b/src/spicelib/devices/bjt/bjtdefs.h @@ -43,6 +43,7 @@ typedef struct sBJTinstance { const int BJTbaseNode; /* number of base node of bjt */ const int BJTemitNode; /* number of emitter node of bjt */ const int BJTsubstNode; /* number of substrate node of bjt */ + int BJTcollCXNode; /* number of internal collector node of bjt */ int BJTcolPrimeNode; /* number of internal collector node of bjt */ int BJTbasePrimeNode; /* number of internal base node of bjt */ int BJTemitPrimeNode; /* number of internal emitter node of bjt */ @@ -100,15 +101,18 @@ typedef struct sBJTinstance { double BJTtjunctionExpBC; /* temperature adjusted MJC */ double BJTtjunctionExpSub; /* temperature adjusted MJS */ double BJTtemissionCoeffS; /* temperature adjusted NS */ + double BJTtintCollResist; /* temperature adjusted QS RO */ + double BJTtepiSatVoltage; /* temperature adjusted QS VO */ + double BJTtepiDoping; /* temperature adjusted QS GAMMA */ - double *BJTcolColPrimePtr; /* pointer to sparse matrix at - * (collector,collector prime) */ + double *BJTcollCollCXPtr; /* pointer to sparse matrix at + * (collector,collector cx) */ double *BJTbaseBasePrimePtr; /* pointer to sparse matrix at * (base,base prime) */ double *BJTemitEmitPrimePtr; /* pointer to sparse matrix at * (emitter,emitter prime) */ - double *BJTcolPrimeColPtr; /* pointer to sparse matrix at - * (collector prime,collector) */ + double *BJTcollCXCollPtr; /* pointer to sparse matrix at + * (collector cx,collector) */ double *BJTcolPrimeBasePrimePtr; /* pointer to sparse matrix at * (collector prime,base prime) */ double *BJTcolPrimeEmitPrimePtr; /* pointer to sparse matrix at @@ -153,6 +157,17 @@ typedef struct sBJTinstance { double *BJTcolPrimeBasePtr; /* pointer to sparse matrix at * (collector prime,base) */ + double *BJTcollCXcollCXPtr; /* pointer to sparse matrix at + * (collector cx,collector cx) */ + double *BJTcollCXBasePrimePtr; /* pointer to sparse matrix at + * (collector cx,base prime) */ + double *BJTbasePrimeCollCXPtr; /* pointer to sparse matrix at + * (base prime,collector cx) */ + double *BJTcolPrimeCollCXPtr; /* pointer to sparse matrix at + * (collector prime,collector cx) */ + double *BJTcollCXColPrimePtr; /* pointer to sparse matrix at + * (collector cx,base prime) */ + unsigned BJToff :1; /* 'off' flag for bjt */ unsigned BJTtempGiven :1; /* temperature given for bjt instance*/ unsigned BJTdtempGiven :1; /* delta temperature given for bjt instance*/ @@ -171,6 +186,7 @@ typedef struct sBJTinstance { double BJTcapbc; double BJTcapsub; double BJTcapbx; + double BJTcapbcx; double *BJTsens; #define BJTsenGpi BJTsens /* stores the perturbed values of gpi */ @@ -297,29 +313,39 @@ typedef struct sBJTinstance { /* entries in the state vector for bjt: */ #define BJTvbe BJTstate #define BJTvbc BJTstate+1 -#define BJTcc BJTstate+2 -#define BJTcb BJTstate+3 -#define BJTgpi BJTstate+4 -#define BJTgmu BJTstate+5 -#define BJTgm BJTstate+6 -#define BJTgo BJTstate+7 -#define BJTqbe BJTstate+8 -#define BJTcqbe BJTstate+9 -#define BJTqbc BJTstate+10 -#define BJTcqbc BJTstate+11 -#define BJTqsub BJTstate+12 -#define BJTcqsub BJTstate+13 -#define BJTqbx BJTstate+14 -#define BJTcqbx BJTstate+15 -#define BJTgx BJTstate+16 -#define BJTcexbc BJTstate+17 -#define BJTgeqcb BJTstate+18 -#define BJTgcsub BJTstate+19 -#define BJTgeqbx BJTstate+20 -#define BJTvsub BJTstate+21 -#define BJTcdsub BJTstate+22 -#define BJTgdsub BJTstate+23 -#define BJTnumStates 24 +#define BJTvbcx BJTstate+2 +#define BJTvrci BJTstate+3 +#define BJTcc BJTstate+4 +#define BJTcb BJTstate+5 +#define BJTgpi BJTstate+6 +#define BJTgmu BJTstate+7 +#define BJTgm BJTstate+8 +#define BJTgo BJTstate+9 +#define BJTqbe BJTstate+10 +#define BJTcqbe BJTstate+11 +#define BJTqbc BJTstate+12 +#define BJTcqbc BJTstate+13 +#define BJTqsub BJTstate+14 +#define BJTcqsub BJTstate+15 +#define BJTqbx BJTstate+16 +#define BJTcqbx BJTstate+17 +#define BJTgx BJTstate+18 +#define BJTcexbc BJTstate+19 +#define BJTgeqcb BJTstate+20 +#define BJTgcsub BJTstate+21 +#define BJTgeqbx BJTstate+22 +#define BJTvsub BJTstate+23 +#define BJTcdsub BJTstate+24 +#define BJTgdsub BJTstate+25 +#define BJTirci BJTstate+26 +#define BJTirci_Vrci BJTstate+27 +#define BJTirci_Vbci BJTstate+28 +#define BJTirci_Vbcx BJTstate+29 +#define BJTqbcx BJTstate+30 +#define BJTcqbcx BJTstate+31 +#define BJTgbcx BJTstate+32 + +#define BJTnumStates 33 #define BJTsensxpbe BJTstate+24 /* charge sensitivities and their derivatives. +25 for the derivatives - @@ -388,6 +414,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */ double BJTfNexp; double BJTsubSatCur; /* input - don't use */ double BJTemissionCoeffS; + double BJTintCollResist; + double BJTepiSatVoltage; + double BJTepiDoping; + double BJTepiCharge; int BJTtlev; int BJTtlevc; double BJTtbf1; @@ -459,6 +489,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */ double BJTtise2; double BJTtisc1; double BJTtisc2; + int BJTquasimod; + double BJTenergyGapQS; + double BJTtempExpRCI; + double BJTtempExpVO; double BJTvbeMax; /* maximum voltage over B-E junction */ double BJTvbcMax; /* maximum voltage over B-C junction */ double BJTvceMax; /* maximum voltage over C-E branch */ @@ -509,6 +543,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */ unsigned BJTfNexpGiven :1; unsigned BJTsubSatCurGiven : 1; unsigned BJTemissionCoeffSGiven : 1; + unsigned BJTintCollResistGiven : 1; + unsigned BJTepiSatVoltageGiven : 1; + unsigned BJTepiDopingGiven : 1; + unsigned BJTepiChargeGiven : 1; unsigned BJTtlevGiven : 1; unsigned BJTtlevcGiven : 1; unsigned BJTtbf1Given : 1; @@ -568,6 +606,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */ unsigned BJTtise2Given : 1; unsigned BJTtisc1Given : 1; unsigned BJTtisc2Given : 1; + unsigned BJTquasimodGiven : 1; + unsigned BJTenergyGapQSGiven : 1; + unsigned BJTtempExpRCIGiven : 1; + unsigned BJTtempExpVOGiven : 1; unsigned BJTvbeMaxGiven : 1; unsigned BJTvbcMaxGiven : 1; unsigned BJTvceMaxGiven : 1; @@ -650,6 +692,10 @@ enum { BJT_MOD_KF, BJT_MOD_ISS, BJT_MOD_NS, + BJT_MOD_RCO, + BJT_MOD_VO, + BJT_MOD_GAMMA, + BJT_MOD_QCO, BJT_MOD_TNOM, BJT_MOD_TLEV, BJT_MOD_TLEVC, @@ -711,6 +757,10 @@ enum { BJT_MOD_TISE2, BJT_MOD_TISC1, BJT_MOD_TISC2, + BJT_MOD_QUASIMOD, + BJT_MOD_EGQS, + BJT_MOD_XRCI, + BJT_MOD_XD, BJT_MOD_VBE_MAX, BJT_MOD_VBC_MAX, BJT_MOD_VCE_MAX, @@ -723,6 +773,7 @@ enum { BJT_QUEST_BASENODE, BJT_QUEST_EMITNODE, BJT_QUEST_SUBSTNODE, + BJT_QUEST_COLLCXNODE, BJT_QUEST_COLPRIMENODE, BJT_QUEST_BASEPRIMENODE, BJT_QUEST_EMITPRIMENODE, diff --git a/src/spicelib/devices/bjt/bjtload.c b/src/spicelib/devices/bjt/bjtload.c index a4cfc8574..1322328cb 100644 --- a/src/spicelib/devices/bjt/bjtload.c +++ b/src/spicelib/devices/bjt/bjtload.c @@ -64,6 +64,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double czbxf2; double czsub; double delvbc; + double delvbcx; double delvbe; double denom; double dqbdvc; @@ -111,6 +112,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double tf; double tr; double vbc; + double vbcx; double vbe; double vbx=0.0; double vce; @@ -137,6 +139,9 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) int error; int SenCond=0; double m; + double vrci=0.0, delvrci; + double Irci=0.0, Irci_Vrci=0.0, Irci_Vbci=0.0, Irci_Vbcx=0.0; + double Qbci=0.0, Qbci_Vbci=0.0, Qbcx, Qbcx_Vbcx=0.0, gbcx, cbcx; /* loop through all the models */ for( ; model != NULL; model = BJTnextModel(model)) { @@ -159,12 +164,13 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) SenCond = here->BJTsenPertFlag; } - gcsub=0; ceqsub=0; geqbx=0; ceqbx=0; geqcb=0; + gbcx=0; + cbcx=0; /* * dc model paramters */ @@ -195,6 +201,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) (ckt->CKTmode & MODEINITTRAN)) { vbe = *(ckt->CKTstate1 + here->BJTvbe); vbc = *(ckt->CKTstate1 + here->BJTvbc); + vbcx = *(ckt->CKTstate1 + here->BJTvbcx); + vrci = *(ckt->CKTstate1 + here->BJTvrci); vbx=model->BJTtype*( *(ckt->CKTrhsOp+here->BJTbaseNode)- *(ckt->CKTrhsOp+here->BJTcolPrimeNode)); @@ -205,6 +213,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) else{ vbe = *(ckt->CKTstate0 + here->BJTvbe); vbc = *(ckt->CKTstate0 + here->BJTvbc); + vbcx = *(ckt->CKTstate0 + here->BJTvbcx); + vrci = *(ckt->CKTstate0 + here->BJTvrci); if((ckt->CKTsenInfo->SENmode == DCSEN)|| (ckt->CKTsenInfo->SENmode == TRANSEN)){ vbx=model->BJTtype*( @@ -233,6 +243,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) if(ckt->CKTmode & MODEINITSMSIG) { vbe= *(ckt->CKTstate0 + here->BJTvbe); vbc= *(ckt->CKTstate0 + here->BJTvbc); + vbcx= *(ckt->CKTstate0 + here->BJTvbcx); + vrci = *(ckt->CKTstate0 + here->BJTvrci); vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); @@ -242,6 +254,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) } else if(ckt->CKTmode & MODEINITTRAN) { vbe = *(ckt->CKTstate1 + here->BJTvbe); vbc = *(ckt->CKTstate1 + here->BJTvbc); + vbcx = *(ckt->CKTstate1 + here->BJTvbcx); + vrci = *(ckt->CKTstate1 + here->BJTvrci); vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); @@ -256,20 +270,23 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)){ vbe=model->BJTtype*here->BJTicVBE; vce=model->BJTtype*here->BJTicVCE; - vbc=vbe-vce; + vbc=vbcx=vbe-vce; vbx=vbc; vsub=0; + vrci=0.0; } else if((ckt->CKTmode & MODEINITJCT) && (here->BJToff==0)) { vbe=here->BJTtVcrit; - vbc=0; + vbc=vbcx=0; /* ERROR: need to initialize VSUB, VBX here */ vsub=vbx=0; + vrci=0.0; } else if((ckt->CKTmode & MODEINITJCT) || ( (ckt->CKTmode & MODEINITFIX) && (here->BJToff!=0))) { vbe=0; - vbc=0; + vbc=vbcx=0; /* ERROR: need to initialize VSUB, VBX here */ vsub=vbx=0; + vrci=0.0; } else { #ifndef PREDICTOR if(ckt->CKTmode & MODEINITPRED) { @@ -282,6 +299,14 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) *(ckt->CKTstate1 + here->BJTvbc); vbc = (1+xfact)**(ckt->CKTstate1 + here->BJTvbc)- xfact* *(ckt->CKTstate2 + here->BJTvbc); + *(ckt->CKTstate0 + here->BJTvbcx) = + *(ckt->CKTstate1 + here->BJTvbcx); + vbcx = (1+xfact)**(ckt->CKTstate1 + here->BJTvbcx)- + xfact* *(ckt->CKTstate2 + here->BJTvbcx); + *(ckt->CKTstate0 + here->BJTvrci) = + *(ckt->CKTstate1 + here->BJTvrci); + vrci = (1+xfact) * *(ckt->CKTstate1 + here->BJTvrci)- + xfact * *(ckt->CKTstate2 + here->BJTvrci); *(ckt->CKTstate0 + here->BJTcc) = *(ckt->CKTstate1 + here->BJTcc); *(ckt->CKTstate0 + here->BJTcb) = @@ -296,10 +321,18 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) *(ckt->CKTstate1 + here->BJTgo); *(ckt->CKTstate0 + here->BJTgx) = *(ckt->CKTstate1 + here->BJTgx); - *(ckt->CKTstate0 + here->BJTvsub) = + *(ckt->CKTstate0 + here->BJTvsub) = *(ckt->CKTstate1 + here->BJTvsub); vsub = (1+xfact)**(ckt->CKTstate1 + here->BJTvsub)- xfact* *(ckt->CKTstate2 + here->BJTvsub); + *(ckt->CKTstate0 + here->BJTirci) = + *(ckt->CKTstate1 + here->BJTirci); + *(ckt->CKTstate0 + here->BJTirci_Vrci) = + *(ckt->CKTstate1 + here->BJTirci_Vrci); + *(ckt->CKTstate0 + here->BJTirci_Vbci) = + *(ckt->CKTstate1 + here->BJTirci_Vbci); + *(ckt->CKTstate0 + here->BJTirci_Vbcx) = + *(ckt->CKTstate1 + here->BJTirci_Vbcx); } else { #endif /* PREDICTOR */ /* @@ -311,6 +344,12 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vbc=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbasePrimeNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + vbcx=model->BJTtype*( + *(ckt->CKTrhsOld+here->BJTbasePrimeNode)- + *(ckt->CKTrhsOld+here->BJTcollCXNode)); + vrci=model->BJTtype*( + *(ckt->CKTrhsOld+here->BJTcollCXNode)- + *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOld+here->BJTsubstNode)- *(ckt->CKTrhsOld+here->BJTsubstConNode)); @@ -319,6 +358,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) #endif /* PREDICTOR */ delvbe=vbe- *(ckt->CKTstate0 + here->BJTvbe); delvbc=vbc- *(ckt->CKTstate0 + here->BJTvbc); + delvbcx=vbcx- *(ckt->CKTstate0 + here->BJTvbcx); + delvrci = vrci - *(ckt->CKTstate0 + here->BJTvrci); vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); @@ -348,6 +389,12 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) if( (fabs(delvbc) < ckt->CKTreltol*MAX(fabs(vbc), fabs(*(ckt->CKTstate0 + here->BJTvbc)))+ ckt->CKTvoltTol) ) + if( (fabs(delvbcx) < ckt->CKTreltol*MAX(fabs(vbcx), + fabs(*(ckt->CKTstate0 + here->BJTvbcx)))+ + ckt->CKTvoltTol) ) + if( (fabs(delvrci) < ckt->CKTreltol*MAX(fabs(vrci), + fabs(*(ckt->CKTstate0 + here->BJTvrci)))+ + ckt->CKTvoltTol) ) if( (fabs(cchat-*(ckt->CKTstate0 + here->BJTcc)) < ckt->CKTreltol* MAX(fabs(cchat), fabs(*(ckt->CKTstate0 + here->BJTcc)))+ @@ -361,6 +408,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) */ vbe = *(ckt->CKTstate0 + here->BJTvbe); vbc = *(ckt->CKTstate0 + here->BJTvbc); + vbcx = *(ckt->CKTstate0 + here->BJTvbcx); + vrci = *(ckt->CKTstate0 + here->BJTvrci); cc = *(ckt->CKTstate0 + here->BJTcc); cb = *(ckt->CKTstate0 + here->BJTcb); gpi = *(ckt->CKTstate0 + here->BJTgpi); @@ -374,6 +423,12 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vsub = *(ckt->CKTstate0 + here->BJTvsub); gdsub = *(ckt->CKTstate0 + here->BJTgdsub); cdsub = *(ckt->CKTstate0 + here->BJTcdsub); + Irci = *(ckt->CKTstate0 + here->BJTirci); + Irci_Vrci = *(ckt->CKTstate0 + here->BJTirci_Vrci); + Irci_Vbci = *(ckt->CKTstate0 + here->BJTirci_Vbci); + Irci_Vbcx = *(ckt->CKTstate0 + here->BJTirci_Vbcx); + gbcx = *(ckt->CKTstate0 + here->BJTgbcx); + cbcx = *(ckt->CKTstate0 + here->BJTcqbcx); goto load; } #endif /*NOBYPASS*/ @@ -389,6 +444,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vsub = DEVpnjlim(vsub,*(ckt->CKTstate0 + here->BJTvsub),vt, here->BJTtSubVcrit,&ichk1); if (ichk1 == 1) icheck=1; + vrci = vbc - vbcx; /* in case vbc was limited */ } /* * determine dc current and derivitives @@ -465,6 +521,65 @@ next1: vtn=vt*here->BJTtemissionCoeffF; gdsub = csubsat*evsub/vts + ckt->CKTgmin; cdsub = csubsat*(evsub-1) + ckt->CKTgmin*vsub; } + + /* + * Kull's Quasi-Saturation model + */ + if (model->BJTintCollResistGiven) { + double Kbci,Kbci_Vbci,Kbcx,Kbcx_Vbcx; + double rKp1,rKp1_Vbci,rKp1_Vbcx,xvar1,xvar1_Vbci,xvar1_Vbcx; + double Vcorr,Vcorr_Vbci,Vcorr_Vbcx,Iohm,Iohm_Vrci,Iohm_Vbci,Iohm_Vbcx; + double quot,quot_Vrci; + if (vrci > 0.) { + Kbci = sqrt(1+here->BJTtepiDoping*exp(vbc/vt)); + Kbci_Vbci = here->BJTtepiDoping*exp(vbc/vt)/(2*vt*Kbci); + Kbcx = sqrt(1+here->BJTtepiDoping*exp(vbcx/vt)); + Kbcx_Vbcx = here->BJTtepiDoping*exp(vbcx/vt)/(2*vt*Kbcx); + + rKp1 = (1+Kbci)/(1+Kbcx); + rKp1_Vbci = Kbci_Vbci/(1+Kbci); + rKp1_Vbcx = -(1+Kbci)*Kbcx_Vbcx/((Kbcx+1)*(Kbcx+1)); + xvar1 = log(rKp1); + xvar1_Vbci = rKp1_Vbci/rKp1; + xvar1_Vbcx = rKp1_Vbcx/rKp1; + + Vcorr = vt*(Kbci - Kbcx - xvar1); + Vcorr_Vbci = vt*(Kbci_Vbci - xvar1_Vbci); + Vcorr_Vbcx = vt*(-Kbcx_Vbcx - xvar1_Vbcx); + + Iohm = (vrci+Vcorr)/here->BJTtintCollResist; + Iohm_Vrci = 1/here->BJTtintCollResist; + Iohm_Vbci = Vcorr_Vbci/here->BJTtintCollResist; + Iohm_Vbcx = Vcorr_Vbcx/here->BJTtintCollResist; + + quot = 1+fabs(vrci)/here->BJTtepiSatVoltage; + quot_Vrci = vrci/(here->BJTtepiSatVoltage*fabs(vrci)); + + Irci = Iohm/quot + ckt->CKTgmin*vrci; + Irci_Vrci = Iohm_Vrci/quot-Iohm*quot_Vrci/(quot*quot) + ckt->CKTgmin; + Irci_Vbci = Iohm_Vbci/quot; + Irci_Vbcx = Iohm_Vbcx/quot; + + Qbci = model->BJTepiCharge*Kbci; + Qbci_Vbci = model->BJTepiCharge*Kbci_Vbci; + Qbcx = model->BJTepiCharge*Kbcx; + Qbcx_Vbcx = model->BJTepiCharge*Kbcx_Vbcx; + *(ckt->CKTstate0 + here->BJTqbcx) = Qbcx; + here->BJTcapbcx = Qbcx_Vbcx; + } else { + Irci = vrci/here->BJTtintCollResist + ckt->CKTgmin*vrci; + Irci_Vrci = 1/here->BJTtintCollResist + ckt->CKTgmin; + Irci_Vbci = 0.0; + Irci_Vbcx = 0.0; + + Qbci = 0.0; + Qbci_Vbci = 0.0; + Qbcx = 0.0; + Qbcx_Vbcx = 0.0; + *(ckt->CKTstate0 + here->BJTqbcx) = Qbcx; + here->BJTcapbcx = Qbcx_Vbcx; + } + } /* * determine base charge terms */ @@ -548,7 +663,7 @@ next1: vtn=vt*here->BJTtemissionCoeffF; cdis=model->BJTbaseFractionBCcap; if (model->BJTsubs == VERTICAL) ctot=here->BJTtBCcap*here->BJTareab; - else + else ctot=here->BJTtBCcap*here->BJTareac; czbc=ctot*cdis; czbx=ctot-czbc; @@ -641,6 +756,11 @@ next1: vtn=vt*here->BJTtemissionCoeffF; } here->BJTcapbe = capbe; here->BJTcapbc = capbc; + if (model->BJTintCollResistGiven) { + *(ckt->CKTstate0 + here->BJTqbc) += Qbci; + here->BJTcapbc += Qbci_Vbci; + capbc += Qbci_Vbci; + } here->BJTcapsub = capsub; here->BJTcapbx = capbx; @@ -655,6 +775,7 @@ next1: vtn=vt*here->BJTtemissionCoeffF; *(ckt->CKTstate0 + here->BJTcqsub) = capsub; *(ckt->CKTstate0 + here->BJTcqbx) = capbx; *(ckt->CKTstate0 + here->BJTcexbc) = geqcb; + *(ckt->CKTstate0 + here->BJTcqbcx) = Qbcx_Vbcx; if(SenCond){ *(ckt->CKTstate0 + here->BJTcc) = cc; *(ckt->CKTstate0 + here->BJTcb) = cb; @@ -663,6 +784,9 @@ next1: vtn=vt*here->BJTtemissionCoeffF; *(ckt->CKTstate0 + here->BJTgm) = gm; *(ckt->CKTstate0 + here->BJTgo) = go; *(ckt->CKTstate0 + here->BJTgx) = gx; + *(ckt->CKTstate0 + here->BJTirci_Vrci) = Irci_Vrci; + *(ckt->CKTstate0 + here->BJTirci_Vbci) = Irci_Vbci; + *(ckt->CKTstate0 + here->BJTirci_Vbcx) = Irci_Vbcx; *(ckt->CKTstate0 + here->BJTgcsub) = gcsub; *(ckt->CKTstate0 + here->BJTgeqbx) = geqbx; } @@ -697,6 +821,8 @@ next1: vtn=vt*here->BJTtemissionCoeffF; *(ckt->CKTstate0 + here->BJTqbx) ; *(ckt->CKTstate1 + here->BJTqsub) = *(ckt->CKTstate0 + here->BJTqsub) ; + *(ckt->CKTstate1 + here->BJTqbcx) = + *(ckt->CKTstate0 + here->BJTqbcx) ; } error = NIintegrate(ckt,&geq,&ceq,capbe,here->BJTqbe); if(error) return(error); @@ -708,11 +834,19 @@ next1: vtn=vt*here->BJTtemissionCoeffF; gmu=gmu+geq; cb=cb+*(ckt->CKTstate0 + here->BJTcqbc); cc=cc-*(ckt->CKTstate0 + here->BJTcqbc); + if (model->BJTintCollResistGiven) { + error = NIintegrate(ckt,&geq,&ceq,Qbcx_Vbcx,here->BJTqbcx); + if(error) return(error); + gbcx = geq; + cbcx = *(ckt->CKTstate0 + here->BJTcqbcx); + } if(ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate1 + here->BJTcqbe) = *(ckt->CKTstate0 + here->BJTcqbe); *(ckt->CKTstate1 + here->BJTcqbc) = *(ckt->CKTstate0 + here->BJTcqbc); + *(ckt->CKTstate1 + here->BJTcqbcx) = + *(ckt->CKTstate0 + here->BJTcqbcx); } } } @@ -747,6 +881,8 @@ next1: vtn=vt*here->BJTtemissionCoeffF; next2: *(ckt->CKTstate0 + here->BJTvbe) = vbe; *(ckt->CKTstate0 + here->BJTvbc) = vbc; + *(ckt->CKTstate0 + here->BJTvbcx) = vbcx; + *(ckt->CKTstate0 + here->BJTvrci) = vrci; *(ckt->CKTstate0 + here->BJTcc) = cc; *(ckt->CKTstate0 + here->BJTcb) = cb; *(ckt->CKTstate0 + here->BJTgpi) = gpi; @@ -760,6 +896,10 @@ next2: *(ckt->CKTstate0 + here->BJTvsub) = vsub; *(ckt->CKTstate0 + here->BJTgdsub) = gdsub; *(ckt->CKTstate0 + here->BJTcdsub) = cdsub; + *(ckt->CKTstate0 + here->BJTirci) = Irci; + *(ckt->CKTstate0 + here->BJTirci_Vrci) = Irci_Vrci; + *(ckt->CKTstate0 + here->BJTirci_Vbci) = Irci_Vbci; + *(ckt->CKTstate0 + here->BJTirci_Vbcx) = Irci_Vbcx; /* Do not load the Jacobian and the rhs if perturbation is being carried out */ @@ -795,14 +935,15 @@ load: *(here->BJTcolColPtr) += m * (gcpr); *(here->BJTbaseBasePtr) += m * (gx+geqbx); *(here->BJTemitEmitPtr) += m * (gepr); - *(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+gcpr+geqbx); + *(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+geqbx); + *(here->BJTcollCXcollCXPtr) += m * (gcpr); *(here->BJTsubstConSubstConPtr) += m * (geqsub); *(here->BJTbasePrimeBasePrimePtr) += m * (gx +gpi+gmu+geqcb); *(here->BJTemitPrimeEmitPrimePtr) += m * (gpi+gepr+gm+go); - *(here->BJTcolColPrimePtr) += m * (-gcpr); + *(here->BJTcollCollCXPtr) += m * (-gcpr); *(here->BJTbaseBasePrimePtr) += m * (-gx); *(here->BJTemitEmitPrimePtr) += m * (-gepr); - *(here->BJTcolPrimeColPtr) += m * (-gcpr); + *(here->BJTcollCXCollPtr) += m * (-gcpr); *(here->BJTcolPrimeBasePrimePtr) += m * (-gmu+gm); *(here->BJTcolPrimeEmitPrimePtr) += m * (-gm-go); *(here->BJTbasePrimeBasePtr) += m * (-gx); @@ -816,6 +957,34 @@ load: *(here->BJTsubstSubstConPtr) += m * (-geqsub); *(here->BJTbaseColPrimePtr) += m * (-geqbx); *(here->BJTcolPrimeBasePtr) += m * (-geqbx); +/* +c Stamp element: Irci +*/ + if (model->BJTintCollResistGiven) { + double rhs_current = model->BJTtype * m * (Irci - Irci_Vrci*vrci - Irci_Vbci*vbc - Irci_Vbcx*vbcx); + *(ckt->CKTrhs + here->BJTcollCXNode) += -rhs_current; + *(here->BJTcollCXcollCXPtr) += m * Irci_Vrci; + *(here->BJTcollCXColPrimePtr) += m * -Irci_Vrci; + *(here->BJTcollCXBasePrimePtr) += m * Irci_Vbci; + *(here->BJTcollCXColPrimePtr) += m * -Irci_Vbci; + *(here->BJTcollCXBasePrimePtr) += m * Irci_Vbcx; + *(here->BJTcollCXcollCXPtr) += m * -Irci_Vbcx; + *(ckt->CKTrhs + here->BJTcolPrimeNode) += rhs_current; + *(here->BJTcolPrimeCollCXPtr) += m * -Irci_Vrci; + *(here->BJTcolPrimeColPrimePtr) += m * Irci_Vrci; + *(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbci; + *(here->BJTcolPrimeColPrimePtr) += m * Irci_Vbci; + *(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbcx; + *(here->BJTcolPrimeCollCXPtr) += m * Irci_Vbcx; + + *(ckt->CKTrhs + here->BJTbasePrimeNode) += m * -cbcx; + *(ckt->CKTrhs + here->BJTcollCXNode) += m * cbcx; + *(here->BJTbasePrimeBasePrimePtr) += m * gbcx; + *(here->BJTcollCXcollCXPtr) += m * gbcx; + *(here->BJTbasePrimeCollCXPtr) += m * -gbcx; + *(here->BJTcollCXBasePrimePtr) += m * -gbcx; + } + } } return(OK); diff --git a/src/spicelib/devices/bjt/bjtmask.c b/src/spicelib/devices/bjt/bjtmask.c index 87a22d7fa..2034b1826 100644 --- a/src/spicelib/devices/bjt/bjtmask.c +++ b/src/spicelib/devices/bjt/bjtmask.c @@ -201,6 +201,18 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case BJT_MOD_NS: value->rValue = here->BJTemissionCoeffS; return(OK); + case BJT_MOD_RCO: + value->rValue = here->BJTintCollResist; + return(OK); + case BJT_MOD_VO: + value->rValue = here->BJTepiSatVoltage; + return(OK); + case BJT_MOD_GAMMA: + value->rValue = here->BJTepiDoping; + return(OK); + case BJT_MOD_QCO: + value->rValue = here->BJTepiCharge; + return(OK); case BJT_MOD_TLEV: value->iValue = here->BJTtlev; return(OK); @@ -378,6 +390,18 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case BJT_MOD_TISC2: value->rValue = here->BJTtisc2; return(OK); + case BJT_MOD_QUASIMOD: + value->iValue = here->BJTquasimod; + return(OK); + case BJT_MOD_EGQS: + value->rValue = here->BJTenergyGapQS; + return(OK); + case BJT_MOD_XRCI: + value->rValue = here->BJTtempExpRCI; + return(OK); + case BJT_MOD_XD: + value->rValue = here->BJTtempExpVO; + return(OK); case BJT_MOD_VBE_MAX: value->rValue = here->BJTvbeMax; return(OK); diff --git a/src/spicelib/devices/bjt/bjtmpar.c b/src/spicelib/devices/bjt/bjtmpar.c index d917aabee..51409905b 100644 --- a/src/spicelib/devices/bjt/bjtmpar.c +++ b/src/spicelib/devices/bjt/bjtmpar.c @@ -218,6 +218,22 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel) mods->BJTemissionCoeffS = value->rValue; mods->BJTemissionCoeffSGiven = TRUE; break; + case BJT_MOD_RCO: + mods->BJTintCollResist = value->rValue; + mods->BJTintCollResistGiven = TRUE; + break; + case BJT_MOD_VO: + mods->BJTepiSatVoltage = value->rValue; + mods->BJTepiSatVoltageGiven = TRUE; + break; + case BJT_MOD_GAMMA: + mods->BJTepiDoping = value->rValue; + mods->BJTepiDopingGiven = TRUE; + break; + case BJT_MOD_QCO: + mods->BJTepiCharge = value->rValue; + mods->BJTepiChargeGiven = TRUE; + break; case BJT_MOD_TLEV: mods->BJTtlev = value->iValue; mods->BJTtlevGiven = TRUE; @@ -454,6 +470,22 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel) mods->BJTtisc2 = value->rValue; mods->BJTtisc2Given = TRUE; break; + case BJT_MOD_QUASIMOD: + mods->BJTquasimod = value->iValue; + mods->BJTquasimodGiven = TRUE; + break; + case BJT_MOD_EGQS: + mods->BJTenergyGapQS = value->rValue; + mods->BJTenergyGapQSGiven = TRUE; + break; + case BJT_MOD_XRCI: + mods->BJTtempExpRCI = value->rValue; + mods->BJTtempExpRCIGiven = TRUE; + break; + case BJT_MOD_XD: + mods->BJTtempExpVO = value->rValue; + mods->BJTtempExpVOGiven = TRUE; + break; case BJT_MOD_VBE_MAX: mods->BJTvbeMax = value->rValue; mods->BJTvbeMaxGiven = TRUE; diff --git a/src/spicelib/devices/bjt/bjtnoise.c b/src/spicelib/devices/bjt/bjtnoise.c index 8cbf4b48c..13b7fb384 100644 --- a/src/spicelib/devices/bjt/bjtnoise.c +++ b/src/spicelib/devices/bjt/bjtnoise.c @@ -85,7 +85,7 @@ for (model=firstModel; model != NULL; model=BJTnextModel(model)) { case N_DENS: NevalSrc(&noizDens[BJTRCNOIZ],&lnNdens[BJTRCNOIZ], - ckt,THERMNOISE,inst->BJTcolPrimeNode,inst->BJTcolNode, + ckt,THERMNOISE,inst->BJTcollCXNode,inst->BJTcolNode, inst->BJTtcollectorConduct * inst->BJTarea * inst->BJTm); NevalSrc(&noizDens[BJTRBNOIZ],&lnNdens[BJTRBNOIZ], diff --git a/src/spicelib/devices/bjt/bjtpzld.c b/src/spicelib/devices/bjt/bjtpzld.c index eca48c04f..95f62b322 100644 --- a/src/spicelib/devices/bjt/bjtpzld.c +++ b/src/spicelib/devices/bjt/bjtpzld.c @@ -32,6 +32,7 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) double xcsub; double xcmcb; double m; + double Irci_Vrci, Irci_Vbci, Irci_Vbcx, xcbcx; for( ; model != NULL; model = BJTnextModel(model)) { for( here = BJTinstances(model); here!= NULL; @@ -45,6 +46,9 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) gmu= *(ckt->CKTstate0 + here->BJTgmu); gm= *(ckt->CKTstate0 + here->BJTgm); go= *(ckt->CKTstate0 + here->BJTgo); + Irci_Vrci = *(ckt->CKTstate0 + here->BJTirci_Vrci); + Irci_Vbci = *(ckt->CKTstate0 + here->BJTirci_Vbci); + Irci_Vbcx = *(ckt->CKTstate0 + here->BJTirci_Vbcx); xgm=0; gx= *(ckt->CKTstate0 + here->BJTgx); xcpi= *(ckt->CKTstate0 + here->BJTcqbe); @@ -52,13 +56,15 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) xcbx= *(ckt->CKTstate0 + here->BJTcqbx); xcsub= *(ckt->CKTstate0 + here->BJTcqsub); xcmcb= *(ckt->CKTstate0 + here->BJTcexbc); + xcbcx= *(ckt->CKTstate0 + here->BJTcqbcx); *(here->BJTcolColPtr) += m * (gcpr); *(here->BJTbaseBasePtr) += m * ((gx) + (xcbx) * (s->real)); *(here->BJTbaseBasePtr + 1) += m * ((xcbx) * (s->imag)); *(here->BJTemitEmitPtr) += m * (gepr); - *(here->BJTcolPrimeColPrimePtr) += m * ((gmu+go+gcpr) + (xcmu+xcbx) * (s->real)); + *(here->BJTcolPrimeColPrimePtr) += m * ((gmu+go) + (xcmu+xcbx) * (s->real)); *(here->BJTcolPrimeColPrimePtr + 1) += m * ((xcmu+xcbx) * (s->imag)); + *(here->BJTcollCXcollCXPtr) += m * (gcpr); *(here->BJTsubstConSubstConPtr) += m * (xcsub)* (s->real); *(here->BJTsubstConSubstConPtr + 1) += m * (xcsub)* (s->imag); @@ -67,10 +73,10 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) *(here->BJTbasePrimeBasePrimePtr + 1) += m * ((xcpi+xcmu+xcmcb) * (s->imag)); *(here->BJTemitPrimeEmitPrimePtr) += m * ((gpi+gepr+gm+go) + (xcpi+xgm) * (s->real)); *(here->BJTemitPrimeEmitPrimePtr + 1) += m * ((xcpi+xgm) * (s->imag)); - *(here->BJTcolColPrimePtr) += m * (-gcpr); + *(here->BJTcollCollCXPtr) += m * (-gcpr); *(here->BJTbaseBasePrimePtr) += m * (-gx); *(here->BJTemitEmitPrimePtr) += m * (-gepr); - *(here->BJTcolPrimeColPtr) += m * (-gcpr); + *(here->BJTcollCXCollPtr) += m * (-gcpr); *(here->BJTcolPrimeBasePrimePtr) += m * ((-gmu+gm) + (-xcmu+xgm) * (s->real)); *(here->BJTcolPrimeBasePrimePtr + 1) += m * ((-xcmu+xgm) * (s->imag)); *(here->BJTcolPrimeEmitPrimePtr) += m * ((-gm-go) + (-xgm) * (s->real)); @@ -95,6 +101,28 @@ BJTpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) *(here->BJTbaseColPrimePtr + 1) += m * ((-xcbx) * (s->imag)); *(here->BJTcolPrimeBasePtr) += m * ((-xcbx) * (s->real)); *(here->BJTcolPrimeBasePtr + 1) += m * ((-xcbx) * (s->imag)); + if (model->BJTintCollResistGiven) { + *(here->BJTcollCXcollCXPtr) += m * Irci_Vrci; + *(here->BJTcollCXColPrimePtr) += m * -Irci_Vrci; + *(here->BJTcollCXBasePrimePtr) += m * Irci_Vbci; + *(here->BJTcollCXColPrimePtr) += m * -Irci_Vbci; + *(here->BJTcollCXBasePrimePtr) += m * Irci_Vbcx; + *(here->BJTcollCXcollCXPtr) += m * -Irci_Vbcx; + *(here->BJTcolPrimeCollCXPtr) += m * -Irci_Vrci; + *(here->BJTcolPrimeColPrimePtr) += m * Irci_Vrci; + *(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbci; + *(here->BJTcolPrimeColPrimePtr) += m * Irci_Vbci; + *(here->BJTcolPrimeBasePrimePtr) += m * -Irci_Vbcx; + *(here->BJTcolPrimeCollCXPtr) += m * Irci_Vbcx; + *(here->BJTbasePrimeBasePrimePtr) += m * xcbcx * (s->real); + *(here->BJTbasePrimeBasePrimePtr + 1) += m * xcbcx * (s->imag); + *(here->BJTcollCXcollCXPtr) += m * xcbcx * (s->real); + *(here->BJTcollCXcollCXPtr + 1) += m * xcbcx * (s->imag); + *(here->BJTbasePrimeCollCXPtr) += m * -xcbcx * (s->real); + *(here->BJTbasePrimeCollCXPtr + 1) += m * -xcbcx * (s->imag); + *(here->BJTcollCXBasePrimePtr) += m * -xcbcx * (s->real); + *(here->BJTcollCXBasePrimePtr + 1) += m * -xcbcx * (s->imag); + } } } return(OK); diff --git a/src/spicelib/devices/bjt/bjtsetup.c b/src/spicelib/devices/bjt/bjtsetup.c index 961ea5100..e22f51d84 100644 --- a/src/spicelib/devices/bjt/bjtsetup.c +++ b/src/spicelib/devices/bjt/bjtsetup.c @@ -140,6 +140,18 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->BJTemissionCoeffSGiven) { model->BJTemissionCoeffS = 1.0; } + if(!model->BJTintCollResistGiven) { + model->BJTintCollResist = 0.01; + } + if(!model->BJTepiSatVoltageGiven) { + model->BJTepiSatVoltage = 10.0; + } + if(!model->BJTepiDopingGiven) { + model->BJTepiDoping = 1.0e-11; + } + if(!model->BJTepiChargeGiven) { + model->BJTepiCharge = 0.0; + } if(!model->BJTtlevGiven) { model->BJTtlev = 0; } @@ -322,6 +334,24 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->BJTtisc2Given) { model->BJTtisc2 = 0.0; } + if(!model->BJTquasimodGiven) { + model->BJTquasimod = 0; + } + if(!model->BJTenergyGapQSGiven) { + model->BJTenergyGapQS = 1.206; + } + if(!model->BJTtempExpRCIGiven) { + if (model->BJTtype == NPN) + model->BJTtempExpRCI = 2.42; + else + model->BJTtempExpRCI = 2.2; + } + if(!model->BJTtempExpVOGiven) { + if (model->BJTtype == NPN) + model->BJTtempExpVO = 0.87; + else + model->BJTtempExpVO = 0.52; + } if(!model->BJTvbeMaxGiven) { model->BJTvbeMax = 1e99; } @@ -370,7 +400,15 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } if(model->BJTcollectorResist == 0) { - here->BJTcolPrimeNode = here->BJTcolNode; + here->BJTcollCXNode = here->BJTcolNode; + } else if(here->BJTcollCXNode == 0) { + error = CKTmkVolt(ckt, &tmp, here->BJTname, "collCX"); + if(error) return(error); + here->BJTcollCXNode = tmp->number; + } + + if(!model->BJTintCollResistGiven) { + here->BJTcolPrimeNode = here->BJTcollCXNode; } else if(here->BJTcolPrimeNode == 0) { error = CKTmkVolt(ckt,&tmp,here->BJTname,"collector"); if(error) return(error); @@ -432,10 +470,11 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ } } while(0) - TSTALLOC(BJTcolColPrimePtr,BJTcolNode,BJTcolPrimeNode); + + TSTALLOC(BJTcollCollCXPtr,BJTcolNode,BJTcollCXNode); TSTALLOC(BJTbaseBasePrimePtr,BJTbaseNode,BJTbasePrimeNode); TSTALLOC(BJTemitEmitPrimePtr,BJTemitNode,BJTemitPrimeNode); - TSTALLOC(BJTcolPrimeColPtr,BJTcolPrimeNode,BJTcolNode); + TSTALLOC(BJTcollCXCollPtr,BJTcollCXNode,BJTcolNode); TSTALLOC(BJTcolPrimeBasePrimePtr,BJTcolPrimeNode,BJTbasePrimeNode); TSTALLOC(BJTcolPrimeEmitPrimePtr,BJTcolPrimeNode,BJTemitPrimeNode); TSTALLOC(BJTbasePrimeBasePtr,BJTbasePrimeNode,BJTbaseNode); @@ -462,6 +501,15 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ TSTALLOC(BJTsubstSubstConPtr,BJTsubstNode,BJTsubstConNode); TSTALLOC(BJTbaseColPrimePtr,BJTbaseNode,BJTcolPrimeNode); TSTALLOC(BJTcolPrimeBasePtr,BJTcolPrimeNode,BJTbaseNode); + + TSTALLOC(BJTcollCXcollCXPtr,BJTcollCXNode,BJTcollCXNode); + + if(model->BJTintCollResistGiven) { + TSTALLOC(BJTcollCXBasePrimePtr,BJTcollCXNode,BJTbasePrimeNode); + TSTALLOC(BJTbasePrimeCollCXPtr,BJTbasePrimeNode,BJTcollCXNode); + TSTALLOC(BJTcolPrimeCollCXPtr,BJTcolPrimeNode,BJTcollCXNode); + TSTALLOC(BJTcollCXColPrimePtr,BJTcollCXNode,BJTcolPrimeNode); + } } } return(OK); @@ -481,20 +529,25 @@ BJTunsetup( for (here = BJTinstances(model); here != NULL; here=BJTnextInstance(here)) { - if (here->BJTemitPrimeNode > 0 - && here->BJTemitPrimeNode != here->BJTemitNode) - CKTdltNNum(ckt, here->BJTemitPrimeNode); - here->BJTemitPrimeNode = 0; + if (here->BJTemitPrimeNode > 0 + && here->BJTemitPrimeNode != here->BJTemitNode) + CKTdltNNum(ckt, here->BJTemitPrimeNode); + here->BJTemitPrimeNode = 0; - if (here->BJTbasePrimeNode > 0 - && here->BJTbasePrimeNode != here->BJTbaseNode) - CKTdltNNum(ckt, here->BJTbasePrimeNode); - here->BJTbasePrimeNode = 0; + if (here->BJTbasePrimeNode > 0 + && here->BJTbasePrimeNode != here->BJTbaseNode) + CKTdltNNum(ckt, here->BJTbasePrimeNode); + here->BJTbasePrimeNode = 0; - if (here->BJTcolPrimeNode > 0 - && here->BJTcolPrimeNode != here->BJTcolNode) + if (here->BJTcollCXNode > 0 + && here->BJTcollCXNode != here->BJTcolNode) + CKTdltNNum(ckt, here->BJTcollCXNode); + here->BJTcollCXNode = 0; + + if (here->BJTcolPrimeNode > 0 + && here->BJTcolPrimeNode != here->BJTcollCXNode) CKTdltNNum(ckt, here->BJTcolPrimeNode); - here->BJTcolPrimeNode = 0; + here->BJTcolPrimeNode = 0; } } return OK; diff --git a/src/spicelib/devices/bjt/bjttemp.c b/src/spicelib/devices/bjt/bjttemp.c index 8456eb42f..eb80b50b5 100644 --- a/src/spicelib/devices/bjt/bjttemp.c +++ b/src/spicelib/devices/bjt/bjttemp.c @@ -177,6 +177,22 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt) here->BJTtSatCur = pow(model->BJTsatCur,(1+model->BJTtis1*dt+model->BJTtis2*dt*dt)); } + if (model->BJTintCollResistGiven) { + if (model->BJTquasimod == 1) { + double rT=here->BJTtemp/model->BJTtnom; + here->BJTtintCollResist=model->BJTintCollResist*pow(rT,model->BJTtempExpRCI); + here->BJTtepiSatVoltage=model->BJTepiSatVoltage*pow(rT,model->BJTtempExpVO); + double xvar1=pow(rT,model->BJTtempExpIS); + double xvar2=-model->BJTenergyGapQS*(1.0-rT)/vt; + double xvar3=exp(xvar2); + here->BJTtepiDoping=model->BJTepiDoping*xvar1*xvar3; + } else { + here->BJTtintCollResist=model->BJTintCollResist; + here->BJTtepiSatVoltage=model->BJTepiSatVoltage; + here->BJTtepiDoping=model->BJTepiDoping; + } + } + if (model->BJTtlev == 0) { bfactor = exp(ratlog*model->BJTbetaExp); } else if (model->BJTtlev == 1) { diff --git a/src/spicelib/devices/bjt/bjttrunc.c b/src/spicelib/devices/bjt/bjttrunc.c index abee58deb..86e197dcd 100644 --- a/src/spicelib/devices/bjt/bjttrunc.c +++ b/src/spicelib/devices/bjt/bjttrunc.c @@ -30,6 +30,9 @@ BJTtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep) CKTterr(here->BJTqbe,ckt,timeStep); CKTterr(here->BJTqbc,ckt,timeStep); CKTterr(here->BJTqsub,ckt,timeStep); + if (model->BJTintCollResistGiven) { + CKTterr(here->BJTqbcx,ckt,timeStep); + } } } return(OK);