📄 b1eval.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Hong J. Park, Thomas L. Quarles**********/#include "spice.h"#include <stdio.h>#include "util.h"#include "cktdefs.h"#include "bsim1def.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 B1 (Berkeley Short-Channel IGFET Model) Equations. */voidB1evaluate(vds,vbs,vgs,here,model,gmPointer,gdsPointer,gmbsPointer, qgPointer,qbPointer,qdPointer,cggbPointer,cgdbPointer,cgsbPointer, cbgbPointer,cbdbPointer,cbsbPointer,cdgbPointer,cddbPointer, cdsbPointer,cdrainPointer,vonPointer,vdsatPointer,ckt) register CKTcircuit *ckt; register B1model *model; register B1instance *here; double vds; double vbs; double vgs; double *gmPointer; double *gdsPointer; double *gmbsPointer; double *qgPointer; double *qbPointer; double *qdPointer; double *cggbPointer; double *cgdbPointer; double *cgsbPointer; double *cbgbPointer; double *cbdbPointer; double *cbsbPointer; double *cdgbPointer; double *cddbPointer; double *cdsbPointer; double *cdrainPointer; double *vonPointer; double *vdsatPointer; { double gm; double gds; double gmbs; double qg; double qb; double qd; double cggb; double cgdb; double cgsb; double cbgb; double cbdb; double cbsb; double cdgb; double cddb; double cdsb; double Vfb; double Phi; double K1; double K2; double Vdd; double Ugs; double Uds; double dUgsdVbs; double Leff; double dUdsdVbs; double dUdsdVds; double Eta; double dEtadVds; double dEtadVbs; double Vpb; double SqrtVpb; double Von; double Vth; double dVthdVbs; double dVthdVds; double Vgs_Vth; double DrainCurrent; double G; double A; double Arg; double dGdVbs; double dAdVbs; double Beta; double Beta_Vds_0; double BetaVdd; double dBetaVdd_dVds; double Beta0; double dBeta0dVds; double dBeta0dVbs; double VddSquare; double C1; double C2; double dBetaVdd_dVbs; double dBeta_Vds_0_dVbs; double dC1dVbs; double dC2dVbs; double dBetadVgs; double dBetadVds; double dBetadVbs; double VdsSat; double Argl1; double Argl2; double Vc; double Term1; double K; double Args1; double dVcdVgs; double dVcdVds; double dVcdVbs; double dKdVc; double dKdVgs; double dKdVds; double dKdVbs; double Args2; double Args3; double Warg1; double Vcut; double N; double N0; double NB; double ND; double Warg2; double Wds; double Wgs; double Ilimit; double Iexp; double Temp1; double Vth0; double Arg1; double Arg2; double Arg3; double Arg5; double Ent; double Vcom; double Vgb; double Vgb_Vfb; double VdsPinchoff; double EntSquare; double Vgs_VthSquare; double Argl3; double Argl4; double Argl5; double Argl6; double Argl7; double Argl8; double Argl9; double dEntdVds; double dEntdVbs; double cgbb; double cdbb; double cbbb; double WLCox; double Vtsquare; double Temp3; int ChargeComputationNeeded; double co4v15; if (ckt->CKTmode & (MODEAC | MODETRAN)) { ChargeComputationNeeded = 1; } else if (ckt->CKTmode & MODEINITSMSIG) { ChargeComputationNeeded = 1; } else if ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { ChargeComputationNeeded = 1; } else { ChargeComputationNeeded = 0; } Vfb = here->B1vfb; Phi = here->B1phi; K1 = here->B1K1; K2 = here->B1K2; Vdd = model->B1vdd; if((Ugs = here->B1ugs + here->B1ugsB * vbs) <= 0 ) { Ugs = 0; dUgsdVbs = 0.0; } else { dUgsdVbs = here->B1ugsB; } if((Uds = here->B1uds + here->B1udsB * vbs + here->B1udsD*(vds-Vdd)) <= 0 ) { Uds = 0.0; dUdsdVbs = dUdsdVds = 0.0; } else { Leff = here->B1l * 1.e6 - model->B1deltaL; /* Leff in um */ Uds = Uds / Leff; dUdsdVbs = here->B1udsB / Leff; dUdsdVds = here->B1udsD / Leff; } Eta = here->B1eta + here->B1etaB * vbs + here->B1etaD * (vds - Vdd); if( Eta <= 0 ) { Eta = 0; dEtadVds = dEtadVbs = 0.0 ; } else if ( Eta > 1 ) { Eta = 1; dEtadVds = dEtadVbs = 0; } else { dEtadVds = here->B1etaD; dEtadVbs = here->B1etaB; } if( vbs < 0 ) { Vpb = Phi - vbs; } else { Vpb = Phi; } SqrtVpb = sqrt( Vpb ); Von = Vfb + Phi + K1 * SqrtVpb - K2 * Vpb - Eta * vds; Vth = Von; dVthdVds = - Eta - dEtadVds * vds; dVthdVbs = K2 - 0.5 * K1 / SqrtVpb - dEtadVbs * vds; Vgs_Vth = vgs - Vth; G = 1. - 1./(1.744+0.8364 * Vpb); A = 1. + 0.5*G*K1/SqrtVpb; A = MAX( A, 1.0); /* Modified */ Arg = MAX(( 1 + Ugs * Vgs_Vth), 1.0); dGdVbs = -0.8364 * (1-G) * (1-G); dAdVbs = 0.25 * K1 / SqrtVpb *(2*dGdVbs + G/Vpb); if( Vgs_Vth < 0 ) { /* cutoff */ DrainCurrent = 0; gm = 0; gds = 0; gmbs = 0; goto SubthresholdComputation; } /* Quadratic Interpolation for Beta0 (Beta at vgs = 0, vds=Vds) */ Beta_Vds_0 = (here->B1betaZero + here->B1betaZeroB * vbs); BetaVdd = (here->B1betaVdd + here->B1betaVddB * vbs); dBetaVdd_dVds = MAX( here->B1betaVddD, 0.0); /* Modified */ if( vds > Vdd ) { Beta0 = BetaVdd + dBetaVdd_dVds * (vds - Vdd); dBeta0dVds = dBetaVdd_dVds; dBeta0dVbs = here->B1betaVddB; } else { VddSquare = Vdd * Vdd; C1 = ( -BetaVdd + Beta_Vds_0 + dBetaVdd_dVds * Vdd) / VddSquare; C2 = 2 * (BetaVdd - Beta_Vds_0) / Vdd - dBetaVdd_dVds; dBeta_Vds_0_dVbs = here->B1betaZeroB; dBetaVdd_dVbs = here->B1betaVddB; dC1dVbs = (dBeta_Vds_0_dVbs - dBetaVdd_dVbs) / VddSquare; dC2dVbs = dC1dVbs * (-2) * Vdd; Beta0 = (C1 * vds + C2) * vds + Beta_Vds_0; dBeta0dVds = 2*C1*vds + C2; dBeta0dVbs = dC1dVbs * vds * vds + dC2dVbs * vds + dBeta_Vds_0_dVbs; } /*Beta = Beta0 / ( 1 + Ugs * Vgs_Vth );*/ Beta = Beta0 / Arg ; dBetadVgs = - Beta * Ugs / Arg; dBetadVds = dBeta0dVds / Arg - dBetadVgs * dVthdVds ; dBetadVbs = dBeta0dVbs / Arg + Beta * Ugs * dVthdVbs / Arg - Beta * Vgs_Vth * dUgsdVbs / Arg; /*VdsSat = MAX( Vgs_Vth / ( A + Uds * Vgs_Vth ), 0.0);*/ if((Vc = Uds * Vgs_Vth / A) < 0.0 ) Vc=0.0; Term1 = sqrt( 1 + 2 * Vc ); K = 0.5 * ( 1 + Vc + Term1 ); VdsSat = MAX( Vgs_Vth / ( A * sqrt(K) ) , 0.0 ); if( vds < VdsSat ) { /* Triode Region */ /*Argl1 = 1 + Uds * vds;*/ Argl1 = MAX( (1 + Uds * vds), 1.); Argl2 = Vgs_Vth - 0.5 * A * vds; DrainCurrent = Beta * Argl2 * vds / Argl1; gm = (dBetadVgs * Argl2 * vds + Beta * vds) / Argl1; gds = (dBetadVds * Argl2 * vds + Beta * (Vgs_Vth - vds * dVthdVds - A * vds) - DrainCurrent * (vds * dUdsdVds + Uds )) / Argl1; gmbs = (dBetadVbs * Argl2 * vds + Beta * vds * (- dVthdVbs - 0.5 * vds * dAdVbs ) - DrainCurrent * vds * dUdsdVbs ) / Argl1; } else { /* Pinchoff (Saturation) Region */ Args1 = 1. + 1. / Term1; dVcdVgs = Uds / A; dVcdVds = Vgs_Vth * dUdsdVds / A - dVcdVgs * dVthdVds; dVcdVbs = ( Vgs_Vth * dUdsdVbs - Uds * (dVthdVbs + Vgs_Vth * dAdVbs / A ))/ A; dKdVc = 0.5* Args1; dKdVgs = dKdVc * dVcdVgs; dKdVds = dKdVc * dVcdVds; dKdVbs = dKdVc * dVcdVbs; Args2 = Vgs_Vth / A / K; Args3 = Args2 * Vgs_Vth; DrainCurrent = 0.5 * Beta * Args3; gm = 0.5 * Args3 * dBetadVgs + Beta * Args2 - DrainCurrent * dKdVgs / K; gds = 0.5 * Args3 * dBetadVds - Beta * Args2 * dVthdVds - DrainCurrent * dKdVds / K; gmbs = 0.5 * dBetadVbs * Args3 - Beta * Args2 *dVthdVbs - DrainCurrent * (dAdVbs / A + dKdVbs / K ); }SubthresholdComputation: N0 = here->B1subthSlope;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -