📄 mos2load.c
字号:
vt,here->MOS2sourceVcrit,&Check); vbd = vbs-vds; } else { vbd = DEVpnjlim(vbd,*(ckt->CKTstate0 + here->MOS2vbd), vt,here->MOS2drainVcrit,&Check); vbs = vbd + vds; } } else { /* ok - not one of the simple cases, so we have to * look at other possibilities */ if((ckt->CKTmode & MODEINITJCT) && !here->MOS2off) { vds= model->MOS2type * here->MOS2icVDS; vgs= model->MOS2type * here->MOS2icVGS; vbs= model->MOS2type * here->MOS2icVBS; if((vds==0) && (vgs==0) && (vbs==0) && ((ckt->CKTmode & (MODETRAN|MODEDCOP|MODEDCTRANCURVE)) || (!(ckt->CKTmode & MODEUIC)))) { vbs = -1; vgs = model->MOS2type * here->MOS2tVto; vds = 0; } } else { vbs=vgs=vds=0; } } /* now all the preliminaries are over - we can start doing the * real work */ vbd = vbs - vds; vgd = vgs - vds; vgb = vgs - vbs; /* bulk-source and bulk-drain doides * here we just evaluate the ideal diode current and the * correspoinding derivative (conductance). */next1: if(vbs <= 0) { here->MOS2gbs = SourceSatCur/vt; here->MOS2cbs = here->MOS2gbs*vbs; here->MOS2gbs += ckt->CKTgmin; } else { evbs = exp(vbs/vt); here->MOS2gbs = SourceSatCur*evbs/vt + ckt->CKTgmin; here->MOS2cbs = SourceSatCur * (evbs-1); } if(vbd <= 0) { here->MOS2gbd = DrainSatCur/vt; here->MOS2cbd = here->MOS2gbd *vbd; here->MOS2gbd += ckt->CKTgmin; } else { evbd = exp(vbd/vt); here->MOS2gbd = DrainSatCur*evbd/vt +ckt->CKTgmin; here->MOS2cbd = DrainSatCur *(evbd-1); } if(vds >= 0) { /* normal mode */ here->MOS2mode = 1; } else { /* inverse mode */ here->MOS2mode = -1; } { /* moseq2(vds,vbs,vgs,gm,gds,gmbs,qg,qc,qb, * cggb,cgdb,cgsb,cbgb,cbdb,cbsb) */ /* note: cgdb, cgsb, cbdb, cbsb never used */ /* * this routine evaluates the drain current, its derivatives and * the charges associated with the gate, channel and bulk * for mosfets * */ double arg; double sarg; double a4[4],b4[4],x4[8],poly4[8]; double beta1; double dsrgdb; double d2sdb2; double sphi; /* square root of phi */ double sphi3; /* square root of phi cubed */ double barg; double d2bdb2; double factor; double dbrgdb; double eta; double vbin; double argd; double args; double argss; double argsd; double argxs; double argxd; double daddb2; double dasdb2; double dbargd; double dbargs; double dbxwd; double dbxws; double dgddb2; double dgddvb; double dgdvds; double gamasd; double xwd; double xws; double ddxwd; double gammad; double vth; double cfs; double cdonco; double xn; double argg; double vgst; double sarg3; double sbiarg; double dgdvbs; double body; double gdbdv; double dodvbs; double dodvds; double dxndvd; double dxndvb; double udenom; double dudvgs; double dudvds; double dudvbs; double gammd2; double argv; double vgsx; double ufact; double ueff; double dsdvgs; double dsdvbs; double a1; double a3; double a; double b1; double b3; double b; double c1; double c; double d1; double fi; double p0; double p2; double p3; double p4; double p; double r3; double r; double ro; double s2; double s; double v1; double v2; double xv; double y3; double delta4; double xvalid; double bsarg; double dbsrdb; double bodys; double gdbdvs; double sargv; double xlfact; double dldsat; double xdv; double xlv; double vqchan; double dqdsat; double vl; double dfundg; double dfunds; double dfundb; double xls; double dldvgs; double dldvds; double dldvbs; double dfact; double clfact; double xleff; double deltal; double xwb; double vdson; double cdson; double didvds; double gdson; double gmw; double gbson; double expg; double xld; double xlamda = model->MOS2lambda; /* 'local' variables - these switch d & s around appropriately * so that we don't have to worry about vds < 0 */ double lvbs = here->MOS2mode==1?vbs:vbd; double lvds = here->MOS2mode*vds; double lvgs = here->MOS2mode==1?vgs:vgd; double phiMinVbs = here->MOS2tPhi - lvbs; double tmp; /* a temporary variable, not used for more than */ /* about 10 lines at a time */ int iknt; int jknt; int i; int j; /* * compute some useful quantities */ if (lvbs <= 0.0) { sarg = sqrt(phiMinVbs); dsrgdb = -0.5/sarg; d2sdb2 = 0.5*dsrgdb/phiMinVbs; } else { sphi = sqrt(here->MOS2tPhi); sphi3 = here->MOS2tPhi*sphi; sarg = sphi/(1.0+0.5*lvbs/here->MOS2tPhi); tmp = sarg/sphi3; dsrgdb = -0.5*sarg*tmp; d2sdb2 = -dsrgdb*tmp; } if ((lvds-lvbs) >= 0) { barg = sqrt(phiMinVbs+lvds); dbrgdb = -0.5/barg; d2bdb2 = 0.5*dbrgdb/(phiMinVbs+lvds); } else { barg = sphi/(1.0+0.5*(lvbs-lvds)/here->MOS2tPhi); tmp = barg/sphi3; dbrgdb = -0.5*barg*tmp; d2bdb2 = -dbrgdb*tmp; } /* * calculate threshold voltage (von) * narrow-channel effect */ /*XXX constant per device */ factor = 0.125*model->MOS2narrowFactor*2.0*M_PI*EPSSIL/ OxideCap*EffectiveLength; /*XXX constant per device */ eta = 1.0+factor; vbin = here->MOS2tVbi*model->MOS2type+factor*phiMinVbs; if ((model->MOS2gamma > 0.0) || (model->MOS2substrateDoping > 0.0)) { xwd = model->MOS2xd*barg; xws = model->MOS2xd*sarg; /* * short-channel effect with vds .ne. 0.0 */ argss = 0.0; argsd = 0.0; dbargs = 0.0; dbargd = 0.0; dgdvds = 0.0; dgddb2 = 0.0; if (model->MOS2junctionDepth > 0) { tmp = 2.0/model->MOS2junctionDepth; argxs = 1.0+xws*tmp; argxd = 1.0+xwd*tmp; args = sqrt(argxs); argd = sqrt(argxd); tmp = .5*model->MOS2junctionDepth/EffectiveLength; argss = tmp * (args-1.0); argsd = tmp * (argd-1.0); } gamasd = model->MOS2gamma*(1.0-argss-argsd); dbxwd = model->MOS2xd*dbrgdb; dbxws = model->MOS2xd*dsrgdb; if (model->MOS2junctionDepth > 0) { tmp = 0.5/EffectiveLength; dbargs = tmp*dbxws/args; dbargd = tmp*dbxwd/argd; dasdb2 = -model->MOS2xd*( d2sdb2+dsrgdb*dsrgdb* model->MOS2xd/(model->MOS2junctionDepth*argxs))/ (EffectiveLength*args); daddb2 = -model->MOS2xd*( d2bdb2+dbrgdb*dbrgdb* model->MOS2xd/(model->MOS2junctionDepth*argxd))/ (EffectiveLength*argd); dgddb2 = -0.5*model->MOS2gamma*(dasdb2+daddb2); } dgddvb = -model->MOS2gamma*(dbargs+dbargd); if (model->MOS2junctionDepth > 0) { ddxwd = -dbxwd; dgdvds = -model->MOS2gamma*0.5*ddxwd/(EffectiveLength*argd); } } else { gamasd = model->MOS2gamma; gammad = model->MOS2gamma; dgddvb = 0.0; dgdvds = 0.0; dgddb2 = 0.0; } von = vbin+gamasd*sarg; vth = von; vdsat = 0.0; if (model->MOS2fastSurfaceStateDensity != 0.0 && OxideCap != 0.0) { /* XXX constant per model */ cfs = CHARGE*model->MOS2fastSurfaceStateDensity* 1e4 /*(cm**2/m**2)*/; cdonco = -(gamasd*dsrgdb+dgddvb*sarg)+factor; xn = 1.0+cfs/OxideCap*here->MOS2w*EffectiveLength+cdonco; tmp = vt*xn; von = von+tmp; argg = 1.0/tmp; vgst = lvgs-von; } else { vgst = lvgs-von; if (lvgs <= von) { /* * cutoff region */ here->MOS2gds = 0.0; goto line1050; } } /* * compute some more useful quantities */ sarg3 = sarg*sarg*sarg; /* XXX constant per model */ sbiarg = sqrt(here->MOS2tBulkPot); gammad = gamasd; dgdvbs = dgddvb; body = barg*barg*barg-sarg3; gdbdv = 2.0*gammad*(barg*barg*dbrgdb-sarg*sarg*dsrgdb); dodvbs = -factor+dgdvbs*sarg+gammad*dsrgdb; if (model->MOS2fastSurfaceStateDensity == 0.0) goto line400; if (OxideCap == 0.0) goto line410; dxndvb = 2.0*dgdvbs*dsrgdb+gammad*d2sdb2+dgddb2*sarg; dodvbs = dodvbs+vt*dxndvb; dxndvd = dgdvds*dsrgdb; dodvds = dgdvds*sarg+vt*dxndvd; /* * evaluate effective mobility and its derivatives */line400: if (OxideCap <= 0.0) goto line410; udenom = vgst; tmp = model->MOS2critField * 100 /* cm/m */ * EPSSIL/ model->MOS2oxideCapFactor; if (udenom <= tmp) goto line410; ufact = exp(model->MOS2critFieldExp*log(tmp/udenom)); ueff = model->MOS2surfaceMobility * 1e-4 /*(m**2/cm**2) */ *ufact; dudvgs = -ufact*model->MOS2critFieldExp/udenom;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -