Browse Source

Revise the SOA and add new parameters:

pd_max id_max idr_max te_max rth_ext derating
rth_ext is currently not used
pre-master-46
Holger Vogt 5 years ago
parent
commit
18478380ad
  1. 4
      src/spicelib/devices/vdmos/vdmos.c
  2. 18
      src/spicelib/devices/vdmos/vdmosdefs.h
  3. 20
      src/spicelib/devices/vdmos/vdmosmask.c
  4. 24
      src/spicelib/devices/vdmos/vdmosmpar.c
  5. 18
      src/spicelib/devices/vdmos/vdmosset.c
  6. 105
      src/spicelib/devices/vdmos/vdmossoachk.c

4
src/spicelib/devices/vdmos/vdmos.c

@ -140,8 +140,10 @@ IFparm VDMOSmPTable[] = { /* model parameters */
IOP("vgdr_max", VDMOS_MOD_VGDR_MAX, IF_REAL, "maximum voltage G-D branch"),
IOP("pd_max", VDMOS_MOD_PD_MAX, IF_REAL, "maximum device power dissipation"),
IOP("id_max", VDMOS_MOD_ID_MAX, IF_REAL, "maximum drain/source current"),
IOP("idr_max", VDMOS_MOD_IB_MAX, IF_REAL, "maximum drain/source reverse current"),
IOP("idr_max", VDMOS_MOD_IDR_MAX, IF_REAL, "maximum drain/source reverse current"),
IOP("te_max", VDMOS_MOD_TE_MAX, IF_REAL, "maximum temperature"),
IOP("rth_ext", VDMOS_MOD_RTH_EXT, IF_REAL, "thermal resistance case to ambient, incl. heat sink"),
IOP("derating", VDMOS_MOD_DERATING, IF_REAL, "thermal derating for power"),
};
char *VDMOSnames[] = {

18
src/spicelib/devices/vdmos/vdmosdefs.h

@ -39,7 +39,7 @@ typedef struct sVDMOSinstance {
#define VDMOSname gen.GENname
#define VDMOSstates gen.GENstate
const int VDMOSdNode; /* number of the gate node of the mosfet */
const int VDMOSdNode; /* number of the drain node of the mosfet */
const int VDMOSgNode; /* number of the gate node of the mosfet */
const int VDMOSsNode; /* number of the source node of the mosfet */
int VDMOStempNode; /* number of the temperature node of the mosfet */
@ -361,6 +361,12 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
double VDMOSvdsMax;
double VDMOSvgsrMax;
double VDMOSvgdrMax;
double VDMOSid_max;
double VDMOSidr_max;
double VDMOSpd_max;
double VDMOSrth_ext;
double VDMOSte_max;
double VDMOSderating;
unsigned VDMOStypeGiven :1;
unsigned VDMOSdrainResistanceGiven :1;
@ -424,6 +430,12 @@ typedef struct sVDMOSmodel { /* model structure for a resistor */
unsigned VDMOSvdsMaxGiven :1;
unsigned VDMOSvgsrMaxGiven :1;
unsigned VDMOSvgdrMaxGiven :1;
unsigned VDMOSrth_extGiven :1;
unsigned VDMOSpd_maxGiven :1;
unsigned VDMOSte_maxGiven :1;
unsigned VDMOSid_maxGiven :1;
unsigned VDMOSidr_maxGiven :1;
unsigned VDMOSderatingGiven :1;
} VDMOSmodel;
#ifndef NMOS
@ -510,8 +522,10 @@ enum {
VDMOS_MOD_VGDR_MAX,
VDMOS_MOD_PD_MAX,
VDMOS_MOD_ID_MAX,
VDMOS_MOD_IB_MAX,
VDMOS_MOD_IDR_MAX,
VDMOS_MOD_TE_MAX,
VDMOS_MOD_RTH_EXT,
VDMOS_MOD_DERATING,
};
/* device questions */

20
src/spicelib/devices/vdmos/vdmosmask.c

@ -182,6 +182,7 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case VDMOS_MOD_TKSUBTHRES2:
value->rValue = model->VDMOStksubthres2;
return(OK);
/* SOA */
case VDMOS_MOD_VGS_MAX:
value->rValue = model->VDMOSvgsMax;
return(OK);
@ -197,6 +198,25 @@ VDMOSmAsk(CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case VDMOS_MOD_VGDR_MAX:
value->rValue = model->VDMOSvgdrMax;
return(OK);
case VDMOS_MOD_PD_MAX:
value->rValue = model->VDMOSpd_max;
return(OK);
case VDMOS_MOD_ID_MAX:
value->rValue = model->VDMOSid_max;
return(OK);
case VDMOS_MOD_IDR_MAX:
value->rValue = model->VDMOSidr_max;
return(OK);
case VDMOS_MOD_TE_MAX:
value->rValue = model->VDMOSte_max;
return(OK);
case VDMOS_MOD_RTH_EXT:
value->rValue = model->VDMOSrth_ext;
return(OK);
case VDMOS_MOD_DERATING:
value->rValue = model->VDMOSderating;
return(OK);
default:
return(E_BADPARM);
}

24
src/spicelib/devices/vdmos/vdmosmpar.c

@ -262,6 +262,30 @@ VDMOSmParam(int param, IFvalue *value, GENmodel *inModel)
model->VDMOSvgdrMax = value->rValue;
model->VDMOSvgdrMaxGiven = TRUE;
break;
case VDMOS_MOD_PD_MAX:
model->VDMOSpd_max = value->rValue;
model->VDMOSpd_maxGiven = TRUE;
break;
case VDMOS_MOD_ID_MAX:
model->VDMOSid_max = value->rValue;
model->VDMOSid_maxGiven = TRUE;
break;
case VDMOS_MOD_IDR_MAX:
model->VDMOSidr_max = value->rValue;
model->VDMOSidr_maxGiven = TRUE;
break;
case VDMOS_MOD_TE_MAX:
model->VDMOSte_max = value->rValue;
model->VDMOSte_maxGiven = TRUE;
break;
case VDMOS_MOD_RTH_EXT:
model->VDMOSrth_ext = value->rValue;
model->VDMOSrth_extGiven = TRUE;
break;
case VDMOS_MOD_DERATING:
model->VDMOSderating = value->rValue;
model->VDMOSderatingGiven = TRUE;
break;
default:
return(E_BADPARM);
}

18
src/spicelib/devices/vdmos/vdmosset.c

@ -190,6 +190,24 @@ VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
if (!model->VDMOSvgdrMaxGiven)
model->VDMOSvgdrMax = 1e99;
if (!model->VDMOSpd_maxGiven)
model->VDMOSpd_max = 1e99;
if (!model->VDMOSid_maxGiven)
model->VDMOSpd_max = 1e99;
if (!model->VDMOSidr_maxGiven)
model->VDMOSidr_max = 1e99;
if (!model->VDMOSte_maxGiven)
model->VDMOSte_max = 1e99;
if (!model->VDMOSderatingGiven)
model->VDMOSderating = 0;
if (!model->VDMOSrth_extGiven)
model->VDMOSrth_ext = model->VDMOSrthca;
if (!model->VDMOSqsResistanceGiven)
model->VDMOSqsResistance = 0.0;

105
src/spicelib/devices/vdmos/vdmossoachk.c

@ -19,12 +19,21 @@ VDMOSsoaCheck(CKTcircuit *ckt, GENmodel *inModel)
VDMOSinstance *here;
double vgs, vgd, vds; /* actual mos voltages */
int maxwarns;
static int warns_vgs = 0, warns_vgd = 0, warns_vds = 0;
static int warns_vgs = 0, warns_vgd = 0, warns_vds = 0, warns_id = 0, warns_idr = 0, warns_pd = 0, warns_te = 0;
double id; /* current VDMOS current */
double idr; /* current reverse diode current */
double pd; /* current VDMOS power dissipation */
double pd_max; /* maximum VDMOS power */
double te; /* current VDMOS temperature */
if (!ckt) {
warns_vgs = 0;
warns_vgd = 0;
warns_vds = 0;
warns_id = 0;
warns_idr = 0;
warns_pd = 0;
warns_te = 0;
return OK;
}
@ -35,13 +44,13 @@ VDMOSsoaCheck(CKTcircuit *ckt, GENmodel *inModel)
for (here = VDMOSinstances(model); here; here = VDMOSnextInstance(here)) {
vgs = ckt->CKTrhsOld [here->VDMOSgNode] -
ckt->CKTrhsOld [here->VDMOSsNodePrime];
ckt->CKTrhsOld [here->VDMOSsNode];
vgd = ckt->CKTrhsOld [here->VDMOSgNode] -
ckt->CKTrhsOld [here->VDMOSdNodePrime];
ckt->CKTrhsOld [here->VDMOSdNode];
vds = ckt->CKTrhsOld [here->VDMOSdNodePrime] -
ckt->CKTrhsOld [here->VDMOSsNodePrime];
vds = ckt->CKTrhsOld [here->VDMOSdNode] -
ckt->CKTrhsOld [here->VDMOSsNode];
if (!model->VDMOSvgsrMaxGiven) {
if (fabs(vgs) > model->VDMOSvgsMax)
@ -135,6 +144,92 @@ VDMOSsoaCheck(CKTcircuit *ckt, GENmodel *inModel)
warns_vds++;
}
/* max. drain current */
id = fabs(here->VDMOScd);
if (model->VDMOSid_maxGiven && id > fabs(model->VDMOSid_max))
if (warns_id < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Id=%.4g A at Vd=%.4g V has exceeded Id_max=%.4g A\n",
id, vds, model->VDMOSid_max);
warns_id++;
}
/* max. reverse current */
idr = fabs(*(ckt->CKTstate0 + here->VDIOcurrent) * -1. + here->VDMOScd);
if (model->VDMOSidr_maxGiven && idr > fabs(model->VDMOSidr_max))
if (warns_idr < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Idr=%.4g A at Vd=%.4g V has exceeded Idr_max=%.4g A\n",
fabs(idr), vds, model->VDMOSidr_max);
warns_idr++;
}
pd = fabs((id + idr) * vds);
pd += fabs(*(ckt->CKTstate0 + here->VDMOScqgd) *
(*(ckt->CKTrhsOld + here->VDMOSgNode) -
*(ckt->CKTrhsOld + here->VDMOSdNode)));
pd += fabs(*(ckt->CKTstate0 + here->VDMOScqgs) *
(*(ckt->CKTrhsOld + here->VDMOSgNode) -
*(ckt->CKTrhsOld + here->VDMOSsNode)));
/* Calculate max power including derating:
up to tnom the derating is zero,
at maximum temp allowed the derating is 100%.
Device temperature by self-heating or given externally. */
if (here->VDMOSthermal && model->VDMOSderatingGiven && model->VDMOSpd_maxGiven
&& model->VDMOSte_maxGiven && model->VDMOStnomGiven) {
te = ckt->CKTrhsOld[here->VDMOStcaseNode];
if (te < model->VDMOStnom - CONSTCtoK)
pd_max = model->VDMOSpd_max;
else {
pd_max = model->VDMOSpd_max - (te - model->VDMOStnom + CONSTCtoK) * model->VDMOSderating;
pd_max = (pd_max > 0) ? pd_max : 0.;
}
if (pd > pd_max)
if (warns_pd < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Pd=%.4g W at Vd=%.4g V and Te=%.4g C has exceeded Pd_max=%.4g W\n",
pd, vds, te, pd_max);
warns_pd++;
}
if (te > model->VDMOSte_max)
if (warns_te < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Te=%.4g C at Vd=%.4g V has exceeded te_max=%.4g C\n",
te, vds, model->VDMOSte_max);
warns_te++;
}
}
/* Derating of max allowed power dissipation, without self-heating,
external temp given by .temp (global) or instance parameter 'temp',
therefore no temperature limits are calculated */
else if (!here->VDMOSthermal && model->VDMOSderatingGiven && model->VDMOSpd_maxGiven && model->VDMOStnomGiven) {
if (here->VDMOStemp < model->VDMOStnom)
pd_max = model->VDMOSpd_max;
else {
pd_max = model->VDMOSpd_max - (here->VDMOStemp - model->VDMOStnom) * model->VDMOSderating;
pd_max = (pd_max > 0) ? pd_max : 0.;
}
if (pd > pd_max)
if (warns_pd < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Pd=%.4g W at Vd=%.4g V and Te=%.4g C has exceeded Pd_max=%.4g W\n",
pd, vds, here->VDMOStemp - CONSTCtoK, pd_max);
warns_pd++;
}
}
/* No derating, max power is fixed by model parameter pd_max */
else {
pd_max = model->VDMOSpd_max;
if (pd > pd_max)
if (warns_pd < maxwarns) {
soa_printf(ckt, (GENinstance*)here,
"Pd=%.4g W at Vd=%.4g V has exceeded Pd_max=%.4g W\n",
pd, vds, pd_max);
warns_pd++;
}
}
}
}

Loading…
Cancel
Save