You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
625 lines
21 KiB
625 lines
21 KiB
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1988 Min-Chie Jeng, Hong J. Park, Thomas L. Quarles
|
|
**********/
|
|
|
|
#include "ngspice.h"
|
|
#include <stdio.h>
|
|
#include "cktdefs.h"
|
|
#include "bsim2def.h"
|
|
#include "trandefs.h"
|
|
#include "const.h"
|
|
#include "suffix.h"
|
|
|
|
/* This routine evaluates the drain current, its derivatives and the
|
|
* charges associated with the gate,bulk and drain terminal
|
|
* using the B2 (Berkeley Short-Channel IGFET Model) Equations.
|
|
*/
|
|
void
|
|
B2evaluate(Vds,Vbs,Vgs,here,model,gm,gds,gmb,qg,qb,qd,cgg,cgd,cgs,
|
|
cbg,cbd,cbs,cdg,cdd,cds,Ids,von,vdsat,ckt)
|
|
|
|
CKTcircuit *ckt;
|
|
B2model *model;
|
|
B2instance *here;
|
|
double Vds,Vbs,Vgs;
|
|
double *gm,*gds,*gmb,*qg,*qb,*qd,*cgg,*cgd,*cgs,*cbg;
|
|
double *cbd,*cbs,*cdg,*cdd,*cds,*Ids,*von,*vdsat;
|
|
{
|
|
double Vth, Vdsat;
|
|
double Phisb, T1s, Eta, Gg, Aa, Inv_Aa, U1, U1s, Vc, Kk, SqrtKk;
|
|
double dPhisb_dVb, dT1s_dVb, dVth_dVb, dVth_dVd, dAa_dVb, dVc_dVd;
|
|
double dVc_dVg, dVc_dVb, dKk_dVc, dVdsat_dVd, dVdsat_dVg, dVdsat_dVb;
|
|
double dUvert_dVg, dUvert_dVd, dUvert_dVb, Inv_Kk;
|
|
double dUtot_dVd, dUtot_dVb, dUtot_dVg, Ai, Bi, Vghigh, Vglow, Vgeff, Vof;
|
|
double Vbseff, Vgst, Vgdt, Qbulk, Utot;
|
|
double T0, T1, T2, T3, T4, T5, Arg1, Arg2, Exp0;
|
|
double tmp, tmp1, tmp2, tmp3, Uvert, Beta1, Beta2, Beta0, dGg_dVb, Exp1;
|
|
double T6, T7, T8, T9, n, ExpArg, ExpArg1;
|
|
double Beta, dQbulk_dVb, dVgdt_dVg, dVgdt_dVd;
|
|
double dVbseff_dVb, Ua, Ub, dVgdt_dVb, dQbulk_dVd;
|
|
double Con1, Con3, Con4, SqrVghigh, SqrVglow, CubVghigh, CubVglow;
|
|
double delta, Coeffa, Coeffb, Coeffc, Coeffd, Inv_Uvert, Inv_Utot;
|
|
double Inv_Vdsat, tanh, Sqrsech, dBeta1_dVb, dU1_dVd, dU1_dVg, dU1_dVb;
|
|
double Betaeff, FR, dFR_dVd, dFR_dVg, dFR_dVb, Betas, Beta3, Beta4;
|
|
double dBeta_dVd, dBeta_dVg, dBeta_dVb, dVgeff_dVg, dVgeff_dVd, dVgeff_dVb;
|
|
double dCon3_dVd, dCon3_dVb, dCon4_dVd, dCon4_dVb, dCoeffa_dVd, dCoeffa_dVb;
|
|
double dCoeffb_dVd, dCoeffb_dVb, dCoeffc_dVd, dCoeffc_dVb;
|
|
double dCoeffd_dVd, dCoeffd_dVb;
|
|
int ChargeComputationNeeded;
|
|
int valuetypeflag; /* added 3/19/90 JSD */
|
|
|
|
if ((ckt->CKTmode & (MODEAC | MODETRAN)) ||
|
|
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ||
|
|
(ckt->CKTmode & MODEINITSMSIG) )
|
|
{ ChargeComputationNeeded = 1;
|
|
}
|
|
else
|
|
{ ChargeComputationNeeded = 0;
|
|
}
|
|
|
|
if (Vbs < model->B2vbb2) Vbs = model->B2vbb2;
|
|
if (Vgs > model->B2vgg2) Vgs = model->B2vgg2;
|
|
if (Vds > model->B2vdd2) Vds = model->B2vdd2;
|
|
|
|
/* Threshold Voltage. */
|
|
if (Vbs <= 0.0)
|
|
{ Phisb = here->pParam->B2phi - Vbs;
|
|
dPhisb_dVb = -1.0;
|
|
T1s = sqrt(Phisb);
|
|
dT1s_dVb = -0.5 / T1s;
|
|
}
|
|
else
|
|
{ tmp = here->pParam->B2phi / (here->pParam->B2phi + Vbs);
|
|
Phisb = here->pParam->B2phi * tmp;
|
|
dPhisb_dVb = -tmp * tmp;
|
|
T1s = here->pParam->Phis3 / (here->pParam->B2phi + 0.5 * Vbs);
|
|
dT1s_dVb = -0.5 * T1s * T1s / here->pParam->Phis3;
|
|
}
|
|
|
|
Eta = here->pParam->B2eta0 + here->pParam->B2etaB * Vbs;
|
|
Ua = here->pParam->B2ua0 + here->pParam->B2uaB * Vbs;
|
|
Ub = here->pParam->B2ub0 + here->pParam->B2ubB * Vbs;
|
|
U1s = here->pParam->B2u10 + here->pParam->B2u1B * Vbs;
|
|
|
|
Vth = here->pParam->B2vfb + here->pParam->B2phi + here->pParam->B2k1
|
|
* T1s - here->pParam->B2k2 * Phisb - Eta * Vds;
|
|
dVth_dVd = -Eta;
|
|
dVth_dVb = here->pParam->B2k1 * dT1s_dVb + here->pParam->B2k2
|
|
- here->pParam->B2etaB * Vds;
|
|
|
|
Vgst = Vgs - Vth;
|
|
|
|
tmp = 1.0 / (1.744 + 0.8364 * Phisb);
|
|
Gg = 1.0 - tmp;
|
|
dGg_dVb = 0.8364 * tmp * tmp * dPhisb_dVb;
|
|
T0 = Gg / T1s;
|
|
tmp1 = 0.5 * T0 * here->pParam->B2k1;
|
|
Aa = 1.0 + tmp1;
|
|
dAa_dVb = (Aa - 1.0) * (dGg_dVb / Gg - dT1s_dVb / T1s);
|
|
Inv_Aa = 1.0 / Aa;
|
|
|
|
Vghigh = here->pParam->B2vghigh;
|
|
Vglow = here->pParam->B2vglow;
|
|
|
|
if ((Vgst >= Vghigh) || (here->pParam->B2n0 == 0.0))
|
|
{ Vgeff = Vgst;
|
|
dVgeff_dVg = 1.0;
|
|
dVgeff_dVd = -dVth_dVd;
|
|
dVgeff_dVb = -dVth_dVb;
|
|
}
|
|
else
|
|
{ Vof = here->pParam->B2vof0 + here->pParam->B2vofB * Vbs
|
|
+ here->pParam->B2vofD * Vds;
|
|
n = here->pParam->B2n0 + here->pParam->B2nB / T1s
|
|
+ here->pParam->B2nD * Vds;
|
|
tmp = 0.5 / (n * model->B2Vtm);
|
|
|
|
ExpArg1 = -Vds / model->B2Vtm;
|
|
ExpArg1 = MAX(ExpArg1, -30.0);
|
|
Exp1 = exp(ExpArg1);
|
|
tmp1 = 1.0 - Exp1;
|
|
tmp1 = MAX(tmp1, 1.0e-18);
|
|
tmp2 = 2.0 * Aa * tmp1;
|
|
|
|
if (Vgst <= Vglow)
|
|
{
|
|
ExpArg = Vgst * tmp;
|
|
ExpArg = MAX(ExpArg, -30.0);
|
|
Exp0 = exp(0.5 * Vof + ExpArg);
|
|
Vgeff = sqrt(tmp2) * model->B2Vtm * Exp0;
|
|
T0 = n * model->B2Vtm;
|
|
dVgeff_dVg = Vgeff * tmp;
|
|
dVgeff_dVd = dVgeff_dVg * (n / tmp1 * Exp1 - dVth_dVd - Vgst
|
|
* here->pParam->B2nD / n + T0 * here->pParam->B2vofD);
|
|
dVgeff_dVb = dVgeff_dVg * (here->pParam->B2vofB * T0
|
|
- dVth_dVb + here->pParam->B2nB * Vgst
|
|
/ (n * T1s * T1s) * dT1s_dVb + T0 * Inv_Aa * dAa_dVb);
|
|
}
|
|
else
|
|
{
|
|
ExpArg = Vglow * tmp;
|
|
ExpArg = MAX(ExpArg, -30.0);
|
|
Exp0 = exp(0.5 * Vof + ExpArg);
|
|
Vgeff = sqrt(2.0 * Aa * (1.0 - Exp1)) * model->B2Vtm * Exp0;
|
|
Con1 = Vghigh;
|
|
Con3 = Vgeff;
|
|
Con4 = Con3 * tmp;
|
|
SqrVghigh = Vghigh * Vghigh;
|
|
SqrVglow = Vglow * Vglow;
|
|
CubVghigh = Vghigh * SqrVghigh;
|
|
CubVglow = Vglow * SqrVglow;
|
|
T0 = 2.0 * Vghigh;
|
|
T1 = 2.0 * Vglow;
|
|
T2 = 3.0 * SqrVghigh;
|
|
T3 = 3.0 * SqrVglow;
|
|
T4 = Vghigh - Vglow;
|
|
T5 = SqrVghigh - SqrVglow;
|
|
T6 = CubVghigh - CubVglow;
|
|
T7 = Con1 - Con3;
|
|
delta = (T1 - T0) * T6 + (T2 - T3) * T5 + (T0 * T3 - T1 * T2) * T4;
|
|
delta = 1.0 / delta;
|
|
Coeffb = (T1 - Con4 * T0) * T6 + (Con4 * T2 - T3) * T5
|
|
+ (T0 * T3 - T1 * T2) * T7;
|
|
Coeffc = (Con4 - 1.0) * T6 + (T2 - T3) * T7 + (T3 - Con4 * T2) * T4;
|
|
Coeffd = (T1 - T0) * T7 + (1.0 - Con4) * T5 + (Con4 * T0 - T1) * T4;
|
|
Coeffa = SqrVghigh * (Coeffc + Coeffd * T0);
|
|
Vgeff = (Coeffa + Vgst * (Coeffb + Vgst * (Coeffc + Vgst * Coeffd)))
|
|
* delta;
|
|
dVgeff_dVg = (Coeffb + Vgst * (2.0 * Coeffc + 3.0 * Vgst * Coeffd))
|
|
* delta;
|
|
T7 = Con3 * tmp;
|
|
T8 = dT1s_dVb * here->pParam->B2nB / (T1s * T1s * n);
|
|
T9 = n * model->B2Vtm;
|
|
dCon3_dVd = T7 * (n * Exp1 / tmp1 - Vglow * here->pParam->B2nD
|
|
/ n + T9 * here->pParam->B2vofD);
|
|
dCon3_dVb = T7 * (T9 * Inv_Aa * dAa_dVb + Vglow * T8
|
|
+ T9 * here->pParam->B2vofB);
|
|
dCon4_dVd = tmp * dCon3_dVd - T7 * here->pParam->B2nD / n;
|
|
dCon4_dVb = tmp * dCon3_dVb + T7 * T8;
|
|
|
|
dCoeffb_dVd = dCon4_dVd * (T2 * T5 - T0 * T6) + dCon3_dVd
|
|
* (T1 * T2 - T0 * T3);
|
|
dCoeffc_dVd = dCon4_dVd * (T6 - T2 * T4) + dCon3_dVd * (T3 - T2);
|
|
dCoeffd_dVd = dCon4_dVd * (T0 * T4 - T5) + dCon3_dVd * (T0 - T1);
|
|
dCoeffa_dVd = SqrVghigh * (dCoeffc_dVd + dCoeffd_dVd * T0);
|
|
|
|
dVgeff_dVd = -dVgeff_dVg * dVth_dVd + (dCoeffa_dVd + Vgst
|
|
* (dCoeffb_dVd + Vgst * (dCoeffc_dVd + Vgst
|
|
* dCoeffd_dVd))) * delta;
|
|
|
|
dCoeffb_dVb = dCon4_dVb * (T2 * T5 - T0 * T6) + dCon3_dVb
|
|
* (T1 * T2 - T0 * T3);
|
|
dCoeffc_dVb = dCon4_dVb * (T6 - T2 * T4) + dCon3_dVb * (T3 - T2);
|
|
dCoeffd_dVb = dCon4_dVb * (T0 * T4 - T5) + dCon3_dVb * (T0 - T1);
|
|
dCoeffa_dVb = SqrVghigh * (dCoeffc_dVb + dCoeffd_dVb * T0);
|
|
|
|
dVgeff_dVb = -dVgeff_dVg * dVth_dVb + (dCoeffa_dVb + Vgst
|
|
* (dCoeffb_dVb + Vgst * (dCoeffc_dVb + Vgst
|
|
* dCoeffd_dVb))) * delta;
|
|
}
|
|
}
|
|
|
|
if (Vgeff > 0.0)
|
|
{
|
|
Uvert = 1.0 + Vgeff * (Ua + Vgeff * Ub);
|
|
Uvert = MAX(Uvert, 0.2);
|
|
Inv_Uvert = 1.0 / Uvert;
|
|
T8 = Ua + 2.0 * Ub * Vgeff;
|
|
dUvert_dVg = T8 * dVgeff_dVg;
|
|
dUvert_dVd = T8 * dVgeff_dVd;
|
|
dUvert_dVb = T8 * dVgeff_dVb + Vgeff * (here->pParam->B2uaB
|
|
+ Vgeff * here->pParam->B2ubB);
|
|
|
|
T8 = U1s * Inv_Aa * Inv_Uvert;
|
|
Vc = T8 * Vgeff;
|
|
T9 = Vc * Inv_Uvert;
|
|
dVc_dVg = T8 * dVgeff_dVg - T9 * dUvert_dVg;
|
|
dVc_dVd = T8 * dVgeff_dVd - T9 * dUvert_dVd;
|
|
dVc_dVb = T8 * dVgeff_dVb + here->pParam->B2u1B * Vgeff * Inv_Aa
|
|
* Inv_Uvert - Vc * Inv_Aa * dAa_dVb - T9 * dUvert_dVb;
|
|
|
|
|
|
tmp2 = sqrt(1.0 + 2.0 * Vc);
|
|
Kk = 0.5 * (1.0 + Vc + tmp2);
|
|
Inv_Kk = 1.0 / Kk;
|
|
dKk_dVc = 0.5 + 0.5 / tmp2;
|
|
SqrtKk = sqrt(Kk);
|
|
|
|
T8 = Inv_Aa / SqrtKk;
|
|
Vdsat = Vgeff * T8;
|
|
Vdsat = MAX(Vdsat, 1.0e-18);
|
|
Inv_Vdsat = 1.0 / Vdsat;
|
|
T9 = 0.5 * Vdsat * Inv_Kk * dKk_dVc;
|
|
dVdsat_dVd = T8 * dVgeff_dVd - T9 * dVc_dVd;
|
|
dVdsat_dVg = T8 * dVgeff_dVg - T9 * dVc_dVg;
|
|
dVdsat_dVb = T8 * dVgeff_dVb - T9 * dVc_dVb - Vdsat* Inv_Aa * dAa_dVb;
|
|
|
|
Beta0 = here->pParam->B2beta0 + here->pParam->B2beta0B * Vbs;
|
|
Betas = here->pParam->B2betas0 + here->pParam->B2betasB * Vbs;
|
|
Beta2 = here->pParam->B2beta20 + here->pParam->B2beta2B * Vbs
|
|
+ here->pParam->B2beta2G * Vgs;
|
|
Beta3 = here->pParam->B2beta30 + here->pParam->B2beta3B * Vbs
|
|
+ here->pParam->B2beta3G * Vgs;
|
|
Beta4 = here->pParam->B2beta40 + here->pParam->B2beta4B * Vbs
|
|
+ here->pParam->B2beta4G * Vgs;
|
|
Beta1 = Betas - (Beta0 + model->B2vdd * (Beta3 - model->B2vdd
|
|
* Beta4));
|
|
|
|
T0 = Vds * Beta2 * Inv_Vdsat;
|
|
T0 = MIN(T0, 30.0);
|
|
T1 = exp(T0);
|
|
T2 = T1 * T1;
|
|
T3 = T2 + 1.0;
|
|
tanh = (T2 - 1.0) / T3;
|
|
Sqrsech = 4.0 * T2 / (T3 * T3);
|
|
|
|
Beta = Beta0 + Beta1 * tanh + Vds * (Beta3 - Beta4 * Vds);
|
|
T4 = Beta1 * Sqrsech * Inv_Vdsat;
|
|
T5 = model->B2vdd * tanh;
|
|
dBeta_dVd = Beta3 - 2.0 * Beta4 * Vds + T4 * (Beta2 - T0 * dVdsat_dVd);
|
|
dBeta_dVg = T4 * (here->pParam->B2beta2G * Vds - T0 * dVdsat_dVg)
|
|
+ here->pParam->B2beta3G * (Vds - T5)
|
|
- here->pParam->B2beta4G * (Vds * Vds - model->B2vdd * T5);
|
|
dBeta1_dVb = here->pParam->Arg;
|
|
dBeta_dVb = here->pParam->B2beta0B + dBeta1_dVb * tanh + Vds
|
|
* (here->pParam->B2beta3B - Vds * here->pParam->B2beta4B)
|
|
+ T4 * (here->pParam->B2beta2B * Vds - T0 * dVdsat_dVb);
|
|
|
|
|
|
if (Vgst > Vglow)
|
|
{
|
|
if (Vds <= Vdsat) /* triode region */
|
|
{
|
|
T3 = Vds * Inv_Vdsat;
|
|
T4 = T3 - 1.0;
|
|
T2 = 1.0 - here->pParam->B2u1D * T4 * T4;
|
|
U1 = U1s * T2;
|
|
Utot = Uvert + U1 * Vds;
|
|
Utot = MAX(Utot, 0.5);
|
|
Inv_Utot = 1.0 / Utot;
|
|
T5 = 2.0 * U1s * here->pParam->B2u1D * Inv_Vdsat * T4;
|
|
dU1_dVd = T5 * (T3 * dVdsat_dVd - 1.0);
|
|
dU1_dVg = T5 * T3 * dVdsat_dVg;
|
|
dU1_dVb = T5 * T3 * dVdsat_dVb + here->pParam->B2u1B * T2;
|
|
dUtot_dVd = dUvert_dVd + U1 + Vds * dU1_dVd;
|
|
dUtot_dVg = dUvert_dVg + Vds * dU1_dVg;
|
|
dUtot_dVb = dUvert_dVb + Vds * dU1_dVb;
|
|
|
|
tmp1 = (Vgeff - 0.5 * Aa * Vds);
|
|
tmp3 = tmp1 * Vds;
|
|
Betaeff = Beta * Inv_Utot;
|
|
*Ids = Betaeff * tmp3;
|
|
T6 = *Ids / Betaeff * Inv_Utot;
|
|
*gds = T6 * (dBeta_dVd - Betaeff * dUtot_dVd) + Betaeff * (tmp1
|
|
+ (dVgeff_dVd - 0.5 * Aa) * Vds);
|
|
*gm = T6 * (dBeta_dVg - Betaeff * dUtot_dVg) + Betaeff * Vds
|
|
* dVgeff_dVg;
|
|
*gmb = T6 * (dBeta_dVb - Betaeff * dUtot_dVb) + Betaeff * Vds
|
|
* (dVgeff_dVb - 0.5 * Vds * dAa_dVb);
|
|
}
|
|
else /* Saturation */
|
|
{ tmp1 = Vgeff * Inv_Aa * Inv_Kk;
|
|
tmp3 = 0.5 * Vgeff * tmp1;
|
|
Betaeff = Beta * Inv_Uvert;
|
|
*Ids = Betaeff * tmp3;
|
|
T0 = *Ids / Betaeff * Inv_Uvert;
|
|
T1 = Betaeff * Vgeff * Inv_Aa * Inv_Kk;
|
|
T2 = *Ids * Inv_Kk * dKk_dVc;
|
|
|
|
if (here->pParam->B2ai0 != 0.0)
|
|
{
|
|
Ai = here->pParam->B2ai0 + here->pParam->B2aiB * Vbs;
|
|
Bi = here->pParam->B2bi0 + here->pParam->B2biB * Vbs;
|
|
T5 = Bi / (Vds - Vdsat);
|
|
T5 = MIN(T5, 30.0);
|
|
T6 = exp(-T5);
|
|
FR = 1.0 + Ai * T6;
|
|
T7 = T5 / (Vds - Vdsat);
|
|
T8 = (1.0 - FR) * T7;
|
|
dFR_dVd = T8 * (dVdsat_dVd - 1.0);
|
|
dFR_dVg = T8 * dVdsat_dVg;
|
|
dFR_dVb = T8 * dVdsat_dVb + T6 * (here->pParam->B2aiB - Ai
|
|
* here->pParam->B2biB / (Vds - Vdsat));
|
|
|
|
*gds = (T0 * (dBeta_dVd - Betaeff * dUvert_dVd) + T1
|
|
* dVgeff_dVd - T2 * dVc_dVd) * FR + *Ids * dFR_dVd;
|
|
*gm = (T0 * (dBeta_dVg - Betaeff * dUvert_dVg)
|
|
+ T1 * dVgeff_dVg - T2 * dVc_dVg) * FR + *Ids * dFR_dVg;
|
|
*gmb = (T0 * (dBeta_dVb - Betaeff * dUvert_dVb) + T1
|
|
* dVgeff_dVb - T2 * dVc_dVb - *Ids * Inv_Aa * dAa_dVb)
|
|
* FR + *Ids * dFR_dVb;
|
|
*Ids *= FR;
|
|
}
|
|
else
|
|
{ *gds = T0 * (dBeta_dVd - Betaeff * dUvert_dVd) + T1
|
|
* dVgeff_dVd - T2 * dVc_dVd;
|
|
*gm = T0 * (dBeta_dVg - Betaeff * dUvert_dVg) + T1 * dVgeff_dVg
|
|
- T2 * dVc_dVg;
|
|
*gmb = T0 * (dBeta_dVb - Betaeff * dUvert_dVb) + T1
|
|
* dVgeff_dVb - T2 * dVc_dVb - *Ids * Inv_Aa * dAa_dVb;
|
|
}
|
|
} /* end of Saturation */
|
|
}
|
|
else
|
|
{ T0 = Exp0 * Exp0;
|
|
T1 = Exp1;
|
|
*Ids = Beta * model->B2Vtm * model->B2Vtm * T0 * (1.0 - T1);
|
|
T2 = *Ids / Beta;
|
|
T4 = n * model->B2Vtm;
|
|
T3 = *Ids / T4;
|
|
if ((Vds > Vdsat) && here->pParam->B2ai0 != 0.0)
|
|
{ Ai = here->pParam->B2ai0 + here->pParam->B2aiB * Vbs;
|
|
Bi = here->pParam->B2bi0 + here->pParam->B2biB * Vbs;
|
|
T5 = Bi / (Vds - Vdsat);
|
|
T5 = MIN(T5, 30.0);
|
|
T6 = exp(-T5);
|
|
FR = 1.0 + Ai * T6;
|
|
T7 = T5 / (Vds - Vdsat);
|
|
T8 = (1.0 - FR) * T7;
|
|
dFR_dVd = T8 * (dVdsat_dVd - 1.0);
|
|
dFR_dVg = T8 * dVdsat_dVg;
|
|
dFR_dVb = T8 * dVdsat_dVb + T6 * (here->pParam->B2aiB - Ai
|
|
* here->pParam->B2biB / (Vds - Vdsat));
|
|
}
|
|
else
|
|
{ FR = 1.0;
|
|
dFR_dVd = 0.0;
|
|
dFR_dVg = 0.0;
|
|
dFR_dVb = 0.0;
|
|
}
|
|
|
|
*gds = (T2 * dBeta_dVd + T3 * (here->pParam->B2vofD * T4 - dVth_dVd
|
|
- here->pParam->B2nD * Vgst / n) + Beta * model->B2Vtm
|
|
* T0 * T1) * FR + *Ids * dFR_dVd;
|
|
*gm = (T2 * dBeta_dVg + T3) * FR + *Ids * dFR_dVg;
|
|
*gmb = (T2 * dBeta_dVb + T3 * (here->pParam->B2vofB * T4 - dVth_dVb
|
|
+ here->pParam->B2nB * Vgst / (n * T1s * T1s) * dT1s_dVb)) * FR
|
|
+ *Ids * dFR_dVb;
|
|
*Ids *= FR;
|
|
}
|
|
}
|
|
else
|
|
{ *Ids = 0.0;
|
|
*gm = 0.0;
|
|
*gds = 0.0;
|
|
*gmb = 0.0;
|
|
}
|
|
|
|
/* Some Limiting of DC Parameters */
|
|
*gds = MAX(*gds,1.0e-20);
|
|
|
|
|
|
if ((model->B2channelChargePartitionFlag > 1)
|
|
|| ((!ChargeComputationNeeded) &&
|
|
(model->B2channelChargePartitionFlag > -5)))
|
|
{
|
|
*qg = 0.0;
|
|
*qd = 0.0;
|
|
*qb = 0.0;
|
|
*cgg = 0.0;
|
|
*cgs = 0.0;
|
|
*cgd = 0.0;
|
|
*cdg = 0.0;
|
|
*cds = 0.0;
|
|
*cdd = 0.0;
|
|
*cbg = 0.0;
|
|
*cbs = 0.0;
|
|
*cbd = 0.0;
|
|
goto finished;
|
|
}
|
|
else
|
|
{
|
|
if (Vbs < 0.0)
|
|
{ Vbseff = Vbs;
|
|
dVbseff_dVb = 1.0;
|
|
}
|
|
else
|
|
{ Vbseff = here->pParam->B2phi - Phisb;
|
|
dVbseff_dVb = -dPhisb_dVb;
|
|
}
|
|
Arg1 = Vgs - Vbseff - here->pParam->B2vfb;
|
|
Arg2 = Arg1 - Vgst;
|
|
Qbulk = here->pParam->One_Third_CoxWL * Arg2;
|
|
dQbulk_dVb = here->pParam->One_Third_CoxWL * (dVth_dVb - dVbseff_dVb);
|
|
dQbulk_dVd = here->pParam->One_Third_CoxWL * dVth_dVd;
|
|
if (Arg1 <= 0.0)
|
|
{
|
|
*qg = here->pParam->CoxWL * Arg1;
|
|
*qb = -(*qg);
|
|
*qd = 0.0;
|
|
|
|
*cgg = here->pParam->CoxWL;
|
|
*cgd = 0.0;
|
|
*cgs = -*cgg * (1.0 - dVbseff_dVb);
|
|
|
|
*cdg = 0.0;
|
|
*cdd = 0.0;
|
|
*cds = 0.0;
|
|
|
|
*cbg = -here->pParam->CoxWL;
|
|
*cbd = 0.0;
|
|
*cbs = -*cgs;
|
|
}
|
|
else if (Vgst <= 0.0)
|
|
{ T2 = Arg1 / Arg2;
|
|
T3 = T2 * T2 * (here->pParam->CoxWL - here->pParam->Two_Third_CoxWL
|
|
* T2);
|
|
|
|
*qg = here->pParam->CoxWL * Arg1 * (1.0 - T2 * (1.0 - T2 / 3.0));
|
|
*qb = -(*qg);
|
|
*qd = 0.0;
|
|
|
|
*cgg = here->pParam->CoxWL * (1.0 - T2 * (2.0 - T2));
|
|
tmp = T3 * dVth_dVb - (*cgg + T3) * dVbseff_dVb;
|
|
*cgd = T3 * dVth_dVd;
|
|
*cgs = -(*cgg + *cgd + tmp);
|
|
|
|
*cdg = 0.0;
|
|
*cdd = 0.0;
|
|
*cds = 0.0;
|
|
|
|
*cbg = -*cgg;
|
|
*cbd = -*cgd;
|
|
*cbs = -*cgs;
|
|
}
|
|
else
|
|
{ if (Vgst < here->pParam->B2vghigh)
|
|
{ Uvert = 1.0 + Vgst * (Ua + Vgst * Ub);
|
|
Uvert = MAX(Uvert, 0.2);
|
|
Inv_Uvert = 1.0 / Uvert;
|
|
dUvert_dVg = Ua + 2.0 * Ub * Vgst;
|
|
dUvert_dVd = -dUvert_dVg * dVth_dVd;
|
|
dUvert_dVb = -dUvert_dVg * dVth_dVb + Vgst
|
|
* (here->pParam->B2uaB + Vgst * here->pParam->B2ubB);
|
|
|
|
T8 = U1s * Inv_Aa * Inv_Uvert;
|
|
Vc = T8 * Vgst;
|
|
T9 = Vc * Inv_Uvert;
|
|
dVc_dVg = T8 - T9 * dUvert_dVg;
|
|
dVc_dVd = -T8 * dVth_dVd - T9 * dUvert_dVd;
|
|
dVc_dVb = -T8 * dVth_dVb + here->pParam->B2u1B * Vgst * Inv_Aa
|
|
* Inv_Uvert - Vc * Inv_Aa * dAa_dVb - T9 * dUvert_dVb;
|
|
|
|
tmp2 = sqrt(1.0 + 2.0 * Vc);
|
|
Kk = 0.5 * (1.0 + Vc + tmp2);
|
|
Inv_Kk = 1.0 / Kk;
|
|
dKk_dVc = 0.5 + 0.5 / tmp2;
|
|
SqrtKk = sqrt(Kk);
|
|
|
|
T8 = Inv_Aa / SqrtKk;
|
|
Vdsat = Vgst * T8;
|
|
T9 = 0.5 * Vdsat * Inv_Kk * dKk_dVc;
|
|
dVdsat_dVd = -T8 * dVth_dVd - T9 * dVc_dVd;
|
|
dVdsat_dVg = T8 - T9 * dVc_dVg;
|
|
dVdsat_dVb = -T8 * dVth_dVb - T9 * dVc_dVb
|
|
- Vdsat* Inv_Aa * dAa_dVb;
|
|
}
|
|
if (Vds >= Vdsat)
|
|
{ /* saturation region */
|
|
*cgg = here->pParam->Two_Third_CoxWL;
|
|
*cgd = -*cgg * dVth_dVd + dQbulk_dVd;
|
|
tmp = -*cgg * dVth_dVb + dQbulk_dVb;
|
|
*cgs = -(*cgg + *cgd + tmp);
|
|
|
|
*cbg = 0.0;
|
|
*cbd = -dQbulk_dVd;
|
|
*cbs = dQbulk_dVd + dQbulk_dVb;
|
|
|
|
*cdg = -0.4 * *cgg;
|
|
tmp = -*cdg * dVth_dVb;
|
|
*cdd = -*cdg * dVth_dVd;
|
|
*cds = -(*cdg + *cdd + tmp);
|
|
|
|
*qb = -Qbulk;
|
|
*qg = here->pParam->Two_Third_CoxWL * Vgst + Qbulk;
|
|
*qd = *cdg * Vgst;
|
|
}
|
|
else
|
|
{ /* linear region */
|
|
T7 = Vds / Vdsat;
|
|
T8 = Vgst / Vdsat;
|
|
T6 = T7 * T8;
|
|
T9 = 1.0 - T7;
|
|
Vgdt = Vgst * T9;
|
|
T0 = Vgst / (Vgst + Vgdt);
|
|
T1 = Vgdt / (Vgst + Vgdt);
|
|
T5 = T0 * T1;
|
|
T2 = 1.0 - T1 + T5;
|
|
T3 = 1.0 - T0 + T5;
|
|
|
|
dVgdt_dVg = T9 + T6 * dVdsat_dVg;
|
|
dVgdt_dVd = T6 * dVdsat_dVd - T8 -T9 * dVth_dVd;
|
|
dVgdt_dVb = T6 * dVdsat_dVb -T9 * dVth_dVb;
|
|
|
|
*qg = here->pParam->Two_Third_CoxWL * (Vgst + Vgdt
|
|
- Vgdt * T0) + Qbulk;
|
|
*qb = -Qbulk;
|
|
*qd = -here->pParam->One_Third_CoxWL * (0.2 * Vgdt
|
|
+ 0.8 * Vgst + Vgdt * T1
|
|
+ 0.2 * T5 * (Vgdt - Vgst));
|
|
|
|
*cgg = here->pParam->Two_Third_CoxWL * (T2 + T3 * dVgdt_dVg);
|
|
tmp = dQbulk_dVb + here->pParam->Two_Third_CoxWL * (T3 * dVgdt_dVb
|
|
- T2 * dVth_dVb);
|
|
*cgd = here->pParam->Two_Third_CoxWL * (T3 * dVgdt_dVd
|
|
- T2 * dVth_dVd) + dQbulk_dVd;
|
|
*cgs = -(*cgg + *cgd + tmp);
|
|
|
|
T2 = 0.8 - 0.4 * T1 * (2.0 * T1 + T0 + T0 * (T1 - T0));
|
|
T3 = 0.2 + T1 + T0 * (1.0 - 0.4 * T0 * (T1 + 3.0 * T0));
|
|
*cdg = -here->pParam->One_Third_CoxWL * (T2 + T3 * dVgdt_dVg);
|
|
tmp = here->pParam->One_Third_CoxWL * (T2 * dVth_dVb
|
|
- T3 * dVgdt_dVb);
|
|
*cdd = here->pParam->One_Third_CoxWL * (T2 * dVth_dVd
|
|
- T3 * dVgdt_dVd);
|
|
*cds = -(*cdg + tmp + *cdd);
|
|
|
|
*cbg = 0.0;
|
|
*cbd = -dQbulk_dVd;
|
|
*cbs = dQbulk_dVd + dQbulk_dVb;
|
|
}
|
|
}
|
|
}
|
|
|
|
finished: /* returning Values to Calling Routine */
|
|
valuetypeflag = (int) model->B2channelChargePartitionFlag;
|
|
switch (valuetypeflag)
|
|
{
|
|
case 0: *Ids = MAX(*Ids,1e-50);
|
|
break;
|
|
case -1: *Ids = MAX(*Ids,1e-50);
|
|
break;
|
|
case -2: *Ids = *gm;
|
|
break;
|
|
case -3: *Ids = *gds;
|
|
break;
|
|
case -4: *Ids = 1.0 / *gds;
|
|
break;
|
|
case -5: *Ids = *gmb;
|
|
break;
|
|
case -6: *Ids = *qg / 1.0e-12;
|
|
break;
|
|
case -7: *Ids = *qb / 1.0e-12;
|
|
break;
|
|
case -8: *Ids = *qd / 1.0e-12;
|
|
break;
|
|
case -9: *Ids = -(*qb + *qg + *qd) / 1.0e-12;
|
|
break;
|
|
case -10: *Ids = *cgg / 1.0e-12;
|
|
break;
|
|
case -11: *Ids = *cgd / 1.0e-12;
|
|
break;
|
|
case -12: *Ids = *cgs / 1.0e-12;
|
|
break;
|
|
case -13: *Ids = -(*cgg + *cgd + *cgs) / 1.0e-12;
|
|
break;
|
|
case -14: *Ids = *cbg / 1.0e-12;
|
|
break;
|
|
case -15: *Ids = *cbd / 1.0e-12;
|
|
break;
|
|
case -16: *Ids = *cbs / 1.0e-12;
|
|
break;
|
|
case -17: *Ids = -(*cbg + *cbd + *cbs) / 1.0e-12;
|
|
break;
|
|
case -18: *Ids = *cdg / 1.0e-12;
|
|
break;
|
|
case -19: *Ids = *cdd / 1.0e-12;
|
|
break;
|
|
case -20: *Ids = *cds / 1.0e-12;
|
|
break;
|
|
case -21: *Ids = -(*cdg + *cdd + *cds) / 1.0e-12;
|
|
break;
|
|
case -22: *Ids = -(*cgg + *cdg + *cbg) / 1.0e-12;
|
|
break;
|
|
case -23: *Ids = -(*cgd + *cdd + *cbd) / 1.0e-12;
|
|
break;
|
|
case -24: *Ids = -(*cgs + *cds + *cbs) / 1.0e-12;
|
|
break;
|
|
default: *Ids = MAX(*Ids, 1.0e-50);
|
|
break;
|
|
}
|
|
*von = Vth;
|
|
*vdsat = Vdsat;
|
|
}
|
|
|