vdmos with soft recovery body diode

This commit is contained in:
dwarning 2026-03-18 20:49:54 +01:00
parent f7ef88b637
commit e590b456a8
10 changed files with 215 additions and 16 deletions

View File

@ -31,6 +31,7 @@ IFparm VDMOSpTable[] = { /* parameters */
OP( "cgd", VDMOS_CAPGD, IF_REAL, "Gate-Drain capacitance"), OP( "cgd", VDMOS_CAPGD, IF_REAL, "Gate-Drain capacitance"),
OP( "cds", VDMOS_CAPDS, IF_REAL, "Drain-Source capacitance"), OP( "cds", VDMOS_CAPDS, IF_REAL, "Drain-Source capacitance"),
OP( "idio", VDMOS_CDIO, IF_REAL, "Body diode current"), OP( "idio", VDMOS_CDIO, IF_REAL, "Body diode current"),
OP( "qdio", VDMOS_QDIO, IF_REAL, "Body diode charge"),
OPU( "dnode", VDMOS_DNODE, IF_INTEGER, "Number of the drain node "), OPU( "dnode", VDMOS_DNODE, IF_INTEGER, "Number of the drain node "),
OPU( "gnode", VDMOS_GNODE, IF_INTEGER, "Number of the gate node "), OPU( "gnode", VDMOS_GNODE, IF_INTEGER, "Number of the gate node "),
@ -115,6 +116,8 @@ IFparm VDMOSmPTable[] = { /* model parameters */
IOP("xti", VDIO_MOD_XTI, IF_REAL, "Body diode saturation current temperature exponent"), IOP("xti", VDIO_MOD_XTI, IF_REAL, "Body diode saturation current temperature exponent"),
IOP("is", VDIO_MOD_IS, IF_REAL, "Body diode saturation current"), IOP("is", VDIO_MOD_IS, IF_REAL, "Body diode saturation current"),
IOP("vj", VDIO_MOD_VJ, IF_REAL, "Body diode junction potential"), IOP("vj", VDIO_MOD_VJ, IF_REAL, "Body diode junction potential"),
IOP("vp", VDIO_MOD_VP, IF_REAL, "Soft reverse recovery parameter"),
/* body diode capacitance (e.g. source-drain capacitance) */ /* body diode capacitance (e.g. source-drain capacitance) */
IOPA("cjo", VDIO_MOD_CJ, IF_REAL, "Zero-bias body diode junction capacitance"), IOPA("cjo", VDIO_MOD_CJ, IF_REAL, "Zero-bias body diode junction capacitance"),

View File

@ -156,6 +156,20 @@ VDMOSacLoad(GENmodel *inModel, CKTcircuit *ckt)
*(here->VDMOSSPtempPtr + 1) += xcsT; *(here->VDMOSSPtempPtr + 1) += xcsT;
*(here->VDMOSGPtempPtr + 1) += xcgT; *(here->VDMOSGPtempPtr + 1) += xcgT;
} }
if ((here->VDIOqpNode > 0) && (model->VDIOsoftRevRecParam!=0) && (here->VDIOtTransitTime!=0)) {
/* QP subcircuit */
double gdres= *(ckt->CKTstate0 + here->VDIOresConduct);
double fac = here->VDIOtTransitTime / model->VDIOsoftRevRecParam;
double dcrrdvd = fac * gdres;
*(here->VDIOqpQpPtr) += 1/model->VDIOsoftRevRecParam;
*(here->VDIOqpQpPtr + 1) += here->VDIOtTransitTime * ckt->CKTomega;
*(here->VDIOqpPosPrimePtr) += -dcrrdvd;
*(here->VDIOqpNegPtr) += dcrrdvd;
/* Gain of VCVS (1-vp)/tau * j*omega*tau = (1-vp) * j*omega */
double xgain = (1 - model->VDIOsoftRevRecParam) * ckt->CKTomega;
*(here->VDIOposPrimeQpPtr + 1) += xgain;
*(here->VDIOnegQpPtr + 1) += -xgain;
}
} }
} }
return(OK); return(OK);

View File

