diff --git a/src/spicelib/devices/vdmos/vdmosask.c b/src/spicelib/devices/vdmos/vdmosask.c index fa266308e..3d419a77c 100644 --- a/src/spicelib/devices/vdmos/vdmosask.c +++ b/src/spicelib/devices/vdmos/vdmosask.c @@ -34,10 +34,10 @@ VDMOSask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, return(OK); case VDMOS_CGD: value->rValue = 2* *(ckt->CKTstate0 + here->VDMOScapgd); - return(OK); + return(OK); case VDMOS_M: value->rValue = here->VDMOSm; - return(OK); + return(OK); case VDMOS_L: value->rValue = here->VDMOSl; return(OK); @@ -96,19 +96,19 @@ VDMOSask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, value->rValue = here->VDMOSsourceConductance; return(OK); case VDMOS_SOURCERESIST: - if (here->VDMOSsNodePrime != here->VDMOSsNode) - value->rValue = 1.0 / here->VDMOSsourceConductance; - else - value->rValue = 0.0; + if (here->VDMOSsNodePrime != here->VDMOSsNode) + value->rValue = 1.0 / here->VDMOSsourceConductance; + else + value->rValue = 0.0; return(OK); case VDMOS_DRAINCONDUCT: value->rValue = here->VDMOSdrainConductance; return(OK); case VDMOS_DRAINRESIST: - if (here->VDMOSdNodePrime != here->VDMOSdNode) - value->rValue = 1.0 / here->VDMOSdrainConductance; - else - value->rValue = 0.0; + if (here->VDMOSdNodePrime != here->VDMOSdNode) + value->rValue = 1.0 / here->VDMOSdrainConductance; + else + value->rValue = 0.0; return(OK); case VDMOS_VON: value->rValue = here->VDMOSvon; diff --git a/src/spicelib/devices/vdmos/vdmosdset.c b/src/spicelib/devices/vdmos/vdmosdset.c index 5af9b97d0..ee3460614 100644 --- a/src/spicelib/devices/vdmos/vdmosdset.c +++ b/src/spicelib/devices/vdmos/vdmosdset.c @@ -87,16 +87,16 @@ VDMOSdSetup(GENmodel *inModel, CKTcircuit *ckt) vt = CONSTKoverQ * here->VDMOStemp; EffectiveLength=here->VDMOSl - 2*model->VDMOSlatDiff; - - if( (here->VDMOStSatCurDens == 0) || + + if( (here->VDMOStSatCurDens == 0) || (here->VDMOSdrainArea == 0) || (here->VDMOSsourceArea == 0)) { DrainSatCur = here->VDMOSm * here->VDMOStSatCur; SourceSatCur = here->VDMOSm * here->VDMOStSatCur; } else { - DrainSatCur = here->VDMOStSatCurDens * + DrainSatCur = here->VDMOStSatCurDens * here->VDMOSm * here->VDMOSdrainArea; - SourceSatCur = here->VDMOStSatCurDens * + SourceSatCur = here->VDMOStSatCurDens * here->VDMOSm * here->VDMOSsourceArea; } GateSourceOverlapCap = model->VDMOSgateSourceOverlapCapFactor * diff --git a/src/spicelib/devices/vdmos/vdmosload.c b/src/spicelib/devices/vdmos/vdmosload.c index 986aa00f9..358df4509 100644 --- a/src/spicelib/devices/vdmos/vdmosload.c +++ b/src/spicelib/devices/vdmos/vdmosload.c @@ -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); diff --git a/src/spicelib/devices/vdmos/vdmostemp.c b/src/spicelib/devices/vdmos/vdmostemp.c index 04fba206a..cbe7c291d 100644 --- a/src/spicelib/devices/vdmos/vdmostemp.c +++ b/src/spicelib/devices/vdmos/vdmostemp.c @@ -112,7 +112,7 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt) } } - + /* loop through all instances of the model */ for(here = VDMOSinstances(model); here!= NULL; here = VDMOSnextInstance(here)) { @@ -218,7 +218,7 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt) if(model->VDMOScapBDGiven) { czbd = here->VDMOStCbd * here->VDMOSm; } else { - if(model->VDMOSbulkCapFactorGiven) { + if(model->VDMOSbulkCapFactorGiven) { czbd=here->VDMOStCj*here->VDMOSm*here->VDMOSdrainArea; } else { czbd=0; @@ -299,7 +299,7 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt) } } else if (model->VDMOSsheetResistanceGiven) { if(model->VDMOSsheetResistance != 0) { - here->VDMOSdrainConductance = + here->VDMOSdrainConductance = here->VDMOSm / (model->VDMOSsheetResistance*here->VDMOSdrainSquares); } else { @@ -318,7 +318,7 @@ VDMOStemp(GENmodel *inModel, CKTcircuit *ckt) } else if (model->VDMOSsheetResistanceGiven) { if ((model->VDMOSsheetResistance != 0) && (here->VDMOSsourceSquares != 0)) { - here->VDMOSsourceConductance = + here->VDMOSsourceConductance = here->VDMOSm / (model->VDMOSsheetResistance*here->VDMOSsourceSquares); } else {