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 + -
显示快捷键?