Browse Source

introduce IBE and IBC model parameter for more accurate current calculation

pre-master-46
dwarning 5 years ago
committed by Holger Vogt
parent
commit
01fb0ac18b
  1. 2
      src/spicelib/devices/bjt/bjt.c
  2. 8
      src/spicelib/devices/bjt/bjtdefs.h
  3. 21
      src/spicelib/devices/bjt/bjtdset.c
  4. 21
      src/spicelib/devices/bjt/bjtload.c
  5. 6
      src/spicelib/devices/bjt/bjtmask.c
  6. 8
      src/spicelib/devices/bjt/bjtmpar.c
  7. 19
      src/spicelib/devices/bjt/bjtsetup.c
  8. 8
      src/spicelib/devices/bjt/bjttemp.c

2
src/spicelib/devices/bjt/bjt.c

@ -82,6 +82,8 @@ IFparm BJTmPTable[] = { /* model parameters */
IOP("tnom", BJT_MOD_TNOM, IF_REAL, "Parameter measurement temperature"),
IOPR("tref", BJT_MOD_TNOM, IF_REAL, "Parameter measurement temperature"),
IOP("is", BJT_MOD_IS, IF_REAL, "Saturation Current"),
IOP("ibe", BJT_MOD_IBE, IF_REAL, "Base-Emitter saturation Current"),
IOP("ibc", BJT_MOD_IBC, IF_REAL, "Base-Collector saturation Current"),
IOP("bf", BJT_MOD_BF, IF_REAL, "Ideal forward beta"),
IOP("nf", BJT_MOD_NF, IF_REAL, "Forward emission coefficient"),
IOP("vaf", BJT_MOD_VAF, IF_REAL, "Forward Early voltage"),

8
src/spicelib/devices/bjt/bjtdefs.h

@ -60,6 +60,8 @@ typedef struct sBJTinstance {
double BJTtemp; /* instance temperature */
double BJTdtemp; /* instance delta temperature from circuit */
double BJTtSatCur; /* temperature adjusted saturation current */
double BJTBEtSatCur; /* temperature adjusted saturation current */
double BJTBCtSatCur; /* temperature adjusted saturation current */
double BJTtBetaF; /* temperature adjusted forward beta */
double BJTtBetaR; /* temperature adjusted reverse beta */
double BJTtBEleakCur; /* temperature adjusted B-E leakage current */
@ -371,6 +373,8 @@ typedef struct sBJTmodel { /* model structure for a bjt */
double BJTtnom; /* nominal temperature */
double BJTsatCur; /* input - don't use */
double BJTBEsatCur;
double BJTBCsatCur;
double BJTbetaF; /* input - don't use */
double BJTemissionCoeffF;
double BJTearlyVoltF;
@ -505,6 +509,8 @@ typedef struct sBJTmodel { /* model structure for a bjt */
unsigned BJTsubsGiven : 1;
unsigned BJTtnomGiven : 1;
unsigned BJTsatCurGiven : 1;
unsigned BJTBEsatCurGiven : 1;
unsigned BJTBCsatCurGiven : 1;
unsigned BJTbetaFGiven : 1;
unsigned BJTemissionCoeffFGiven : 1;
unsigned BJTearlyVoltFGiven : 1;
@ -659,6 +665,8 @@ enum {
BJT_MOD_NPN = 101,
BJT_MOD_PNP,
BJT_MOD_IS,
BJT_MOD_IBE,
BJT_MOD_IBC,
BJT_MOD_BF,
BJT_MOD_NF,
BJT_MOD_VAF,

21
src/spicelib/devices/bjt/bjtdset.c

@ -35,7 +35,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt)
double cbe;
double cben;
double cdis;
double csat;
double csatbe, csatbc;
double ctot;
double czbc;
double czbcf2;
@ -153,7 +153,8 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt)
/*
* dc model paramters
*/
csat=here->BJTtSatCur*here->BJTarea * here->BJTm;
csatbe=here->BJTBEtSatCur*here->BJTarea * here->BJTm;
csatbc=here->BJTBCtSatCur*here->BJTarea * here->BJTm;
rbpr=here->BJTtminBaseResist/(here->BJTarea * here->BJTm);
rbpi=here->BJTtbaseResist/(here->BJTarea * here->BJTm)-rbpr;
oik=here->BJTtinvRollOffF/(here->BJTarea * here->BJTm);
@ -228,9 +229,9 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt)
vtn=vt*here->BJTtemissionCoeffF;
if(vbe > -5*vtn){
evbe=exp(vbe/vtn);
cbe=csat*(evbe-1)+ckt->CKTgmin*vbe;
gbe=csat*evbe/vtn+ckt->CKTgmin;
gbe2 = csat*evbe/vtn/vtn;
cbe=csatbe*(evbe-1)+ckt->CKTgmin*vbe;
gbe=csatbe*evbe/vtn+ckt->CKTgmin;
gbe2 = csatbe*evbe/vtn/vtn;
gbe3 = gbe2/vtn;
/* note - these are actually derivs, not Taylor
@ -247,7 +248,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt)
gben3=gben2/vte;
}
} else {
gbe = -csat/vbe+ckt->CKTgmin;
gbe = -csatbe/vbe+ckt->CKTgmin;
gbe2=gbe3=gben2=gben3=0;
cbe=gbe*vbe;
gben = -c2/vbe;
@ -256,9 +257,9 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt)
vtn=vt*here->BJTtemissionCoeffR;
if(vbc > -5*vtn) {
evbc=exp(vbc/vtn);
cbc=csat*(evbc-1)+ckt->CKTgmin*vbc;
gbc=csat*evbc/vtn+ckt->CKTgmin;
gbc2=csat*evbc/vtn/vtn;
cbc=csatbc*(evbc-1)+ckt->CKTgmin*vbc;
gbc=csatbc*evbc/vtn+ckt->CKTgmin;
gbc2=csatbc*evbc/vtn/vtn;
gbc3=gbc2/vtn;
if (c4 == 0) {
cbcn=0;
@ -272,7 +273,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt)
gbcn3=gbcn2/vtc;
}
} else {
gbc = -csat/vbc+ckt->CKTgmin;
gbc = -csatbc/vbc+ckt->CKTgmin;
gbc2=gbc3=0;
cbc = gbc*vbc;
gbcn = -c4/vbc;

21
src/spicelib/devices/bjt/bjtload.c

@ -53,7 +53,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
double geqsub;
double ceqsub;
double cex;
double csat;
double csatbe, csatbc;
double csubsat;
double ctot;
double czbc;
@ -172,7 +172,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt)
/*
* dc model paramters
*/
csat=here->BJTtSatCur*here->BJTarea;
csatbe=here->BJTBEtSatCur*here->BJTarea;
csatbc=here->BJTBCtSatCur*here->BJTarea;
csubsat=here->BJTtSubSatCur*here->BJTarea;
rbpr=here->BJTtminBaseResist/here->BJTarea;
rbpi=here->BJTtbaseResist/here->BJTarea-rbpr;
@ -451,13 +452,13 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
if(vbe >= -3*vtn){
evbe=exp(vbe/vtn);
cbe=csat*(evbe-1);
gbe=csat*evbe/vtn;
cbe=csatbe*(evbe-1);
gbe=csatbe*evbe/vtn;
} else {
arg=3*vtn/(vbe*CONSTe);
arg = arg * arg * arg;
cbe = -csat*(1+arg);
gbe = csat*3*arg/vbe;
cbe = -csatbe*(1+arg);
gbe = csatbe*3*arg/vbe;
}
if (c2 == 0) {
cben=0;
@ -481,13 +482,13 @@ next1: vtn=vt*here->BJTtemissionCoeffF;
if(vbc >= -3*vtn) {
evbc=exp(vbc/vtn);
cbc=csat*(evbc-1);
gbc=csat*evbc/vtn;
cbc=csatbc*(evbc-1);
gbc=csatbc*evbc/vtn;
} else {
arg=3*vtn/(vbc*CONSTe);
arg = arg * arg * arg;
cbc = -csat*(1+arg);
gbc = csat*3*arg/vbc;
cbc = -csatbc*(1+arg);
gbc = csatbc*3*arg/vbc;
}
if (c4 == 0) {
cbcn=0;

6
src/spicelib/devices/bjt/bjtmask.c

@ -42,6 +42,12 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value)
case BJT_MOD_IS:
value->rValue = here->BJTsatCur;
return(OK);
case BJT_MOD_IBE:
value->rValue = here->BJTBEsatCur;
return(OK);
case BJT_MOD_IBC:
value->rValue = here->BJTBCsatCur;
return(OK);
case BJT_MOD_BF:
value->rValue = here->BJTbetaF;
return(OK);

8
src/spicelib/devices/bjt/bjtmpar.c

@ -46,6 +46,14 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel)
mods->BJTsatCur = value->rValue;
mods->BJTsatCurGiven = TRUE;
break;
case BJT_MOD_IBE:
mods->BJTBEsatCur = value->rValue;
mods->BJTBEsatCurGiven = TRUE;
break;
case BJT_MOD_IBC:
mods->BJTBCsatCur = value->rValue;
mods->BJTBCsatCurGiven = TRUE;
break;
case BJT_MOD_BF:
mods->BJTbetaF = value->rValue;
mods->BJTbetaFGiven = TRUE;

19
src/spicelib/devices/bjt/bjtsetup.c

@ -47,6 +47,12 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
if(!model->BJTsatCurGiven) {
model->BJTsatCur = 1e-16;
}
if(!model->BJTBEsatCurGiven) {
model->BJTBEsatCur = model->BJTsatCur;
}
if(!model->BJTBCsatCurGiven) {
model->BJTBCsatCur = model->BJTsatCur;
}
if(!model->BJTbetaFGiven) {
model->BJTbetaF = 100;
}
@ -396,19 +402,6 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
model->BJTteMax = 1e99;
}
/*
* COMPATABILITY WARNING!
* special note: for backward compatability to much older models, spice 2G
* implemented a special case which checked if B-E leakage saturation
* current was >1, then it was instead a the B-E leakage saturation current
* divided by IS, and multiplied it by IS at this point. This was not
* handled correctly in the 2G code, and there is some question on its
* reasonability, since it is also undocumented, so it has been left out
* here. It could easily be added with 1 line. (The same applies to the B-C
* leakage saturation current). TQ 6/29/84
*/
/* loop through all the instances of the model */
for (here = BJTinstances(model); here != NULL ;
here=BJTnextInstance(here)) {

8
src/spicelib/devices/bjt/bjttemp.c

@ -146,6 +146,14 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt)
if ((model->BJTtlev == 0) || (model->BJTtlev == 1)) {
factor = exp(factlog);
here->BJTtSatCur = model->BJTsatCur * factor;
if (model->BJTBEsatCurGiven) {
factor = exp(factlog / model->BJTemissionCoeffF);
here->BJTBEtSatCur = model->BJTBEsatCur * factor;
}
if (model->BJTBCsatCurGiven) {
factor = exp(factlog / model->BJTemissionCoeffR);
here->BJTBCtSatCur = model->BJTBCsatCur * factor;
}
if (model->BJTsubSatCurGiven)
here->BJTtSubSatCur = model->BJTsubSatCur * factor;
} else if (model->BJTtlev == 3) {

Loading…
Cancel
Save