|
|
|
@ -372,495 +372,495 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
* here we just evaluate the ideal diode current and the |
|
|
|
* corresponding derivative (conductance). |
|
|
|
*/ |
|
|
|
if (vbs <= -3 * vt) { |
|
|
|
here->VDMOSgbs = ckt->CKTgmin; |
|
|
|
here->VDMOScbs = here->VDMOSgbs*vbs - SourceSatCur; |
|
|
|
} |
|
|
|
else { |
|
|
|
evbs = exp(MIN(MAX_EXP_ARG, vbs / vt)); |
|
|
|
here->VDMOSgbs = SourceSatCur*evbs / vt + ckt->CKTgmin; |
|
|
|
here->VDMOScbs = SourceSatCur*(evbs - 1) + ckt->CKTgmin*vbs; |
|
|
|
} |
|
|
|
if (vbd <= -3 * vt) { |
|
|
|
here->VDMOSgbd = ckt->CKTgmin; |
|
|
|
here->VDMOScbd = here->VDMOSgbd*vbd - DrainSatCur; |
|
|
|
} |
|
|
|
else { |
|
|
|
evbd = exp(MIN(MAX_EXP_ARG, vbd / vt)); |
|
|
|
here->VDMOSgbd = DrainSatCur*evbd / vt + ckt->CKTgmin; |
|
|
|
here->VDMOScbd = DrainSatCur*(evbd - 1) + ckt->CKTgmin*vbd; |
|
|
|
} |
|
|
|
/* now to determine whether the user was able to correctly |
|
|
|
* identify the source and drain of his device |
|
|
|
if (vbs <= -3 * vt) { |
|
|
|
here->VDMOSgbs = ckt->CKTgmin; |
|
|
|
here->VDMOScbs = here->VDMOSgbs*vbs - SourceSatCur; |
|
|
|
} |
|
|
|
else { |
|
|
|
evbs = exp(MIN(MAX_EXP_ARG, vbs / vt)); |
|
|
|
here->VDMOSgbs = SourceSatCur*evbs / vt + ckt->CKTgmin; |
|
|
|
here->VDMOScbs = SourceSatCur*(evbs - 1) + ckt->CKTgmin*vbs; |
|
|
|
} |
|
|
|
if (vbd <= -3 * vt) { |
|
|
|
here->VDMOSgbd = ckt->CKTgmin; |
|
|
|
here->VDMOScbd = here->VDMOSgbd*vbd - DrainSatCur; |
|
|
|
} |
|
|
|
else { |
|
|
|
evbd = exp(MIN(MAX_EXP_ARG, vbd / vt)); |
|
|
|
here->VDMOSgbd = DrainSatCur*evbd / vt + ckt->CKTgmin; |
|
|
|
here->VDMOScbd = DrainSatCur*(evbd - 1) + ckt->CKTgmin*vbd; |
|
|
|
} |
|
|
|
/* now to determine whether the user was able to correctly |
|
|
|
* identify the source and drain of his device |
|
|
|
*/ |
|
|
|
if (vds >= 0) { |
|
|
|
/* normal mode */ |
|
|
|
here->VDMOSmode = 1; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* inverse mode */ |
|
|
|
here->VDMOSmode = -1; |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
{ |
|
|
|
/* |
|
|
|
* this block of code evaluates the drain current and its |
|
|
|
* derivatives using the shichman-hodges model and the |
|
|
|
* charges associated with the gate, channel and bulk for |
|
|
|
* mosfets |
|
|
|
* |
|
|
|
*/ |
|
|
|
|
|
|
|
/* the following 4 variables are local to this code block until |
|
|
|
* it is obvious that they can be made global |
|
|
|
*/ |
|
|
|
double arg; |
|
|
|
double betap; |
|
|
|
double sarg; |
|
|
|
double vgst; |
|
|
|
|
|
|
|
if ((here->VDMOSmode == 1 ? vbs : vbd) <= 0) { |
|
|
|
sarg = sqrt(here->VDMOStPhi - (here->VDMOSmode == 1 ? vbs : vbd)); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = sqrt(here->VDMOStPhi); |
|
|
|
sarg = sarg - (here->VDMOSmode == 1 ? vbs : vbd) / (sarg + sarg); |
|
|
|
sarg = MAX(0, sarg); |
|
|
|
} |
|
|
|
von = (here->VDMOStVbi*model->VDMOStype) + model->VDMOSgamma*sarg; |
|
|
|
vgst = (here->VDMOSmode == 1 ? vgs : vgd) - von; |
|
|
|
vdsat = MAX(vgst, 0); |
|
|
|
if (sarg <= 0) { |
|
|
|
arg = 0; |
|
|
|
} |
|
|
|
else { |
|
|
|
arg = model->VDMOSgamma / (sarg + sarg); |
|
|
|
} |
|
|
|
if (vgst <= 0) { |
|
|
|
/* |
|
|
|
* cutoff region |
|
|
|
*/ |
|
|
|
cdrain = 0; |
|
|
|
here->VDMOSgm = 0; |
|
|
|
here->VDMOSgds = 0; |
|
|
|
here->VDMOSgmbs = 0; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* |
|
|
|
* saturation region |
|
|
|
*/ |
|
|
|
if (vds >= 0) { |
|
|
|
/* normal mode */ |
|
|
|
here->VDMOSmode = 1; |
|
|
|
betap = Beta*(1 + model->VDMOSlambda*(vds*here->VDMOSmode)); |
|
|
|
if (vgst <= (vds*here->VDMOSmode)) { |
|
|
|
cdrain = betap*vgst*vgst*.5; |
|
|
|
here->VDMOSgm = betap*vgst; |
|
|
|
here->VDMOSgds = model->VDMOSlambda*Beta*vgst*vgst*.5; |
|
|
|
here->VDMOSgmbs = here->VDMOSgm*arg; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* inverse mode */ |
|
|
|
here->VDMOSmode = -1; |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
{ |
|
|
|
/* |
|
|
|
* this block of code evaluates the drain current and its |
|
|
|
* derivatives using the shichman-hodges model and the |
|
|
|
* charges associated with the gate, channel and bulk for |
|
|
|
* mosfets |
|
|
|
* |
|
|
|
* linear region |
|
|
|
*/ |
|
|
|
cdrain = betap*(vds*here->VDMOSmode)* |
|
|
|
(vgst - .5*(vds*here->VDMOSmode)); |
|
|
|
here->VDMOSgm = betap*(vds*here->VDMOSmode); |
|
|
|
here->VDMOSgds = betap*(vgst - (vds*here->VDMOSmode)) + |
|
|
|
model->VDMOSlambda*Beta* |
|
|
|
(vds*here->VDMOSmode)* |
|
|
|
(vgst - .5*(vds*here->VDMOSmode)); |
|
|
|
here->VDMOSgmbs = here->VDMOSgm*arg; |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
* finished |
|
|
|
*/ |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
/* the following 4 variables are local to this code block until |
|
|
|
* it is obvious that they can be made global |
|
|
|
*/ |
|
|
|
double arg; |
|
|
|
double betap; |
|
|
|
double sarg; |
|
|
|
double vgst; |
|
|
|
/* now deal with n vs p polarity */ |
|
|
|
|
|
|
|
if ((here->VDMOSmode == 1 ? vbs : vbd) <= 0) { |
|
|
|
sarg = sqrt(here->VDMOStPhi - (here->VDMOSmode == 1 ? vbs : vbd)); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = sqrt(here->VDMOStPhi); |
|
|
|
sarg = sarg - (here->VDMOSmode == 1 ? vbs : vbd) / (sarg + sarg); |
|
|
|
sarg = MAX(0, sarg); |
|
|
|
} |
|
|
|
von = (here->VDMOStVbi*model->VDMOStype) + model->VDMOSgamma*sarg; |
|
|
|
vgst = (here->VDMOSmode == 1 ? vgs : vgd) - von; |
|
|
|
vdsat = MAX(vgst, 0); |
|
|
|
if (sarg <= 0) { |
|
|
|
arg = 0; |
|
|
|
} |
|
|
|
else { |
|
|
|
arg = model->VDMOSgamma / (sarg + sarg); |
|
|
|
} |
|
|
|
if (vgst <= 0) { |
|
|
|
here->VDMOSvon = model->VDMOStype * von; |
|
|
|
here->VDMOSvdsat = model->VDMOStype * vdsat; |
|
|
|
/* line 490 */ |
|
|
|
/* |
|
|
|
* COMPUTE EQUIVALENT DRAIN CURRENT SOURCE |
|
|
|
*/ |
|
|
|
here->VDMOScd = here->VDMOSmode * cdrain - here->VDMOScbd; |
|
|
|
|
|
|
|
if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { |
|
|
|
/* |
|
|
|
* now we do the hard part of the bulk-drain and bulk-source |
|
|
|
* diode - we evaluate the non-linear capacitance and |
|
|
|
* charge |
|
|
|
* |
|
|
|
* the basic equations are not hard, but the implementation |
|
|
|
* is somewhat long in an attempt to avoid log/exponential |
|
|
|
* evaluations |
|
|
|
*/ |
|
|
|
/* |
|
|
|
* charge storage elements |
|
|
|
* |
|
|
|
*.. bulk-drain and bulk-source depletion capacitances |
|
|
|
*/ |
|
|
|
{ |
|
|
|
/* can't bypass the diode capacitance calculations */ |
|
|
|
if (here->VDMOSCbs != 0 || here->VDMOSCbssw != 0) { |
|
|
|
if (vbs < here->VDMOStDepCap) { |
|
|
|
arg = 1 - vbs / here->VDMOStBulkPot; |
|
|
|
/* |
|
|
|
* cutoff region |
|
|
|
* the following block looks somewhat long and messy, |
|
|
|
* but since most users use the default grading |
|
|
|
* coefficients of .5, and sqrt is MUCH faster than an |
|
|
|
* exp(log()) we use this special case code to buy time. |
|
|
|
* (as much as 10% of total job time!) |
|
|
|
*/ |
|
|
|
cdrain = 0; |
|
|
|
here->VDMOSgm = 0; |
|
|
|
here->VDMOSgds = 0; |
|
|
|
here->VDMOSgmbs = 0; |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == |
|
|
|
model->VDMOSbulkJctSideGradingCoeff) { |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5) { |
|
|
|
sarg = sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = sargsw = |
|
|
|
exp(-model->VDMOSbulkJctBotGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5) { |
|
|
|
sarg = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = exp(-model->VDMOSbulkJctBotGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
if (model->VDMOSbulkJctSideGradingCoeff == .5) { |
|
|
|
sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sargsw = exp(-model->VDMOSbulkJctSideGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbs) = |
|
|
|
here->VDMOStBulkPot*(here->VDMOSCbs* |
|
|
|
(1 - arg*sarg) / (1 - model->VDMOSbulkJctBotGradingCoeff) |
|
|
|
+ here->VDMOSCbssw* |
|
|
|
(1 - arg*sargsw) / |
|
|
|
(1 - model->VDMOSbulkJctSideGradingCoeff)); |
|
|
|
here->VDMOScapbs = here->VDMOSCbs*sarg + |
|
|
|
here->VDMOSCbssw*sargsw; |
|
|
|
} |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbs) = here->VDMOSf4s + |
|
|
|
vbs*(here->VDMOSf2s + vbs*(here->VDMOSf3s / 2)); |
|
|
|
here->VDMOScapbs = here->VDMOSf2s + here->VDMOSf3s*vbs; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbs) = 0; |
|
|
|
here->VDMOScapbs = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
{ |
|
|
|
if (here->VDMOSCbd != 0 || here->VDMOSCbdsw != 0) { |
|
|
|
if (vbd < here->VDMOStDepCap) { |
|
|
|
arg = 1 - vbd / here->VDMOStBulkPot; |
|
|
|
/* |
|
|
|
* saturation region |
|
|
|
* the following block looks somewhat long and messy, |
|
|
|
* but since most users use the default grading |
|
|
|
* coefficients of .5, and sqrt is MUCH faster than an |
|
|
|
* exp(log()) we use this special case code to buy time. |
|
|
|
* (as much as 10% of total job time!) |
|
|
|
*/ |
|
|
|
betap = Beta*(1 + model->VDMOSlambda*(vds*here->VDMOSmode)); |
|
|
|
if (vgst <= (vds*here->VDMOSmode)) { |
|
|
|
cdrain = betap*vgst*vgst*.5; |
|
|
|
here->VDMOSgm = betap*vgst; |
|
|
|
here->VDMOSgds = model->VDMOSlambda*Beta*vgst*vgst*.5; |
|
|
|
here->VDMOSgmbs = here->VDMOSgm*arg; |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5 && |
|
|
|
model->VDMOSbulkJctSideGradingCoeff == .5) { |
|
|
|
sarg = sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* |
|
|
|
* linear region |
|
|
|
*/ |
|
|
|
cdrain = betap*(vds*here->VDMOSmode)* |
|
|
|
(vgst - .5*(vds*here->VDMOSmode)); |
|
|
|
here->VDMOSgm = betap*(vds*here->VDMOSmode); |
|
|
|
here->VDMOSgds = betap*(vgst - (vds*here->VDMOSmode)) + |
|
|
|
model->VDMOSlambda*Beta* |
|
|
|
(vds*here->VDMOSmode)* |
|
|
|
(vgst - .5*(vds*here->VDMOSmode)); |
|
|
|
here->VDMOSgmbs = here->VDMOSgm*arg; |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
* finished |
|
|
|
*/ |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
/* now deal with n vs p polarity */ |
|
|
|
|
|
|
|
here->VDMOSvon = model->VDMOStype * von; |
|
|
|
here->VDMOSvdsat = model->VDMOStype * vdsat; |
|
|
|
/* line 490 */ |
|
|
|
/* |
|
|
|
* COMPUTE EQUIVALENT DRAIN CURRENT SOURCE |
|
|
|
*/ |
|
|
|
here->VDMOScd = here->VDMOSmode * cdrain - here->VDMOScbd; |
|
|
|
|
|
|
|
if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { |
|
|
|
/* |
|
|
|
* now we do the hard part of the bulk-drain and bulk-source |
|
|
|
* diode - we evaluate the non-linear capacitance and |
|
|
|
* charge |
|
|
|
* |
|
|
|
* the basic equations are not hard, but the implementation |
|
|
|
* is somewhat long in an attempt to avoid log/exponential |
|
|
|
* evaluations |
|
|
|
*/ |
|
|
|
/* |
|
|
|
* charge storage elements |
|
|
|
* |
|
|
|
*.. bulk-drain and bulk-source depletion capacitances |
|
|
|
*/ |
|
|
|
{ |
|
|
|
/* can't bypass the diode capacitance calculations */ |
|
|
|
if (here->VDMOSCbs != 0 || here->VDMOSCbssw != 0) { |
|
|
|
if (vbs < here->VDMOStDepCap) { |
|
|
|
arg = 1 - vbs / here->VDMOStBulkPot; |
|
|
|
/* |
|
|
|
* the following block looks somewhat long and messy, |
|
|
|
* but since most users use the default grading |
|
|
|
* coefficients of .5, and sqrt is MUCH faster than an |
|
|
|
* exp(log()) we use this special case code to buy time. |
|
|
|
* (as much as 10% of total job time!) |
|
|
|
*/ |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == |
|
|
|
model->VDMOSbulkJctSideGradingCoeff) { |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5) { |
|
|
|
sarg = sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = sargsw = |
|
|
|
exp(-model->VDMOSbulkJctBotGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5) { |
|
|
|
sarg = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = exp(-model->VDMOSbulkJctBotGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
if (model->VDMOSbulkJctSideGradingCoeff == .5) { |
|
|
|
sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sargsw = exp(-model->VDMOSbulkJctSideGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbs) = |
|
|
|
here->VDMOStBulkPot*(here->VDMOSCbs* |
|
|
|
(1 - arg*sarg) / (1 - model->VDMOSbulkJctBotGradingCoeff) |
|
|
|
+ here->VDMOSCbssw* |
|
|
|
(1 - arg*sargsw) / |
|
|
|
(1 - model->VDMOSbulkJctSideGradingCoeff)); |
|
|
|
here->VDMOScapbs = here->VDMOSCbs*sarg + |
|
|
|
here->VDMOSCbssw*sargsw; |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5) { |
|
|
|
sarg = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbs) = here->VDMOSf4s + |
|
|
|
vbs*(here->VDMOSf2s + vbs*(here->VDMOSf3s / 2)); |
|
|
|
here->VDMOScapbs = here->VDMOSf2s + here->VDMOSf3s*vbs; |
|
|
|
sarg = exp(-model->VDMOSbulkJctBotGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbs) = 0; |
|
|
|
here->VDMOScapbs = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
{ |
|
|
|
if (here->VDMOSCbd != 0 || here->VDMOSCbdsw != 0) { |
|
|
|
if (vbd < here->VDMOStDepCap) { |
|
|
|
arg = 1 - vbd / here->VDMOStBulkPot; |
|
|
|
/* |
|
|
|
* the following block looks somewhat long and messy, |
|
|
|
* but since most users use the default grading |
|
|
|
* coefficients of .5, and sqrt is MUCH faster than an |
|
|
|
* exp(log()) we use this special case code to buy time. |
|
|
|
* (as much as 10% of total job time!) |
|
|
|
*/ |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5 && |
|
|
|
model->VDMOSbulkJctSideGradingCoeff == .5) { |
|
|
|
sarg = sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (model->VDMOSbulkJctBotGradingCoeff == .5) { |
|
|
|
sarg = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sarg = exp(-model->VDMOSbulkJctBotGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
if (model->VDMOSbulkJctSideGradingCoeff == .5) { |
|
|
|
sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
sargsw = exp(-model->VDMOSbulkJctSideGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbd) = |
|
|
|
here->VDMOStBulkPot*(here->VDMOSCbd* |
|
|
|
(1 - arg*sarg) |
|
|
|
/ (1 - model->VDMOSbulkJctBotGradingCoeff) |
|
|
|
+ here->VDMOSCbdsw* |
|
|
|
(1 - arg*sargsw) |
|
|
|
/ (1 - model->VDMOSbulkJctSideGradingCoeff)); |
|
|
|
here->VDMOScapbd = here->VDMOSCbd*sarg + |
|
|
|
here->VDMOSCbdsw*sargsw; |
|
|
|
if (model->VDMOSbulkJctSideGradingCoeff == .5) { |
|
|
|
sargsw = 1 / sqrt(arg); |
|
|
|
} |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbd) = here->VDMOSf4d + |
|
|
|
vbd * (here->VDMOSf2d + vbd * here->VDMOSf3d / 2); |
|
|
|
here->VDMOScapbd = here->VDMOSf2d + vbd * here->VDMOSf3d; |
|
|
|
sargsw = exp(-model->VDMOSbulkJctSideGradingCoeff* |
|
|
|
log(arg)); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbd) = 0; |
|
|
|
here->VDMOScapbd = 0; |
|
|
|
} |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbd) = |
|
|
|
here->VDMOStBulkPot*(here->VDMOSCbd* |
|
|
|
(1 - arg*sarg) |
|
|
|
/ (1 - model->VDMOSbulkJctBotGradingCoeff) |
|
|
|
+ here->VDMOSCbdsw* |
|
|
|
(1 - arg*sargsw) |
|
|
|
/ (1 - model->VDMOSbulkJctSideGradingCoeff)); |
|
|
|
here->VDMOScapbd = here->VDMOSCbd*sarg + |
|
|
|
here->VDMOSCbdsw*sargsw; |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
if ((ckt->CKTmode & MODETRAN) || ((ckt->CKTmode&MODEINITTRAN) |
|
|
|
&& !(ckt->CKTmode&MODEUIC))) { |
|
|
|
/* (above only excludes tranop, since we're only at this |
|
|
|
* point if tran or tranop ) |
|
|
|
*/ |
|
|
|
|
|
|
|
/* |
|
|
|
* calculate equivalent conductances and currents for |
|
|
|
* depletion capacitors |
|
|
|
*/ |
|
|
|
|
|
|
|
/* integrate the capacitors and save results */ |
|
|
|
|
|
|
|
error = NIintegrate(ckt, &geq, &ceq, here->VDMOScapbd, |
|
|
|
here->VDMOSqbd); |
|
|
|
if (error) return(error); |
|
|
|
here->VDMOSgbd += geq; |
|
|
|
here->VDMOScbd += *(ckt->CKTstate0 + here->VDMOScqbd); |
|
|
|
here->VDMOScd -= *(ckt->CKTstate0 + here->VDMOScqbd); |
|
|
|
error = NIintegrate(ckt, &geq, &ceq, here->VDMOScapbs, |
|
|
|
here->VDMOSqbs); |
|
|
|
if (error) return(error); |
|
|
|
here->VDMOSgbs += geq; |
|
|
|
here->VDMOScbs += *(ckt->CKTstate0 + here->VDMOScqbs); |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbd) = here->VDMOSf4d + |
|
|
|
vbd * (here->VDMOSf2d + vbd * here->VDMOSf3d / 2); |
|
|
|
here->VDMOScapbd = here->VDMOSf2d + vbd * here->VDMOSf3d; |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
else { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqbd) = 0; |
|
|
|
here->VDMOScapbd = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* check convergence |
|
|
|
if ((ckt->CKTmode & MODETRAN) || ((ckt->CKTmode&MODEINITTRAN) |
|
|
|
&& !(ckt->CKTmode&MODEUIC))) { |
|
|
|
/* (above only excludes tranop, since we're only at this |
|
|
|
* point if tran or tranop ) |
|
|
|
*/ |
|
|
|
if ((here->VDMOSoff == 0) || |
|
|
|
(!(ckt->CKTmode & (MODEINITFIX | MODEINITSMSIG)))) { |
|
|
|
if (Check == 1) { |
|
|
|
ckt->CKTnoncon++; |
|
|
|
ckt->CKTtroubleElt = (GENinstance *)here; |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
/* save things away for next time */ |
|
|
|
/* |
|
|
|
* calculate equivalent conductances and currents for |
|
|
|
* depletion capacitors |
|
|
|
*/ |
|
|
|
|
|
|
|
/* integrate the capacitors and save results */ |
|
|
|
|
|
|
|
error = NIintegrate(ckt, &geq, &ceq, here->VDMOScapbd, |
|
|
|
here->VDMOSqbd); |
|
|
|
if (error) return(error); |
|
|
|
here->VDMOSgbd += geq; |
|
|
|
here->VDMOScbd += *(ckt->CKTstate0 + here->VDMOScqbd); |
|
|
|
here->VDMOScd -= *(ckt->CKTstate0 + here->VDMOScqbd); |
|
|
|
error = NIintegrate(ckt, &geq, &ceq, here->VDMOScapbs, |
|
|
|
here->VDMOSqbs); |
|
|
|
if (error) return(error); |
|
|
|
here->VDMOSgbs += geq; |
|
|
|
here->VDMOScbs += *(ckt->CKTstate0 + here->VDMOScqbs); |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
*(ckt->CKTstate0 + here->VDMOSvbs) = vbs; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSvbd) = vbd; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSvgs) = vgs; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSvds) = vds; |
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
/* |
|
|
|
* check convergence |
|
|
|
*/ |
|
|
|
if ((here->VDMOSoff == 0) || |
|
|
|
(!(ckt->CKTmode & (MODEINITFIX | MODEINITSMSIG)))) { |
|
|
|
if (Check == 1) { |
|
|
|
ckt->CKTnoncon++; |
|
|
|
ckt->CKTtroubleElt = (GENinstance *)here; |
|
|
|
} |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
/* |
|
|
|
* vdmos capacitor model |
|
|
|
*/ |
|
|
|
if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { |
|
|
|
/* |
|
|
|
* calculate gate - drain, gate - source capacitors |
|
|
|
* drain-source capacitor is evaluated with the bulk diode below |
|
|
|
*/ |
|
|
|
/* |
|
|
|
* this just evaluates at the current time, |
|
|
|
* expects you to remember values from previous time |
|
|
|
* returns 1/2 of non-constant portion of capacitance |
|
|
|
* you must add in the other half from previous time |
|
|
|
* and the constant part |
|
|
|
*/ |
|
|
|
DevCapVDMOS(vgd, cgdmin, cgdmax, a, cgs, |
|
|
|
(ckt->CKTstate0 + here->VDMOScapgs), |
|
|
|
(ckt->CKTstate0 + here->VDMOScapgd), |
|
|
|
(ckt->CKTstate0 + here->VDMOScapgb)); |
|
|
|
|
|
|
|
vgs1 = *(ckt->CKTstate1 + here->VDMOSvgs); |
|
|
|
vgd1 = vgs1 - *(ckt->CKTstate1 + here->VDMOSvds); |
|
|
|
vgb1 = vgs1 - *(ckt->CKTstate1 + here->VDMOSvbs); |
|
|
|
if (ckt->CKTmode & (MODETRANOP | MODEINITSMSIG)) { |
|
|
|
capgs = 2 * *(ckt->CKTstate0 + here->VDMOScapgs) + |
|
|
|
GateSourceOverlapCap; |
|
|
|
capgd = 2 * *(ckt->CKTstate0 + here->VDMOScapgd) + |
|
|
|
GateDrainOverlapCap; |
|
|
|
capgb = 2 * *(ckt->CKTstate0 + here->VDMOScapgb) + |
|
|
|
GateBulkOverlapCap; |
|
|
|
} |
|
|
|
else { |
|
|
|
capgs = (*(ckt->CKTstate0 + here->VDMOScapgs) + |
|
|
|
*(ckt->CKTstate1 + here->VDMOScapgs) + |
|
|
|
GateSourceOverlapCap); |
|
|
|
capgd = (*(ckt->CKTstate0 + here->VDMOScapgd) + |
|
|
|
*(ckt->CKTstate1 + here->VDMOScapgd) + |
|
|
|
GateDrainOverlapCap); |
|
|
|
capgb = (*(ckt->CKTstate0 + here->VDMOScapgb) + |
|
|
|
*(ckt->CKTstate1 + here->VDMOScapgb) + |
|
|
|
GateBulkOverlapCap); |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
/* save things away for next time */ |
|
|
|
|
|
|
|
*(ckt->CKTstate0 + here->VDMOSvbs) = vbs; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSvbd) = vbd; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSvgs) = vgs; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSvds) = vds; |
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
/* |
|
|
|
* vdmos capacitor model |
|
|
|
*/ |
|
|
|
if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) { |
|
|
|
/* |
|
|
|
* calculate gate - drain, gate - source capacitors |
|
|
|
* drain-source capacitor is evaluated with the bulk diode below |
|
|
|
*/ |
|
|
|
/* |
|
|
|
* this just evaluates at the current time, |
|
|
|
* expects you to remember values from previous time |
|
|
|
* returns 1/2 of non-constant portion of capacitance |
|
|
|
* you must add in the other half from previous time |
|
|
|
* and the constant part |
|
|
|
*/ |
|
|
|
DevCapVDMOS(vgd, cgdmin, cgdmax, a, cgs, |
|
|
|
(ckt->CKTstate0 + here->VDMOScapgs), |
|
|
|
(ckt->CKTstate0 + here->VDMOScapgd), |
|
|
|
(ckt->CKTstate0 + here->VDMOScapgb)); |
|
|
|
|
|
|
|
vgs1 = *(ckt->CKTstate1 + here->VDMOSvgs); |
|
|
|
vgd1 = vgs1 - *(ckt->CKTstate1 + here->VDMOSvds); |
|
|
|
vgb1 = vgs1 - *(ckt->CKTstate1 + here->VDMOSvbs); |
|
|
|
if (ckt->CKTmode & (MODETRANOP | MODEINITSMSIG)) { |
|
|
|
capgs = 2 * *(ckt->CKTstate0 + here->VDMOScapgs) + |
|
|
|
GateSourceOverlapCap; |
|
|
|
capgd = 2 * *(ckt->CKTstate0 + here->VDMOScapgd) + |
|
|
|
GateDrainOverlapCap; |
|
|
|
capgb = 2 * *(ckt->CKTstate0 + here->VDMOScapgb) + |
|
|
|
GateBulkOverlapCap; |
|
|
|
} |
|
|
|
else { |
|
|
|
capgs = (*(ckt->CKTstate0 + here->VDMOScapgs) + |
|
|
|
*(ckt->CKTstate1 + here->VDMOScapgs) + |
|
|
|
GateSourceOverlapCap); |
|
|
|
capgd = (*(ckt->CKTstate0 + here->VDMOScapgd) + |
|
|
|
*(ckt->CKTstate1 + here->VDMOScapgd) + |
|
|
|
GateDrainOverlapCap); |
|
|
|
capgb = (*(ckt->CKTstate0 + here->VDMOScapgb) + |
|
|
|
*(ckt->CKTstate1 + here->VDMOScapgb) + |
|
|
|
GateBulkOverlapCap); |
|
|
|
} |
|
|
|
/* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
#ifndef PREDICTOR |
|
|
|
if (ckt->CKTmode & (MODEINITPRED | MODEINITTRAN)) { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs) = |
|
|
|
(1 + xfact) * *(ckt->CKTstate1 + here->VDMOSqgs) |
|
|
|
- xfact * *(ckt->CKTstate2 + here->VDMOSqgs); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd) = |
|
|
|
(1 + xfact) * *(ckt->CKTstate1 + here->VDMOSqgd) |
|
|
|
- xfact * *(ckt->CKTstate2 + here->VDMOSqgd); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb) = |
|
|
|
(1 + xfact) * *(ckt->CKTstate1 + here->VDMOSqgb) |
|
|
|
- xfact * *(ckt->CKTstate2 + here->VDMOSqgb); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (ckt->CKTmode & (MODEINITPRED | MODEINITTRAN)) { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs) = |
|
|
|
(1 + xfact) * *(ckt->CKTstate1 + here->VDMOSqgs) |
|
|
|
- xfact * *(ckt->CKTstate2 + here->VDMOSqgs); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd) = |
|
|
|
(1 + xfact) * *(ckt->CKTstate1 + here->VDMOSqgd) |
|
|
|
- xfact * *(ckt->CKTstate2 + here->VDMOSqgd); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb) = |
|
|
|
(1 + xfact) * *(ckt->CKTstate1 + here->VDMOSqgb) |
|
|
|
- xfact * *(ckt->CKTstate2 + here->VDMOSqgb); |
|
|
|
} |
|
|
|
else { |
|
|
|
#endif /*PREDICTOR*/ |
|
|
|
if (ckt->CKTmode & MODETRAN) { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs) = (vgs - vgs1)*capgs + |
|
|
|
*(ckt->CKTstate1 + here->VDMOSqgs); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd) = (vgd - vgd1)*capgd + |
|
|
|
*(ckt->CKTstate1 + here->VDMOSqgd); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb) = (vgb - vgb1)*capgb + |
|
|
|
*(ckt->CKTstate1 + here->VDMOSqgb); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* TRANOP only */ |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs) = vgs*capgs; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd) = vgd*capgd; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb) = vgb*capgb; |
|
|
|
} |
|
|
|
if (ckt->CKTmode & MODETRAN) { |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs) = (vgs - vgs1)*capgs + |
|
|
|
*(ckt->CKTstate1 + here->VDMOSqgs); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd) = (vgd - vgd1)*capgd + |
|
|
|
*(ckt->CKTstate1 + here->VDMOSqgd); |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb) = (vgb - vgb1)*capgb + |
|
|
|
*(ckt->CKTstate1 + here->VDMOSqgb); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* TRANOP only */ |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs) = vgs*capgs; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd) = vgd*capgd; |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb) = vgb*capgb; |
|
|
|
} |
|
|
|
#ifndef PREDICTOR |
|
|
|
} |
|
|
|
} |
|
|
|
#endif /*PREDICTOR*/ |
|
|
|
} |
|
|
|
} |
|
|
|
#ifndef NOBYPASS |
|
|
|
bypass : |
|
|
|
bypass : |
|
|
|
#endif |
|
|
|
|
|
|
|
if ((ckt->CKTmode & (MODEINITTRAN)) || |
|
|
|
(!(ckt->CKTmode & (MODETRAN)))) { |
|
|
|
/* |
|
|
|
* initialize to zero charge conductances |
|
|
|
* and current |
|
|
|
*/ |
|
|
|
gcgs = 0; |
|
|
|
ceqgs = 0; |
|
|
|
gcgd = 0; |
|
|
|
ceqgd = 0; |
|
|
|
gcgb = 0; |
|
|
|
ceqgb = 0; |
|
|
|
} |
|
|
|
else { |
|
|
|
if (capgs == 0) *(ckt->CKTstate0 + here->VDMOScqgs) = 0; |
|
|
|
if (capgd == 0) *(ckt->CKTstate0 + here->VDMOScqgd) = 0; |
|
|
|
if (capgb == 0) *(ckt->CKTstate0 + here->VDMOScqgb) = 0; |
|
|
|
/* |
|
|
|
* calculate equivalent conductances and currents for |
|
|
|
* meyer"s capacitors |
|
|
|
*/ |
|
|
|
error = NIintegrate(ckt, &gcgs, &ceqgs, capgs, here->VDMOSqgs); |
|
|
|
if (error) return(error); |
|
|
|
error = NIintegrate(ckt, &gcgd, &ceqgd, capgd, here->VDMOSqgd); |
|
|
|
if (error) return(error); |
|
|
|
error = NIintegrate(ckt, &gcgb, &ceqgb, capgb, here->VDMOSqgb); |
|
|
|
if (error) return(error); |
|
|
|
ceqgs = ceqgs - gcgs*vgs + ckt->CKTag[0] * |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs); |
|
|
|
ceqgd = ceqgd - gcgd*vgd + ckt->CKTag[0] * |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd); |
|
|
|
ceqgb = ceqgb - gcgb*vgb + ckt->CKTag[0] * |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb); |
|
|
|
} |
|
|
|
/* |
|
|
|
* store charge storage info for meyer's cap in lx table |
|
|
|
*/ |
|
|
|
if ((ckt->CKTmode & (MODEINITTRAN)) || |
|
|
|
(!(ckt->CKTmode & (MODETRAN)))) { |
|
|
|
/* |
|
|
|
* initialize to zero charge conductances |
|
|
|
* and current |
|
|
|
*/ |
|
|
|
gcgs = 0; |
|
|
|
ceqgs = 0; |
|
|
|
gcgd = 0; |
|
|
|
ceqgd = 0; |
|
|
|
gcgb = 0; |
|
|
|
ceqgb = 0; |
|
|
|
} |
|
|
|
else { |
|
|
|
if (capgs == 0) *(ckt->CKTstate0 + here->VDMOScqgs) = 0; |
|
|
|
if (capgd == 0) *(ckt->CKTstate0 + here->VDMOScqgd) = 0; |
|
|
|
if (capgb == 0) *(ckt->CKTstate0 + here->VDMOScqgb) = 0; |
|
|
|
/* |
|
|
|
* calculate equivalent conductances and currents for |
|
|
|
* meyer"s capacitors |
|
|
|
*/ |
|
|
|
error = NIintegrate(ckt, &gcgs, &ceqgs, capgs, here->VDMOSqgs); |
|
|
|
if (error) return(error); |
|
|
|
error = NIintegrate(ckt, &gcgd, &ceqgd, capgd, here->VDMOSqgd); |
|
|
|
if (error) return(error); |
|
|
|
error = NIintegrate(ckt, &gcgb, &ceqgb, capgb, here->VDMOSqgb); |
|
|
|
if (error) return(error); |
|
|
|
ceqgs = ceqgs - gcgs*vgs + ckt->CKTag[0] * |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgs); |
|
|
|
ceqgd = ceqgd - gcgd*vgd + ckt->CKTag[0] * |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgd); |
|
|
|
ceqgb = ceqgb - gcgb*vgb + ckt->CKTag[0] * |
|
|
|
*(ckt->CKTstate0 + here->VDMOSqgb); |
|
|
|
} |
|
|
|
/* |
|
|
|
* store charge storage info for meyer's cap in lx table |
|
|
|
*/ |
|
|
|
|
|
|
|
/* |
|
|
|
* load current vector |
|
|
|
*/ |
|
|
|
ceqbs = model->VDMOStype * |
|
|
|
(here->VDMOScbs - (here->VDMOSgbs)*vbs); |
|
|
|
ceqbd = model->VDMOStype * |
|
|
|
(here->VDMOScbd - (here->VDMOSgbd)*vbd); |
|
|
|
if (here->VDMOSmode >= 0) { |
|
|
|
xnrm = 1; |
|
|
|
xrev = 0; |
|
|
|
cdreq = model->VDMOStype*(cdrain - here->VDMOSgds*vds - |
|
|
|
here->VDMOSgm*vgs - here->VDMOSgmbs*vbs); |
|
|
|
} |
|
|
|
else { |
|
|
|
xnrm = 0; |
|
|
|
xrev = 1; |
|
|
|
cdreq = -(model->VDMOStype)*(cdrain - here->VDMOSgds*(-vds) - |
|
|
|
here->VDMOSgm*vgd - here->VDMOSgmbs*vbd); |
|
|
|
} |
|
|
|
*(ckt->CKTrhs + here->VDMOSgNodePrime) -= |
|
|
|
(model->VDMOStype * (ceqgs + ceqgb + ceqgd)); |
|
|
|
*(ckt->CKTrhs + here->VDMOSbNode) -= |
|
|
|
(ceqbs + ceqbd - model->VDMOStype * ceqgb); |
|
|
|
*(ckt->CKTrhs + here->VDMOSdNodePrime) += |
|
|
|
(ceqbd - cdreq + model->VDMOStype * ceqgd); |
|
|
|
*(ckt->CKTrhs + here->VDMOSsNodePrime) += |
|
|
|
cdreq + ceqbs + model->VDMOStype * ceqgs; |
|
|
|
/* |
|
|
|
* load y matrix |
|
|
|
*/ |
|
|
|
|
|
|
|
*(here->VDMOSDdPtr) += (here->VDMOSdrainConductance); |
|
|
|
*(here->VDMOSGgPtr) += (here->VDMOSgateConductance); //((gcgd + gcgs + gcgb)); |
|
|
|
*(here->VDMOSSsPtr) += (here->VDMOSsourceConductance); |
|
|
|
*(here->VDMOSBbPtr) += (here->VDMOSgbd + here->VDMOSgbs + gcgb); |
|
|
|
*(here->VDMOSDPdpPtr) += |
|
|
|
(here->VDMOSdrainConductance + here->VDMOSgds + |
|
|
|
here->VDMOSgbd + xrev*(here->VDMOSgm + here->VDMOSgmbs) + gcgd); |
|
|
|
*(here->VDMOSSPspPtr) += |
|
|
|
(here->VDMOSsourceConductance + here->VDMOSgds + |
|
|
|
here->VDMOSgbs + xnrm*(here->VDMOSgm + here->VDMOSgmbs) + gcgs); |
|
|
|
*(here->VDMOSGPgpPtr) += |
|
|
|
(here->VDMOSgateConductance) + (gcgd + gcgs + gcgb); |
|
|
|
*(here->VDMOSGgpPtr) += (-here->VDMOSgateConductance); |
|
|
|
*(here->VDMOSDdpPtr) += (-here->VDMOSdrainConductance); |
|
|
|
*(here->VDMOSGPgPtr) += (-here->VDMOSgateConductance); |
|
|
|
*(here->VDMOSGPbPtr) -= gcgb; |
|
|
|
*(here->VDMOSGPdpPtr) -= gcgd; |
|
|
|
*(here->VDMOSGPspPtr) -= gcgs; |
|
|
|
*(here->VDMOSSspPtr) += (-here->VDMOSsourceConductance); |
|
|
|
*(here->VDMOSBgpPtr) -= gcgb; |
|
|
|
*(here->VDMOSBdpPtr) -= here->VDMOSgbd; |
|
|
|
*(here->VDMOSBspPtr) -= here->VDMOSgbs; |
|
|
|
*(here->VDMOSDPdPtr) += (-here->VDMOSdrainConductance); |
|
|
|
*(here->VDMOSDPgpPtr) += ((xnrm - xrev)*here->VDMOSgm - gcgd); |
|
|
|
*(here->VDMOSDPbPtr) += (-here->VDMOSgbd + (xnrm - xrev)*here->VDMOSgmbs); |
|
|
|
*(here->VDMOSDPspPtr) += (-here->VDMOSgds - xnrm* |
|
|
|
(here->VDMOSgm + here->VDMOSgmbs)); |
|
|
|
*(here->VDMOSSPgpPtr) += (-(xnrm - xrev)*here->VDMOSgm - gcgs); |
|
|
|
*(here->VDMOSSPsPtr) += (-here->VDMOSsourceConductance); |
|
|
|
*(here->VDMOSSPbPtr) += (-here->VDMOSgbs - (xnrm - xrev)*here->VDMOSgmbs); |
|
|
|
*(here->VDMOSSPdpPtr) += (-here->VDMOSgds - xrev* |
|
|
|
(here->VDMOSgm + here->VDMOSgmbs)); |
|
|
|
/* |
|
|
|
* load current vector |
|
|
|
*/ |
|
|
|
ceqbs = model->VDMOStype * |
|
|
|
(here->VDMOScbs - (here->VDMOSgbs)*vbs); |
|
|
|
ceqbd = model->VDMOStype * |
|
|
|
(here->VDMOScbd - (here->VDMOSgbd)*vbd); |
|
|
|
if (here->VDMOSmode >= 0) { |
|
|
|
xnrm = 1; |
|
|
|
xrev = 0; |
|
|
|
cdreq = model->VDMOStype*(cdrain - here->VDMOSgds*vds - |
|
|
|
here->VDMOSgm*vgs - here->VDMOSgmbs*vbs); |
|
|
|
} |
|
|
|
else { |
|
|
|
xnrm = 0; |
|
|
|
xrev = 1; |
|
|
|
cdreq = -(model->VDMOStype)*(cdrain - here->VDMOSgds*(-vds) - |
|
|
|
here->VDMOSgm*vgd - here->VDMOSgmbs*vbd); |
|
|
|
} |
|
|
|
*(ckt->CKTrhs + here->VDMOSgNodePrime) -= |
|
|
|
(model->VDMOStype * (ceqgs + ceqgb + ceqgd)); |
|
|
|
*(ckt->CKTrhs + here->VDMOSbNode) -= |
|
|
|
(ceqbs + ceqbd - model->VDMOStype * ceqgb); |
|
|
|
*(ckt->CKTrhs + here->VDMOSdNodePrime) += |
|
|
|
(ceqbd - cdreq + model->VDMOStype * ceqgd); |
|
|
|
*(ckt->CKTrhs + here->VDMOSsNodePrime) += |
|
|
|
cdreq + ceqbs + model->VDMOStype * ceqgs; |
|
|
|
/* |
|
|
|
* load y matrix |
|
|
|
*/ |
|
|
|
|
|
|
|
*(here->VDMOSDdPtr) += (here->VDMOSdrainConductance); |
|
|
|
*(here->VDMOSGgPtr) += (here->VDMOSgateConductance); //((gcgd + gcgs + gcgb)); |
|
|
|
*(here->VDMOSSsPtr) += (here->VDMOSsourceConductance); |
|
|
|
*(here->VDMOSBbPtr) += (here->VDMOSgbd + here->VDMOSgbs + gcgb); |
|
|
|
*(here->VDMOSDPdpPtr) += |
|
|
|
(here->VDMOSdrainConductance + here->VDMOSgds + |
|
|
|
here->VDMOSgbd + xrev*(here->VDMOSgm + here->VDMOSgmbs) + gcgd); |
|
|
|
*(here->VDMOSSPspPtr) += |
|
|
|
(here->VDMOSsourceConductance + here->VDMOSgds + |
|
|
|
here->VDMOSgbs + xnrm*(here->VDMOSgm + here->VDMOSgmbs) + gcgs); |
|
|
|
*(here->VDMOSGPgpPtr) += |
|
|
|
(here->VDMOSgateConductance) + (gcgd + gcgs + gcgb); |
|
|
|
*(here->VDMOSGgpPtr) += (-here->VDMOSgateConductance); |
|
|
|
*(here->VDMOSDdpPtr) += (-here->VDMOSdrainConductance); |
|
|
|
*(here->VDMOSGPgPtr) += (-here->VDMOSgateConductance); |
|
|
|
*(here->VDMOSGPbPtr) -= gcgb; |
|
|
|
*(here->VDMOSGPdpPtr) -= gcgd; |
|
|
|
*(here->VDMOSGPspPtr) -= gcgs; |
|
|
|
*(here->VDMOSSspPtr) += (-here->VDMOSsourceConductance); |
|
|
|
*(here->VDMOSBgpPtr) -= gcgb; |
|
|
|
*(here->VDMOSBdpPtr) -= here->VDMOSgbd; |
|
|
|
*(here->VDMOSBspPtr) -= here->VDMOSgbs; |
|
|
|
*(here->VDMOSDPdPtr) += (-here->VDMOSdrainConductance); |
|
|
|
*(here->VDMOSDPgpPtr) += ((xnrm - xrev)*here->VDMOSgm - gcgd); |
|
|
|
*(here->VDMOSDPbPtr) += (-here->VDMOSgbd + (xnrm - xrev)*here->VDMOSgmbs); |
|
|
|
*(here->VDMOSDPspPtr) += (-here->VDMOSgds - xnrm* |
|
|
|
(here->VDMOSgm + here->VDMOSgmbs)); |
|
|
|
*(here->VDMOSSPgpPtr) += (-(xnrm - xrev)*here->VDMOSgm - gcgs); |
|
|
|
*(here->VDMOSSPsPtr) += (-here->VDMOSsourceConductance); |
|
|
|
*(here->VDMOSSPbPtr) += (-here->VDMOSgbs - (xnrm - xrev)*here->VDMOSgmbs); |
|
|
|
*(here->VDMOSSPdpPtr) += (-here->VDMOSgds - xrev* |
|
|
|
(here->VDMOSgm + here->VDMOSgmbs)); |
|
|
|
} |
|
|
|
} |
|
|
|
return(OK); |
|
|
|
|