@ -118,6 +118,13 @@ VDMOSask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
return(OK); return(OK);
case VDMOS_CDIO: case VDMOS_CDIO:
value->rValue = *(ckt->CKTstate0 + here->VDIOcurrent); value->rValue = *(ckt->CKTstate0 + here->VDIOcurrent);
if ((here->VDIOqpNode > 0) && (here->VDIOtTransitTime!=0))
value->rValue += here->VDIOqpGain * *(ckt->CKTstate0 + here->VDIOcqcsr);
return(OK);
case VDMOS_QDIO:
value->rValue = *(ckt->CKTstate0+here->VDIOcapCharge);
if ((here->VDIOqpNode > 0) && (here->VDIOtTransitTime!=0))
value->rValue += *(ckt->CKTstate0 + here->VDIOsrcapCharge);
return(OK); return(OK);
case VDMOS_CG : case VDMOS_CG :
if (ckt->CKTcurrentAnalysis & DOING_AC) { if (ckt->CKTcurrentAnalysis & DOING_AC) {

View File

@ -80,6 +80,14 @@ VDMOSbindCSC (GENmodel *inModel, CKTcircuit *ckt)
CREATE_KLU_BINDING_TABLE(VDMOSDevTtpPtr, VDMOSDevTtpBinding, VDMOSvdevTbranch, VDMOStNodePrime); CREATE_KLU_BINDING_TABLE(VDMOSDevTtpPtr, VDMOSDevTtpBinding, VDMOSvdevTbranch, VDMOStNodePrime);
CREATE_KLU_BINDING_TABLE(VDMOSTpdevTPtr, VDMOSTpdevTBinding, VDMOStNodePrime, VDMOSvdevTbranch); CREATE_KLU_BINDING_TABLE(VDMOSTpdevTPtr, VDMOSTpdevTBinding, VDMOStNodePrime, VDMOSvdevTbranch);
} }
/* rev-rec */
if (model->VDIOsoftRevRecParamGiven && model->VDIOsoftRevRecParam!=0 && model->VDIOtransitTime!=0) {
CREATE_KLU_BINDING_TABLE(VDIOqpQpPtr , VDIOqpQpBinding , VDIOqpNode, VDIOqpNode);
CREATE_KLU_BINDING_TABLE(VDIOqpPosPrimePtr, VDIOqpPosPrimeBinding, VDIOqpNode, VDIOposPrimeNode);
CREATE_KLU_BINDING_TABLE(VDIOqpNegPtr , VDIOqpNegBinding , VDIOqpNode, VDMOSdNode);
CREATE_KLU_BINDING_TABLE(VDIOposPrimeQpPtr, VDIOposPrimeQpBinding, VDIOposPrimeNode, VDIOqpNode);
CREATE_KLU_BINDING_TABLE(VDIOnegQpPtr , VDIOnegQpBinding , VDMOSdNode, VDIOqpNode);
}
} }
} }
@ -155,6 +163,14 @@ VDMOSbindCSCComplex (GENmodel *inModel, CKTcircuit *ckt)
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDMOSDevTtpPtr, VDMOSDevTtpBinding, VDMOSvdevTbranch, VDMOStNodePrime); CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDMOSDevTtpPtr, VDMOSDevTtpBinding, VDMOSvdevTbranch, VDMOStNodePrime);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDMOSTpdevTPtr, VDMOSTpdevTBinding, VDMOStNodePrime, VDMOSvdevTbranch); CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDMOSTpdevTPtr, VDMOSTpdevTBinding, VDMOStNodePrime, VDMOSvdevTbranch);
} }
/* rev-rec */
if (model->VDIOsoftRevRecParamGiven && model->VDIOsoftRevRecParam!=0 && model->VDIOtransitTime!=0) {
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDIOqpQpPtr , VDIOqpQpBinding , VDIOqpNode, VDIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDIOqpPosPrimePtr, VDIOqpPosPrimeBinding, VDIOqpNode, VDIOposPrimeNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDIOqpNegPtr , VDIOqpNegBinding , VDIOqpNode, VDMOSdNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDIOposPrimeQpPtr, VDIOposPrimeQpBinding, VDIOposPrimeNode, VDIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(VDIOnegQpPtr , VDIOnegQpBinding , VDMOSdNode, VDIOqpNode);
}
} }
} }
@ -230,6 +246,14 @@ VDMOSbindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt)
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDMOSDevTtpPtr, VDMOSDevTtpBinding, VDMOSvdevTbranch, VDMOStNodePrime); CONVERT_KLU_BINDING_TABLE_TO_REAL(VDMOSDevTtpPtr, VDMOSDevTtpBinding, VDMOSvdevTbranch, VDMOStNodePrime);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDMOSTpdevTPtr, VDMOSTpdevTBinding, VDMOStNodePrime, VDMOSvdevTbranch); CONVERT_KLU_BINDING_TABLE_TO_REAL(VDMOSTpdevTPtr, VDMOSTpdevTBinding, VDMOStNodePrime, VDMOSvdevTbranch);
} }
/* rev-rec */
if (model->VDIOsoftRevRecParamGiven && model->VDIOsoftRevRecParam!=0 && model->VDIOtransitTime!=0) {
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDIOqpQpPtr , VDIOqpQpBinding , VDIOqpNode, VDIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDIOqpPosPrimePtr, VDIOqpPosPrimeBinding, VDIOqpNode, VDIOposPrimeNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDIOqpNegPtr , VDIOqpNegBinding , VDIOqpNode, VDMOSdNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDIOposPrimeQpPtr, VDIOposPrimeQpBinding, VDIOposPrimeNode, VDIOqpNode);
CONVERT_KLU_BINDING_TABLE_TO_REAL(VDIOnegQpPtr , VDIOnegQpBinding , VDMOSdNode, VDIOqpNode);
}
} }
} }

View File

@ -49,6 +49,7 @@ typedef struct sVDMOSinstance {
int VDMOSgNodePrime; /* number of the internal gate node of the mosfet */ int VDMOSgNodePrime; /* number of the internal gate node of the mosfet */
int VDMOStNodePrime; /* number of the internal temp node between voltage source and Rthca */ int VDMOStNodePrime; /* number of the internal temp node between voltage source and Rthca */
int VDIOposPrimeNode; /* number of the internal node of the body diode */ int VDIOposPrimeNode; /* number of the internal node of the body diode */
int VDIOqpNode; /* number of soft recovery charge node */
int VDMOSvdevTbranch; /* equation number of branch equation added for cktTemp source */ int VDMOSvdevTbranch; /* equation number of branch equation added for cktTemp source */
@ -97,6 +98,9 @@ typedef struct sVDMOSinstance {
double VDIOtF2; double VDIOtF2;
double VDIOtF3; double VDIOtF3;
/* rev-rec */
double VDIOqpGain;/* converts iterated diffcharge current */
double VDMOSTempSH; /* for portability of SH temp to noise analysis */ double VDMOSTempSH; /* for portability of SH temp to noise analysis */
double VDMOSgmT; double VDMOSgmT;
@ -216,6 +220,13 @@ typedef struct sVDMOSinstance {
(source node, diode prime node) */ (source node, diode prime node) */
double *VDIORPsPtr; /* pointer to sparse matrix element at double *VDIORPsPtr; /* pointer to sparse matrix element at
(diode prime node, source node) */ (diode prime node, source node) */
/* rev-rec */
double *VDIOqpQpPtr;
double *VDIOqpPosPrimePtr;
double *VDIOqpNegPtr;
double *VDIOposPrimeQpPtr;
double *VDIOnegQpPtr;
/* self heating */ /* self heating */
double *VDMOSTemptempPtr; /* Transistor thermal contribution */ double *VDMOSTemptempPtr; /* Transistor thermal contribution */
double *VDMOSTempdpPtr; double *VDMOSTempdpPtr;
@ -290,6 +301,12 @@ typedef struct sVDMOSinstance {
BindElement *VDMOSDevTdevTBinding ; BindElement *VDMOSDevTdevTBinding ;
BindElement *VDMOSDevTtpBinding ; BindElement *VDMOSDevTtpBinding ;
BindElement *VDMOSTpdevTBinding ; BindElement *VDMOSTpdevTBinding ;
/* rev-rec */
BindElement *VDIOqpQpBinding;
BindElement *VDIOqpPosPrimeBinding;
BindElement *VDIOqpNegBinding;
BindElement *VDIOposPrimeQpBinding;
BindElement *VDIOnegQpBinding;
#endif #endif
} VDMOSinstance ; } VDMOSinstance ;
@ -319,8 +336,16 @@ typedef struct sVDMOSinstance {
#define VDIOdIdio_dT VDMOSstates+ 17 #define VDIOdIdio_dT VDMOSstates+ 17
#define VDMOSnumStates 18 /* rev-rec */
#define VDIOsrcapCharge VDMOSstates+18
#define VDIOsrcapCurrent VDMOSstates+19
#define VDIOqp VDMOSstates+20
#define VDIOresCurrent VDMOSstates+21
#define VDIOresConduct VDMOSstates+22
#define VDIOcqcsr VDMOSstates+23
#define VDIOgqcsr VDMOSstates+24
#define VDMOSnumStates 25
/* per model data */ /* per model data */
@ -385,6 +410,7 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
double VDIOgradCoeffTemp2; double VDIOgradCoeffTemp2;
double VDIOtrb1; double VDIOtrb1;
double VDIOtrb2; double VDIOtrb2;
double VDIOsoftRevRecParam; /* Soft reverse recovery parameter */
double VDMOStcvth; double VDMOStcvth;
double VDMOSrthjc; double VDMOSrthjc;
@ -482,6 +508,7 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
unsigned VDMOSid_maxGiven :1; unsigned VDMOSid_maxGiven :1;
unsigned VDMOSidr_maxGiven :1; unsigned VDMOSidr_maxGiven :1;
unsigned VDMOSderatingGiven :1; unsigned VDMOSderatingGiven :1;
unsigned VDIOsoftRevRecParamGiven : 1;
} VDMOSmodel; } VDMOSmodel;
#ifndef NMOS #ifndef NMOS
@ -546,6 +573,7 @@ enum {
VDIO_MOD_XTI, VDIO_MOD_XTI,
VDIO_MOD_TRB1, VDIO_MOD_TRB1,
VDIO_MOD_TRB2, VDIO_MOD_TRB2,
VDIO_MOD_VP,
VDMOS_MOD_TCVTH, VDMOS_MOD_TCVTH,
VDMOS_MOD_RTHJC, VDMOS_MOD_RTHJC,
VDMOS_MOD_RTHCA, VDMOS_MOD_RTHCA,
@ -599,6 +627,7 @@ enum {
VDMOS_QGD, VDMOS_QGD,
VDMOS_CQGD, VDMOS_CQGD,
VDMOS_CDIO, VDMOS_CDIO,
VDMOS_QDIO,
VDMOS_SOURCERESIST, VDMOS_SOURCERESIST,
VDMOS_DRAINRESIST, VDMOS_DRAINRESIST,
}; };

View File

@ -710,11 +710,17 @@ bypass:
double Ith=0.0, dIth_dT=0.0; double Ith=0.0, dIth_dT=0.0;
double dIdio_dT=0.0, dIth_dVdio=0.0; double dIdio_dT=0.0, dIth_dVdio=0.0;
double vrb=0.0, dIrb_dT=0.0, dIth_dVrb=0.0; double vrb=0.0, dIrb_dT=0.0, dIth_dVrb=0.0;
/* rev-rec */
double cdres, gdres;
double vqp;
double capsr, gqcsr, cqcsr;
#ifndef NOBYPASS #ifndef NOBYPASS
double tol; /* temporary for tolerance calculations */ double tol; /* temporary for tolerance calculations */
#endif #endif
int revrec = ((here->VDIOqpNode > 0) && (model->VDIOsoftRevRecParam!=0) && (here->VDIOtTransitTime!=0));
gbpr = here->VDIOtConductance; gbpr = here->VDIOtConductance;
vt = CONSTKoverQ * Temp; vt = CONSTKoverQ * Temp;
@ -725,13 +731,17 @@ bypass:
Check_dio = 1; Check_dio = 1;
if (ckt->CKTmode & MODEINITSMSIG) { if (ckt->CKTmode & MODEINITSMSIG) {
vd = *(ckt->CKTstate0 + here->VDIOvoltage); vd = *(ckt->CKTstate0 + here->VDIOvoltage);
vqp = *(ckt->CKTstate0 + here->VDIOqp);
} else if (ckt->CKTmode & MODEINITTRAN) { } else if (ckt->CKTmode & MODEINITTRAN) {
vd = *(ckt->CKTstate1 + here->VDIOvoltage); vd = *(ckt->CKTstate1 + here->VDIOvoltage);
vqp = *(ckt->CKTstate1 + here->VDIOqp);
} else if ((ckt->CKTmode & MODEINITJCT) && } else if ((ckt->CKTmode & MODEINITJCT) &&
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
vd = here->VDIOinitCond; vd = here->VDIOinitCond;
vqp=0;
} else if (ckt->CKTmode & MODEINITJCT) { } else if (ckt->CKTmode & MODEINITJCT) {
vd = here->VDIOtVcrit; vd = here->VDIOtVcrit;
vqp=0;
} else { } else {
#ifndef PREDICTOR #ifndef PREDICTOR
if (ckt->CKTmode & MODEINITPRED) { if (ckt->CKTmode & MODEINITPRED) {
@ -744,10 +754,20 @@ bypass:
*(ckt->CKTstate1 + here->VDIOconduct); *(ckt->CKTstate1 + here->VDIOconduct);
*(ckt->CKTstate0 + here->VDIOdIdio_dT) = *(ckt->CKTstate0 + here->VDIOdIdio_dT) =
*(ckt->CKTstate1 + here->VDIOdIdio_dT); *(ckt->CKTstate1 + here->VDIOdIdio_dT);
vqp = DEVpred(ckt,here->VDIOqp);
*(ckt->CKTstate0 + here->VDIOresCurrent) =
*(ckt->CKTstate1 + here->VDIOresCurrent);
*(ckt->CKTstate0 + here->VDIOresConduct) =
*(ckt->CKTstate1 + here->VDIOresConduct);
*(ckt->CKTstate0 + here->VDIOcqcsr) =
*(ckt->CKTstate1 + here->VDIOcqcsr);
*(ckt->CKTstate0 + here->VDIOgqcsr) =
*(ckt->CKTstate1 + here->VDIOgqcsr);
} else { } else {
#endif /* PREDICTOR */ #endif /* PREDICTOR */
vd = model->VDMOStype * (*(ckt->CKTrhsOld + here->VDIOposPrimeNode) - vd = model->VDMOStype * (*(ckt->CKTrhsOld + here->VDIOposPrimeNode) -
*(ckt->CKTrhsOld + here->VDMOSdNode)); *(ckt->CKTrhsOld + here->VDMOSdNode));
vqp = *(ckt->CKTrhsOld+here->VDIOqpNode);
#ifndef PREDICTOR #ifndef PREDICTOR
} }
#endif /* PREDICTOR */ #endif /* PREDICTOR */
@ -776,6 +796,11 @@ bypass:
cd = *(ckt->CKTstate0 + here->VDIOcurrent); cd = *(ckt->CKTstate0 + here->VDIOcurrent);
gd = *(ckt->CKTstate0 + here->VDIOconduct); gd = *(ckt->CKTstate0 + here->VDIOconduct);
dIdio_dT= *(ckt->CKTstate0 + here->VDIOdIdio_dT); dIdio_dT= *(ckt->CKTstate0 + here->VDIOdIdio_dT);
vqp= *(ckt->CKTstate0 + here->VDIOqp);
cdres= *(ckt->CKTstate0 + here->VDIOresCurrent);
gdres= *(ckt->CKTstate0 + here->VDIOresConduct);
cqcsr= *(ckt->CKTstate0 + here->VDIOcqcsr);
gqcsr= *(ckt->CKTstate0 + here->VDIOgqcsr);
goto load; goto load;
} }
} }
@ -833,6 +858,10 @@ bypass:
cd = cdb + ckt->CKTgmin*vd; cd = cdb + ckt->CKTgmin*vd;
gd = gdb + ckt->CKTgmin; gd = gdb + ckt->CKTgmin;
cdres = cd;
gdres = gd;
cqcsr = 0;
gqcsr = 0;
if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) || if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) ||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) { ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) {
@ -853,14 +882,34 @@ bypass:
(here->VDIOtGradingCoeff / (here->VDIOtJctPot + here->VDIOtJctPot))*(vd*vd - here->VDIOtDepCap*here->VDIOtDepCap)); (here->VDIOtGradingCoeff / (here->VDIOtJctPot + here->VDIOtJctPot))*(vd*vd - here->VDIOtDepCap*here->VDIOtDepCap));
deplcap = czof2*(here->VDIOtF3 + here->VDIOtGradingCoeff*vd / here->VDIOtJctPot); deplcap = czof2*(here->VDIOtF3 + here->VDIOtGradingCoeff*vd / here->VDIOtJctPot);
} }
diffcharge = here->VDIOtTransitTime*cdb;
*(ckt->CKTstate0 + here->VDIOcapCharge) =
diffcharge + deplcharge;
diffcap = here->VDIOtTransitTime*gdb; if (revrec) {
capd = diffcap + deplcap; /*
soft recovery with TT!=0
add only depletion capacitance.
*/
*(ckt->CKTstate0 + here->VDIOcapCharge) = deplcharge;
here->VDIOcap = capd; capd = deplcap;
here->VDIOcap = capd;
/*
DIOcap is now equal only to depletion capacitance + overlap capacitance.
Diffusion capacitance is modelled via Qp so there is no clear way to define it.
Now prepare the charge for the capacitor connected to the QP node
*/
*(ckt->CKTstate0 + here->VDIOsrcapCharge) = here->VDIOtTransitTime * vqp;
capsr = here->VDIOtTransitTime;
} else {
/* no soft recovery of soft recovery with TT=0 (i.e. no soft recovery due to TT=0) */
diffcharge = here->VDIOtTransitTime*cdb;
diffcap = here->VDIOtTransitTime*gdb;
*(ckt->CKTstate0 + here->VDIOcapCharge) = diffcharge + deplcharge;
capd = diffcap + deplcap;
here->VDIOcap = capd;
*(ckt->CKTstate0 + here->VDIOsrcapCharge) = 0;
capsr = 0;
}
/* /*
* store small-signal parameters * store small-signal parameters
@ -869,6 +918,7 @@ bypass:
(!(ckt->CKTmode & MODEUIC))) { (!(ckt->CKTmode & MODEUIC))) {
if (ckt->CKTmode & MODEINITSMSIG) { if (ckt->CKTmode & MODEINITSMSIG) {
*(ckt->CKTstate0 + here->VDIOcapCurrent) = capd; *(ckt->CKTstate0 + here->VDIOcapCurrent) = capd;
*(ckt->CKTstate0 + here->VDIOresConduct) = gdres;
continue; continue;
} }
@ -889,6 +939,21 @@ bypass:
*(ckt->CKTstate1 + here->VDIOcapCurrent) = *(ckt->CKTstate1 + here->VDIOcapCurrent) =
*(ckt->CKTstate0 + here->VDIOcapCurrent); *(ckt->CKTstate0 + here->VDIOcapCurrent);
} }
if (revrec) {
/* soft recovery subcircuit */
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->VDIOsrcapCharge) =
*(ckt->CKTstate0 + here->VDIOsrcapCharge);
}
error = NIintegrate(ckt,&geq,&ceq,capsr,here->VDIOsrcapCharge);
if(error) return(error);
gqcsr = geq;
cqcsr = *(ckt->CKTstate0 + here->VDIOsrcapCurrent);
if (ckt->CKTmode & MODEINITTRAN) {
*(ckt->CKTstate1 + here->VDIOsrcapCurrent) =
*(ckt->CKTstate0 + here->VDIOsrcapCurrent);
}
}
} }
} }
@ -905,6 +970,11 @@ bypass:
*(ckt->CKTstate0 + here->VDIOcurrent) = cd; *(ckt->CKTstate0 + here->VDIOcurrent) = cd;
*(ckt->CKTstate0 + here->VDIOconduct) = gd; *(ckt->CKTstate0 + here->VDIOconduct) = gd;
*(ckt->CKTstate0 + here->VDIOdIdio_dT) = dIdio_dT; *(ckt->CKTstate0 + here->VDIOdIdio_dT) = dIdio_dT;
*(ckt->CKTstate0 + here->VDIOqp) = vqp;
*(ckt->CKTstate0 + here->VDIOresCurrent) = cdres;
*(ckt->CKTstate0 + here->VDIOresConduct) = gdres;
*(ckt->CKTstate0 + here->VDIOcqcsr) = cqcsr;
*(ckt->CKTstate0 + here->VDIOgqcsr) = gqcsr;
#ifndef NOBYPASS #ifndef NOBYPASS
load: load:
@ -926,14 +996,10 @@ load:
/* /*
* load current vector * load current vector
*/ */
cdeq = cd - gd*vd; cdeq = model->VDMOStype * (cd - gd*vd);
if (model->VDMOStype == 1) { *(ckt->CKTrhs + here->VDMOSdNode) += cdeq;
*(ckt->CKTrhs + here->VDMOSdNode) += cdeq; *(ckt->CKTrhs + here->VDIOposPrimeNode) -= cdeq;
*(ckt->CKTrhs + here->VDIOposPrimeNode) -= cdeq;
} else {
*(ckt->CKTrhs + here->VDMOSdNode) -= cdeq;
*(ckt->CKTrhs + here->VDIOposPrimeNode) += cdeq;
}
if (selfheat) { if (selfheat) {
*(ckt->CKTrhs + here->VDIOposPrimeNode) += dIdio_dT*delTemp - dIrb_dT*delTemp; *(ckt->CKTrhs + here->VDIOposPrimeNode) += dIdio_dT*delTemp - dIrb_dT*delTemp;
*(ckt->CKTrhs + here->VDMOSdNode) += -dIdio_dT*delTemp; *(ckt->CKTrhs + here->VDMOSdNode) += -dIdio_dT*delTemp;
@ -959,6 +1025,26 @@ load:
(*(here->VDMOSStempPtr) += dIrb_dT); (*(here->VDMOSStempPtr) += dIrb_dT);
(*(here->VDMOSDtempPtr) += -dIdio_dT); (*(here->VDMOSDtempPtr) += -dIdio_dT);
} }
if (revrec) {
/* QP subcircuit */
double fac = here->VDIOtTransitTime / model->VDIOsoftRevRecParam;
double dcrrdvd = fac*gdres;
double ceqrr = -fac*cdres + cqcsr + dcrrdvd*vd - gqcsr*vqp;
double grr = 1/model->VDIOsoftRevRecParam;
*(ckt->CKTrhs + here->VDIOqpNode) -= ceqrr;
*(here->VDIOqpQpPtr) += grr + gqcsr;
*(here->VDIOqpPosPrimePtr) += -dcrrdvd;
*(here->VDIOqpNegPtr) += dcrrdvd;
/* Contribution to diode current */
here->VDIOqpGain = (1 - model->VDIOsoftRevRecParam) / here->VDIOtTransitTime;
/* Linear contribution -(1-vp)/tau*ddt(Qp) */
double geqrrd = here->VDIOqpGain*gqcsr;
double ceqrrd = model->VDMOStype * (here->VDIOqpGain*cqcsr - geqrrd*vqp);
*(ckt->CKTrhs + here->VDIOposPrimeNode) += -ceqrrd;
*(ckt->CKTrhs + here->VDMOSdNode) += ceqrrd;
*(here->VDIOposPrimeQpPtr) += geqrrd;
*(here->VDIOnegQpPtr) += -geqrrd;
}
} }
} }
return(OK); return(OK);

View File

@ -182,6 +182,9 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case VDMOS_MOD_TKSUBTHRES2: case VDMOS_MOD_TKSUBTHRES2:
value->rValue = model->VDMOStksubthres2; value->rValue = model->VDMOStksubthres2;
return(OK); return(OK);
case VDIO_MOD_VP:
value->rValue = model->VDIOsoftRevRecParam;
return(OK);
/* SOA */ /* SOA */
case VDMOS_MOD_VGS_MAX: case VDMOS_MOD_VGS_MAX:
value->rValue = model->VDMOSvgsMax; value->rValue = model->VDMOSvgsMax;

View File

@ -166,6 +166,10 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
model->VDIOtranTimeTemp1 = 0; model->VDIOtranTimeTemp1 = 0;
model->VDIOtranTimeTemp2 = 0; model->VDIOtranTimeTemp2 = 0;
break; break;
case VDIO_MOD_VP:
model->VDIOsoftRevRecParam = value->rValue;
model->VDIOsoftRevRecParamGiven = TRUE;
break;
case VDIO_MOD_EG: case VDIO_MOD_EG:
model->VDIOeg = value->rValue; model->VDIOeg = value->rValue;
model->VDIOegGiven = TRUE; model->VDIOegGiven = TRUE;

View File

@ -251,6 +251,10 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
if (model->VDIOjctSatCur < ckt->CKTepsmin) if (model->VDIOjctSatCur < ckt->CKTepsmin)
model->VDIOjctSatCur = ckt->CKTepsmin; model->VDIOjctSatCur = ckt->CKTepsmin;
if (!model->VDIOsoftRevRecParamGiven) {
model->VDIOsoftRevRecParam = 0.0;
}
/* loop through all the instances of the model */ /* loop through all the instances of the model */
for (here = VDMOSinstances(model); here != NULL; for (here = VDMOSinstances(model); here != NULL;
here = VDMOSnextInstance(here)) { here = VDMOSnextInstance(here)) {
@ -431,6 +435,16 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
here->VDMOStcaseNode = 0; here->VDMOStcaseNode = 0;
} }
/* rev-rec */
if (model->VDIOsoftRevRecParamGiven && model->VDIOsoftRevRecParam!=0 && model->VDIOtransitTime!=0) {
if(here->VDIOqpNode == 0) {
error = CKTmkVolt(ckt, &tmp, here->VDMOSname, "qp");
if(error) return(error);
here->VDIOqpNode = tmp->number;
}
} else {
here->VDIOqpNode = 0;
}
/* macro to make elements with built in test for out of memory */ /* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \ #define TSTALLOC(ptr,first,second) \
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
@ -487,11 +501,20 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
TSTALLOC(VDMOSTemptcasePtr, VDMOStempNode, VDMOStcaseNode); TSTALLOC(VDMOSTemptcasePtr, VDMOStempNode, VDMOStcaseNode);
TSTALLOC(VDMOSTptpPtr, VDMOStNodePrime, VDMOStNodePrime); /* Rthca between tcase and Vsrc */ TSTALLOC(VDMOSTptpPtr, VDMOStNodePrime, VDMOStNodePrime); /* Rthca between tcase and Vsrc */
TSTALLOC(VDMOSTptcasePtr, VDMOStNodePrime, VDMOStcaseNode); TSTALLOC(VDMOSTptcasePtr, VDMOStNodePrime, VDMOStcaseNode);
TSTALLOC(VDMOSTcasetpPtr, VDMOStcaseNode, VDMOStNodePrime); TSTALLOC(VDMOSTcasetpPtr, VDMOStcaseNode, VDMOStNodePrime);
TSTALLOC(VDMOSDevTdevTPtr, VDMOSvdevTbranch, VDMOSvdevTbranch); /* Vsrc=cktTemp to gnd */ TSTALLOC(VDMOSDevTdevTPtr, VDMOSvdevTbranch, VDMOSvdevTbranch); /* Vsrc=cktTemp to gnd */
TSTALLOC(VDMOSDevTtpPtr, VDMOSvdevTbranch, VDMOStNodePrime); TSTALLOC(VDMOSDevTtpPtr, VDMOSvdevTbranch, VDMOStNodePrime);
TSTALLOC(VDMOSTpdevTPtr, VDMOStNodePrime, VDMOSvdevTbranch); TSTALLOC(VDMOSTpdevTPtr, VDMOStNodePrime, VDMOSvdevTbranch);
} }
/* rev-rec */
if (model->VDIOsoftRevRecParamGiven && model->VDIOsoftRevRecParam!=0 && model->VDIOtransitTime!=0) {
TSTALLOC(VDIOqpQpPtr , VDIOqpNode, VDIOqpNode);
TSTALLOC(VDIOqpPosPrimePtr, VDIOqpNode, VDIOposPrimeNode);
TSTALLOC(VDIOqpNegPtr , VDIOqpNode, VDMOSdNode);
TSTALLOC(VDIOposPrimeQpPtr, VDIOposPrimeNode, VDIOqpNode);
TSTALLOC(VDIOnegQpPtr, VDMOSdNode, VDIOqpNode);
}
} }
} }
return(OK); return(OK);
@ -538,6 +561,10 @@ VDMOSunsetup(GENmodel *inModel, CKTcircuit *ckt)
here->VDMOSvdevTbranch = 0; here->VDMOSvdevTbranch = 0;
} }
/* rev-rec */
if (here->VDIOqpNode > 0)
CKTdltNNum(ckt, here->VDIOqpNode);
here->VDIOqpNode = 0;
} }
} }
return OK; return OK;

View File

@ -24,6 +24,8 @@ VDMOStrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
CKTterr(here->VDMOSqgs,ckt,timeStep); CKTterr(here->VDMOSqgs,ckt,timeStep);
CKTterr(here->VDMOSqgd,ckt,timeStep); CKTterr(here->VDMOSqgd,ckt,timeStep);
CKTterr(here->VDIOcapCharge,ckt,timeStep); CKTterr(here->VDIOcapCharge,ckt,timeStep);
if (model->VDIOsoftRevRecParam!=0 && here->VDIOtTransitTime!=0)
CKTterr(here->VDIOsrcapCharge,ckt,timeStep);
} }
} }
return(OK); return(OK);