mos3load.c
来自「ngspice又一个电子CAD仿真软件代码.功能更全」· C语言 代码 · 共 1,286 行 · 第 1/3 页
C
1,286 行
here->MOS3gbd = DrainSatCur*evbd/vt + ckt->CKTgmin; here->MOS3cbd = 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->MOS3mode = 1; } else { /* inverse mode */ here->MOS3mode = -1; } { /* * subroutine moseq3(vds,vbs,vgs,gm,gds,gmbs, * qg,qc,qb,cggb,cgdb,cgsb,cbgb,cbdb,cbsb) */ /* this routine evaluates the drain current, its * derivatives and the charges associated with the * gate, channel and bulk for mosfets based on * semi-empirical equations */ double coeff0 = 0.0631353e0; double coeff1 = 0.8013292e0; double coeff2 = -0.01110777e0; double oneoverxl; /* 1/effective length */ double eta; /* eta from model after length factor */ double phibs; /* phi - vbs */ double sqphbs; /* square root of phibs */ double dsqdvb; /* */ double sqphis; /* square root of phi */ double sqphs3; /* square root of phi cubed */ double wps; double oneoverxj; /* 1/junction depth */ double xjonxl; /* junction depth/effective length */ double djonxj; double wponxj; double arga; double argb; double argc; double dwpdvb; double dadvb; double dbdvb; double gammas; double fbodys; double fbody; double onfbdy; double qbonco; double vbix; double wconxj; double dfsdvb; double dfbdvb; double dqbdvb; double vth; double dvtdvb; double csonco; double cdonco; double dxndvb = 0.0; double dvodvb = 0.0; double dvodvd = 0.0; double vgsx; double dvtdvd; double onfg; double fgate; double us; double dfgdvg; double dfgdvd; double dfgdvb; double dvsdvg; double dvsdvb; double dvsdvd; double xn = 0.0; double vdsc; double onvdsc = 0.0; double dvsdga; double vdsx; double dcodvb; double cdnorm; double cdo; double cd1; double fdrain = 0.0; double fd2; double dfddvg = 0.0; double dfddvb = 0.0; double dfddvd = 0.0; double gdsat; double cdsat; double gdoncd; double gdonfd; double gdonfg; double dgdvg; double dgdvd; double dgdvb; double emax; double emongd; double demdvg; double demdvd; double demdvb; double delxl; double dldvd; double dldem; double ddldvg; double ddldvd; double ddldvb; double dlonxl; double xlfact; double diddl; double gds0 = 0.0; double emoncd; double ondvt; double onxn; double wfact; double gms; double gmw; double fshort; /* * bypasses the computation of charges */ /* * reference cdrain equations to source and * charge equations to bulk */ vdsat = 0.0; oneoverxl = 1.0/EffectiveLength; eta = model->MOS3eta * 8.15e-22/(model->MOS3oxideCapFactor* EffectiveLength*EffectiveLength*EffectiveLength); /* *.....square root term */ if ( (here->MOS3mode==1?vbs:vbd) <= 0.0 ) { phibs = here->MOS3tPhi-(here->MOS3mode==1?vbs:vbd); sqphbs = sqrt(phibs); dsqdvb = -0.5/sqphbs; } else { sqphis = sqrt(here->MOS3tPhi); sqphs3 = here->MOS3tPhi*sqphis; sqphbs = sqphis/(1.0+(here->MOS3mode==1?vbs:vbd)/ (here->MOS3tPhi+here->MOS3tPhi)); phibs = sqphbs*sqphbs; dsqdvb = -phibs/(sqphs3+sqphs3); } /* *.....short channel effect factor */ if ( (model->MOS3junctionDepth != 0.0) && (model->MOS3coeffDepLayWidth != 0.0) ) { wps = model->MOS3coeffDepLayWidth*sqphbs; oneoverxj = 1.0/model->MOS3junctionDepth; xjonxl = model->MOS3junctionDepth*oneoverxl; djonxj = model->MOS3latDiff*oneoverxj; wponxj = wps*oneoverxj; wconxj = coeff0+coeff1*wponxj+coeff2*wponxj*wponxj; arga = wconxj+djonxj; argc = wponxj/(1.0+wponxj); argb = sqrt(1.0-argc*argc); fshort = 1.0-xjonxl*(arga*argb-djonxj); dwpdvb = model->MOS3coeffDepLayWidth*dsqdvb; dadvb = (coeff1+coeff2*(wponxj+wponxj))*dwpdvb*oneoverxj; dbdvb = -argc*argc*(1.0-argc)*dwpdvb/(argb*wps); dfsdvb = -xjonxl*(dadvb*argb+arga*dbdvb); } else { fshort = 1.0; dfsdvb = 0.0; } /* *.....body effect */ gammas = model->MOS3gamma*fshort; fbodys = 0.5*gammas/(sqphbs+sqphbs); fbody = fbodys+model->MOS3narrowFactor/EffectiveWidth; onfbdy = 1.0/(1.0+fbody); dfbdvb = -fbodys*dsqdvb/sqphbs+fbodys*dfsdvb/fshort; qbonco =gammas*sqphbs+model->MOS3narrowFactor*phibs/EffectiveWidth; dqbdvb = gammas*dsqdvb+model->MOS3gamma*dfsdvb*sqphbs- model->MOS3narrowFactor/EffectiveWidth; /* *.....static feedback effect */ vbix = here->MOS3tVbi*model->MOS3type-eta*(here->MOS3mode*vds); /* *.....threshold voltage */ vth = vbix+qbonco; dvtdvd = -eta; dvtdvb = dqbdvb; /* *.....joint weak inversion and strong inversion */ von = vth; if ( model->MOS3fastSurfaceStateDensity != 0.0 ) { csonco = CHARGE*model->MOS3fastSurfaceStateDensity * 1e4 /*(cm**2/m**2)*/ *EffectiveLength*EffectiveWidth * here->MOS3m/OxideCap; cdonco = qbonco/(phibs+phibs); xn = 1.0+csonco+cdonco; von = vth+vt*xn; dxndvb = dqbdvb/(phibs+phibs)-qbonco*dsqdvb/(phibs*sqphbs); dvodvd = dvtdvd; dvodvb = dvtdvb+vt*dxndvb; } else { /* *.....cutoff region */ if ( (here->MOS3mode==1?vgs:vgd) <= von ) { cdrain = 0.0; here->MOS3gm = 0.0; here->MOS3gds = 0.0; here->MOS3gmbs = 0.0; goto innerline1000; } } /* *.....device is on */ vgsx = MAX((here->MOS3mode==1?vgs:vgd),von); /* *.....mobility modulation by gate voltage */ onfg = 1.0+model->MOS3theta*(vgsx-vth); fgate = 1.0/onfg; us = here->MOS3tSurfMob * 1e-4 /*(m**2/cm**2)*/ *fgate; dfgdvg = -model->MOS3theta*fgate*fgate; dfgdvd = -dfgdvg*dvtdvd; dfgdvb = -dfgdvg*dvtdvb; /* *.....saturation voltage */ vdsat = (vgsx-vth)*onfbdy; if ( model->MOS3maxDriftVel <= 0.0 ) { dvsdvg = onfbdy; dvsdvd = -dvsdvg*dvtdvd; dvsdvb = -dvsdvg*dvtdvb-vdsat*dfbdvb*onfbdy; } else { vdsc = EffectiveLength*model->MOS3maxDriftVel/us; onvdsc = 1.0/vdsc; arga = (vgsx-vth)*onfbdy; argb = sqrt(arga*arga+vdsc*vdsc); vdsat = arga+vdsc-argb; dvsdga = (1.0-arga/argb)*onfbdy; dvsdvg = dvsdga-(1.0-vdsc/argb)*vdsc*dfgdvg*onfg; dvsdvd = -dvsdvg*dvtdvd; dvsdvb = -dvsdvg*dvtdvb-arga*dvsdga*dfbdvb; } /* *.....current factors in linear region */ vdsx = MIN((here->MOS3mode*vds),vdsat); if ( vdsx == 0.0 ) goto line900; cdo = vgsx-vth-0.5*(1.0+fbody)*vdsx; dcodvb = -dvtdvb-0.5*dfbdvb*vdsx; /* *.....normalized drain current */ cdnorm = cdo*vdsx; here->MOS3gm = vdsx; if ((here->MOS3mode*vds) > vdsat) here->MOS3gds = -dvtdvd*vdsx; else here->MOS3gds = vgsx-vth-(1.0+fbody+dvtdvd)*vdsx; here->MOS3gmbs = dcodvb*vdsx; /* *.....drain current without velocity saturation effect */ cd1 = Beta*cdnorm; Beta = Beta*fgate; cdrain = Beta*cdnorm; here->MOS3gm = Beta*here->MOS3gm+dfgdvg*cd1; here->MOS3gds = Beta*here->MOS3gds+dfgdvd*cd1; here->MOS3gmbs = Beta*here->MOS3gmbs+dfgdvb*cd1; /* *.....velocity saturation factor */ if ( model->MOS3maxDriftVel > 0.0 ) { fdrain = 1.0/(1.0+vdsx*onvdsc); fd2 = fdrain*fdrain; arga = fd2*vdsx*onvdsc*onfg; dfddvg = -dfgdvg*arga; if ((here->MOS3mode*vds) > vdsat) dfddvd = -dfgdvd*arga; else dfddvd = -dfgdvd*arga-fd2*onvdsc; dfddvb = -dfgdvb*arga; /* *.....drain current */ here->MOS3gm = fdrain*here->MOS3gm+dfddvg*cdrain; here->MOS3gds = fdrain*here->MOS3gds+dfddvd*cdrain; here->MOS3gmbs = fdrain*here->MOS3gmbs+dfddvb*cdrain; cdrain = fdrain*cdrain; Beta = Beta*fdrain; } /* *.....channel length modulation */ if ( (here->MOS3mode*vds) <= vdsat ) { if ( (model->MOS3maxDriftVel > 0.0) || (model->MOS3alpha == 0.0) || (ckt->CKTbadMos3) ) goto line700; else { arga = (here->MOS3mode*vds)/vdsat; delxl = sqrt(model->MOS3kappa*model->MOS3alpha*vdsat/8); dldvd = 4*delxl*arga*arga*arga/vdsat; arga *= arga; arga *= arga; delxl *= arga; ddldvg = 0.0; ddldvd = -dldvd; ddldvb = 0.0; goto line520; }; }; if ( model->MOS3maxDriftVel <= 0.0 ) goto line510; if (model->MOS3alpha == 0.0) goto line700; cdsat = cdrain; gdsat = cdsat*(1.0-fdrain)*onvdsc; gdsat = MAX(1.0e-12,gdsat); gdoncd = gdsat/cdsat; gdonfd = gdsat/(1.0-fdrain); gdonfg = gdsat*onfg; dgdvg = gdoncd*here->MOS3gm-gdonfd*dfddvg+gdonfg*dfgdvg; dgdvd = gdoncd*here->MOS3gds-gdonfd*dfddvd+gdonfg*dfgdvd; dgdvb = gdoncd*here->MOS3gmbs-gdonfd*dfddvb+gdonfg*dfgdvb; if (ckt->CKTbadMos3) emax = cdsat*oneoverxl/gdsat; else emax = model->MOS3kappa * cdsat*oneoverxl/gdsat; emoncd = emax/cdsat; emongd = emax/gdsat; demdvg = emoncd*here->MOS3gm-emongd*dgdvg; demdvd = emoncd*here->MOS3gds-emongd*dgdvd; demdvb = emoncd*here->MOS3gmbs-emongd*dgdvb; arga = 0.5*emax*model->MOS3alpha; argc = model->MOS3kappa*model->MOS3alpha; argb = sqrt(arga*arga+argc*((here->MOS3mode*vds)-vdsat)); delxl = argb-arga; if (argb != 0.0) { dldvd = argc/(argb+argb); dldem = 0.5*(arga/argb-1.0)*model->MOS3alpha; } else { dldvd = 0.0; dldem = 0.0; } ddldvg = dldem*demdvg; ddldvd = dldem*demdvd-dldvd; ddldvb = dldem*demdvb; goto line520;line510: if (ckt->CKTbadMos3) { delxl = sqrt(model->MOS3kappa*((here->MOS3mode*vds)-vdsat)* model->MOS3alpha); dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat); } else { delxl = sqrt(model->MOS3kappa*model->MOS3alpha* ((here->MOS3mode*vds)-vdsat+(vdsat/8))); dldvd = 0.5*delxl/((here->MOS3mode*vds)-vdsat+(vdsat/8)); }; ddldvg = 0.0; ddldvd = -dldvd; ddldvb = 0.0; /* *.....punch through approximation */line520: if ( delxl > (0.5*EffectiveLength) ) { delxl = EffectiveLength-(EffectiveLength*EffectiveLength/ (4.0*delxl)); arga = 4.0*(EffectiveLength-delxl)*(EffectiveLength-delxl)/ (EffectiveLength*EffectiveLength); ddldvg = ddldvg*arga; ddldvd = ddldvd*arga; ddldvb = ddldvb*arga; dldvd = dldvd*arga; } /* *.....saturation region */ dlonxl = delxl*oneoverxl; xlfact = 1.0/(1.0-dlonxl); cd1 = cdrain; cdrain = cdrain*xlfact; diddl = cdrain/(EffectiveLength-delxl); here->MOS3gm = here->MOS3gm*xlfact+diddl*ddldvg; here->MOS3gmbs = here->MOS3gmbs*xlfact+diddl*ddldvb; gds0 = diddl*ddldvd; here->MOS3gm = here->MOS3gm+gds0*dvsdvg; here->MOS3gmbs = here->MOS3gmbs+gds0*dvsdvb; here->MOS3gds = here->MOS3gds*xlfact+diddl*dldvd+gds0*dvsdvd;/* here->MOS3gds = (here->MOS3gds*xlfact)+gds0*dvsdvd- (cd1*ddldvd/(EffectiveLength*(1-2*dlonxl+dlonxl*dlonxl)));*/ /* *.....finish strong inversion case */line700: if ( (here->MOS3mode==1?vgs:vgd) < von ) { /* *.....weak inversion */ onxn = 1.0/xn; ondvt = onxn/vt; wfact = exp( ((here->MOS3mode==1?vgs:vgd)-von)*ondvt ); cdrain = cdrain*wfact; gms = here->MOS3gm*wfact; gmw = cdrain*ondvt; here->MOS3gm = gmw; if ((here->MOS3mode*vds) > vdsat) { here->MOS3gm = here->MOS3gm+gds0*dvsdvg*wfact; } here->MOS3gds = here->MOS3gds*wfact+(gms-gmw)*dvodvd; here->MOS3gmbs = here->MOS3gmbs*wfact+(gms-gmw)*dvodvb-gmw* ((here->MOS3mode==1?vgs:vgd)-von)*onxn*dxndvb; } /* *.....charge computation */ goto innerline1000; /* *.....special case of vds = 0.0d0 */line900: Beta = Beta*fgate; cdrain = 0.0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?