📄 diotemp.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Thomas L. Quarles**********/ /* perform the temperature update to the diode */#include "spice.h"#include <stdio.h>#include "util.h"#include "cktdefs.h"#include "diodefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"intDIOtemp(inModel,ckt) GENmodel *inModel; register CKTcircuit *ckt;{ register DIOmodel *model = (DIOmodel*)inModel; double xfc; double vte; double cbv; double xbv; double xcbv; double tol; double vt; double vtnom; register DIOinstance *here; register int iter; char *emsg; /* loop through all the diode models */ for( ; model != NULL; model = model->DIOnextModel ) { if(!model->DIOnomTempGiven) { model->DIOnomTemp = ckt->CKTnomTemp; } vtnom = CONSTKoverQ * model->DIOnomTemp; /* limit grading coeff to max of .9 */ if(model->DIOgradingCoeff>.9) { (*(SPfrontEnd->IFerror))(ERR_WARNING, "%s: grading coefficient too large, limited to 0.9", &(model->DIOmodName)); model->DIOgradingCoeff=.9; } /* limit activation energy to min of .1 */ if(model->DIOactivationEnergy<.1) { (*(SPfrontEnd->IFerror))(ERR_WARNING, "%s: activation energy too small, limited to 0.1", &(model->DIOmodName)); model->DIOactivationEnergy=.1; } /* limit depletion cap coeff to max of .95 */ if(model->DIOdepletionCapCoeff>.95) { (*(SPfrontEnd->IFerror))(ERR_WARNING, "%s: coefficient Fc too large, limited to 0.95", &(model->DIOmodName)); model->DIOdepletionCapCoeff=.95; } if(!model->DIOresistGiven || model->DIOresist==0) { model->DIOconductance = 0; } else { model->DIOconductance = 1/model->DIOresist; } xfc=log(1-model->DIOdepletionCapCoeff); for(here=model->DIOinstances;here;here=here->DIOnextInstance) { double egfet1,arg1,fact1,pbfact1,pbo,gmaold; double fact2,pbfact,arg,egfet,gmanew; /* loop through all the instances */ if(!here->DIOtempGiven) here->DIOtemp = ckt->CKTtemp; vt = CONSTKoverQ * here->DIOtemp; /* this part gets really ugly - I won't even try to * explain these equations */ fact2 = here->DIOtemp/REFTEMP; egfet = 1.16-(7.02e-4*here->DIOtemp*here->DIOtemp)/ (here->DIOtemp+1108); arg = -egfet/(2*CONSTboltz*here->DIOtemp) + 1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); pbfact = -2*vt*(1.5*log(fact2)+CHARGE*arg); egfet1 = 1.16 - (7.02e-4*model->DIOnomTemp*model->DIOnomTemp)/ (model->DIOnomTemp+1108); arg1 = -egfet1/(CONSTboltz*2*model->DIOnomTemp) + 1.1150877/(2*CONSTboltz*REFTEMP); fact1 = model->DIOnomTemp/REFTEMP; pbfact1 = -2 * vtnom*(1.5*log(fact1)+CHARGE*arg1); pbo = (model->DIOjunctionPot-pbfact1)/fact1; gmaold = (model->DIOjunctionPot -pbo)/pbo; here->DIOtJctCap = model->DIOjunctionCap/ (1+model->DIOgradingCoeff* (400e-6*(model->DIOnomTemp-REFTEMP)-gmaold) ); here->DIOtJctPot = pbfact+fact2*pbo; gmanew = (here->DIOtJctPot-pbo)/pbo; here->DIOtJctCap *= 1+model->DIOgradingCoeff* (400e-6*(here->DIOtemp-REFTEMP)-gmanew); here->DIOtSatCur = model->DIOsatCur * exp( ((here->DIOtemp/model->DIOnomTemp)-1) * model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) + model->DIOsaturationCurrentExp/model->DIOemissionCoeff* log(here->DIOtemp/model->DIOnomTemp) ); /* the defintion of f1, just recompute after temperature adjusting * all the variables used in it */ here->DIOtF1=here->DIOtJctPot* (1-exp((1-model->DIOgradingCoeff)*xfc))/ (1-model->DIOgradingCoeff); /* same for Depletion Capacitance */ here->DIOtDepCap=model->DIOdepletionCapCoeff* here->DIOtJctPot; /* and Vcrit */ vte=model->DIOemissionCoeff*vt; here->DIOtVcrit=vte*log(vte/(CONSTroot2*here->DIOtSatCur)); /* and now to copute the breakdown voltage, again, using * temperature adjusted basic parameters */ if (model->DIObreakdownVoltageGiven){ cbv=model->DIObreakdownCurrent; if (cbv < here->DIOtSatCur*model->DIObreakdownVoltage/vt){ cbv=here->DIOtSatCur*model->DIObreakdownVoltage/vt; emsg = MALLOC(100); if(emsg == (char *)NULL) return(E_NOMEM); (void)sprintf(emsg, "%%s: breakdown current increased to %g to resolve incompatability", cbv); (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&(here->DIOname)); FREE(emsg); (*(SPfrontEnd->IFerror))(ERR_WARNING, "with specified saturation current",(IFuid*)NULL); xbv=model->DIObreakdownVoltage; } else { tol=ckt->CKTreltol*cbv; xbv=model->DIObreakdownVoltage-vt*log(1+cbv/ here->DIOtSatCur); iter=0; for(iter=0 ; iter < 25 ; iter++) { xbv=model->DIObreakdownVoltage-vt*log(cbv/ here->DIOtSatCur+1-xbv/vt); xcbv=here->DIOtSatCur*(exp((model->DIObreakdownVoltage -xbv)/vt)-1+xbv/vt); if (FABS(xcbv-cbv) <= tol) goto matched; } emsg = MALLOC(100); if(emsg == (char *)NULL) return(E_NOMEM); (void)sprintf(emsg,"%%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g", xbv,xcbv); (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&here->DIOname); FREE(emsg); } matched: here->DIOtBrkdwnV = xbv; } } model->DIOf2=exp((1+model->DIOgradingCoeff)*xfc); model->DIOf3=1-model->DIOdepletionCapCoeff* (1+model->DIOgradingCoeff); } return(OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -