diff --git a/src/spicelib/devices/adms/ekv/admsva/ekv.va b/src/spicelib/devices/adms/ekv/admsva/ekv.va index 71ae4accb..c6a32440b 100644 --- a/src/spicelib/devices/adms/ekv/admsva/ekv.va +++ b/src/spicelib/devices/adms/ekv/admsva/ekv.va @@ -3,28 +3,18 @@ // (revision II) available at http://legwww.epfl.ch/ekv. // contribution of Ivan Riis Nielsen 11/2006, modified by Dietmar Warning 01/2009 -//Default simulator: Spectre - +`define P(txt) (*txt*) +`define PGIVEN(p) $param_given(p) `ifdef insideADMS - `define P(txt) (*txt*) - `define PGIVEN(p) $given(p) - `define INITIAL_MODEL @(initial_model) - `define INSTANCE @(initial_instance) - `define NOISE @(noise) + `define INITIAL_MODEL @(initial_model) + `define INSTANCE @(initial_instance) + `define NOISE @(noise) `else - `define P(txt) (txt) - `define PGIVEN(p) p - `define INITIAL_MODEL - `define INSTANCE - `define NOISE + `define INITIAL_MODEL + `define INSTANCE + `define NOISE `endif -//ADS -//`include "constants.vams" -//`include "disciplines.vams" -//`include "compact.vams" - -//Spectre `include "constants.h" `include "discipline.h" @@ -34,6 +24,8 @@ `define EPSSI `P_EPS0*11.7 `define EPSOX `P_EPS0*3.9 `define TREF 300.15 +`define MIN_R 0.001 +`define VEXLIM 200.0 `define SQR(x) ((x)*(x)) @@ -41,621 +33,588 @@ `define EG(temp) (1.16-0.000702*`SQR(temp)/(temp+1108)) `define NI(temp) (1.45e16*(temp/`TREF)*exp(`EG(`TREF)/(2*`VT(`TREF))-`EG(temp)/(2*`VT(temp)))) - -`define oneThird 3.3333333333333333e-01 - -// Constants needed in safe exponential function (called "expl") -`define se05 2.3025850929940458e+02 -`define ke05 1.0e-100 -`define ke05inv 1.0e100 - -// P3 3rd order polynomial expansion of exp() -`define P3(u) (1.0 + (u) * (1.0 + 0.5 * ((u) * (1.0 + (u) * `oneThird)))) - -// expl exp() with 3rd order polynomial extrapolation -// to avoid overflows and underflows and retain C-3 continuity -`define expl(x, res) \ -if (abs(x) < `se05) begin\ - res = exp(x); \ -end else begin \ - if ((x) < -`se05) begin\ - res = `ke05 / `P3(-`se05 - (x)); \ - end else begin\ - res = `ke05inv * `P3((x) - `se05); \ +`define y_fv(fv,y)\ + if (fv > -0.35) begin \ + z0 = 2.0/(1.3 + fv - ln(fv+1.6));\ + z1 = (2.0 + z0) / (1.0 + fv + ln(z0));\ + y = (1.0 + fv + ln(z1)) / (2.0 + z1);\ end \ -end + else if (fv > -15) begin \ + tmp = exp(-fv);\ + z0 = 1.55 + tmp;\ + z1 = (2.0 + z0) / (1.0 + fv + ln(z0));\ + y = (1.0 + fv + ln(z1)) / (2.0 + z1);\ + end \ + else if (fv > -23.0) begin \ + tmp = exp(-fv);\ + y = 1.0 / (2.0 + tmp);\ + end \ + else begin \ + tmp = exp(fv);\ + y = tmp + 1.0e-64;\ + end +`define expLin(result, x)\ + if (x < `VEXLIM)\ + result = exp(x);\ + else begin\ + result = exp(`VEXLIM) * (1.0 + (x - `VEXLIM));\ + end module ekv (d,g,s,b); - // Node definitions + // Node definitions - inout d,g,s,b; - electrical d,g,s,b,di,si; + inout d,g,s,b; // external nodes + electrical d,g,s,b; // external nodes + electrical dp,sp; // internal nodes - // Model parameters - - parameter integer nmos=1 from [0:1] `P(info="MOS type : nmos:0"); - parameter integer pmos=1 from [0:1] `P(info="MOS type : pmos:0"); - parameter integer MTYPE=(nmos==0 ? (pmos==0 ? 0 : 1) : (pmos==0 ? -1 : 1)); - parameter real TNOM=27 from (-273.15:inf) - `P(info="Nominal temperature [degC]"); - parameter real IMAX=1 from (0:inf) - `P(info="Maximum forward junction current before linearization [A]"); - - // - intrinsic model (optional, section 4.2.1) - parameter real TOX=0 from [0:inf) - `P(info="Oxide thickness [m]"); - parameter real NSUB=0 from [0:inf) - `P(info="Channel doping [cm^-3]"); - parameter real VFB=1001.0 from (-inf:inf) // use 1001V as "not specified" - `P(info="Flat-band voltage [V]"); - parameter real UO=0 from [0:inf) - `P(info="Low-field mobility [cm^2/Vs]"); - parameter real VMAX=0 from [0:inf) - `P(info="Saturation velocity [m/s]"); - parameter real THETA=0 from [0:inf) - `P(info="Mobility reduction coefficient [V^-1]"); - - // - intrinsic model (process related, section 4.1) - parameter real COX=((TOX>0) ? (`EPSOX/TOX) : 0.7m) from [0:inf) - `P(info="Oxide capacitance [F/m^2]"); - parameter real XJ=0.1u from [1n:inf) - `P(info="Junction depth [m]"); - parameter real DL=0 from (-inf:inf) - `P(info="Length correction [m]"); - parameter real DW=0 from (-inf:inf) - `P(info="Width correction [m]"); - - // - intrinsic model (basic, section 4.2) - parameter real GAMMA=((NSUB>0) ? (sqrt(2*`P_Q*`EPSSI*NSUB*1e6)/COX) : 1) from [0:inf) - `P(info="Body effect parameter [V^0.5]"); - parameter real PHI=((NSUB>0) ? (2*`VT((TNOM+273.15))*ln(max(NSUB,1)*1e6/`NI((TNOM+273.15)))) : 0.7) from [0.1:inf) - `P(info="Bulk Fermi potential (*2) [V]"); - parameter real VTO=((VFB<1000.0) ? (VFB+MTYPE*(PHI+GAMMA*sqrt(PHI))) : 0.5) from (-inf:inf) - `P(info="Long-channel threshold voltage [V]"); - parameter real KP=((UO>0) ? (UO*1e-4*COX) : 50u) from (0:inf) - `P(info="Transconductance parameter [A/V^2]"); - parameter real UCRIT=(((VMAX>0) && (UO>0)) ? (VMAX/(UO*1e-4)) : 2e6 ) from [100k:inf) - `P(info="Longitudinal critical field [V/m]"); - parameter real E0=((THETA>0) ? 0 : 1e12) from [100k:inf) - `P(info="Mobility reduction coefficient [V/m]"); - - // - intrinsic model (channel length modulation and charge sharing, section 4.3) - parameter real LAMBDA=0.5 from [0:inf) - `P(info="Depletion length coefficient (CLM)"); - parameter real WETA=0.25 from (-inf:inf) - `P(info="Narrow-channel effect coefficient"); - parameter real LETA=0.1 from (-inf:inf) - `P(info="Short-channel effect coefficient"); - - // - intrinsic model (reverse short channel effect, section 4.4) - parameter real Q0=0 from (-inf:inf) - `P(info="RSCE peak charge density [C/m^2]"); - parameter real LK=0.29u from [10n:inf) - `P(info="RSCE characteristic length [m]"); - - // - intrinsic model (impact ionization, section 4.5) - parameter real IBA=0 from (-inf:inf) - `P(info="First impact ionization coefficient [m^-1]"); - parameter real IBB=3e8 from [1e8:inf) - `P(info="Second impact ionization coefficient [V/m]"); - parameter real IBN=1 from [0.1:inf) - `P(info="Saturation voltage factor for impact ionization"); - - // - intrinsic model (temperature, section 4.6) - parameter real TCV=1m from (-inf:inf) - `P(info="Threshold voltage TC [V/K]"); - parameter real BEX=-1.5 from (-inf:inf) - `P(info="Mobility temperature exponent"); - parameter real UCEX=0.8 from (-inf:inf) - `P(info="Longitudinal critical field temperature exponent"); - parameter real IBBT=9e-4 from (-inf:inf) - `P(info="Temperature coefficient for IBB [K^-1]"); - - // - intrinsic model (matching, section 4.7) - parameter real AVTO=0 from (-inf:inf) - `P(info="Area related VTO mismatch parameter [Vm]"); - parameter real AKP=0 from (-inf:inf) - `P(info="Area related KP mismatch parameter [m]"); - parameter real AGAMMA=0 from (-inf:inf) - `P(info="Area related GAMMA mismatch parameter [V^0.5*m]"); - - // - intrinsic model (flicker noise, section 4.8) - parameter real KF=0 from [0:inf) - `P(info="Flicker noise coefficient"); - parameter real AF=1 from (-inf:inf) - `P(info="Flicker noise exponent"); - - // - intrinsic model (setup, section 4.9) - parameter real NQS=0 from [0:1] - `P(info="Non-quasi-static operation switch"); - parameter real SATLIM=exp(4) from (0:inf) - `P(info="Saturation limit (if/ir)"); - parameter real XQC=0.4 from [0:1] - `P(info="Charge/capacitance model selector"); - - // - external parasitic parameters - parameter real HDIF=0 from [0:inf) - `P(info="S/D diffusion length (/2) [m]"); - parameter real RSH=0 from [0:inf) - `P(info="S/D sheet resistance [ohm]"); - parameter real JS=0 from [0:inf) - `P(info="S/D junction saturation current density [A/m^2]"); - parameter real JSW=0 from [0:inf) - `P(info="S/D junction sidewall saturation current density [A/m]"); - parameter real XTI=0 from [0:inf) - `P(info="S/D diode saturation current temperature exponent"); - parameter real N=1 from [0.5:10] - `P(info="S/D diode emission coefficient"); - parameter real CJ=0 from [0:inf) - `P(info="S/D zero-bias junction capacitance per area [F/m^2]"); - parameter real CJSW=0 from [0:inf) - `P(info="S/D zero-bias junction capacitance per perimeter [F/m]"); - parameter real PB=0.8 from (0:inf) - `P(info="S/D bottom junction builtin potential [V]"); - parameter real PBSW=PB from (0:inf) - `P(info="S/D sidewall junction builtin potential [V]"); - parameter real MJ=0.5 from (0:inf) - `P(info="S/D bottom junction grading coefficient"); - parameter real MJSW=0.333 from (0:inf) - `P(info="S/D sidewall junction grading coefficient"); - parameter real FC=0.5 from (0:inf) - `P(info="S/D bottom junction forward-bias threshold"); - parameter real FCSW=FC from (0:inf) - `P(info="S/D sidewall junction forward-bias threshold"); - parameter real CGSO=0 from [0:inf) - `P(info="Gate-source overlap capacitance per width [F/m]"); - parameter real CGDO=0 from [0:inf) - `P(info="Gate-drain overlap capacitance per width [F/m]"); - parameter real CGBO=0 from [0:inf) - `P(info="Gate-bulk overlap capacitance per length [F/m]"); + branch (dp,sp) dpsp; + branch (dp,b) dpb; + branch (sp,b) spb; + branch (g,dp) gpdp; + branch (g,sp) gpsp; + branch (g,b) gb; + branch (d,dp) ddp; + branch (s,sp) ssp; + // Instance parameters - // Instance parameters + // - intrinsic model + parameter real l=10e-6 from [0:inf) `P(type="instance" info="Drawn length [m]" units="m"); + parameter real w=10e-6 from [0:inf) `P(type="instance" info="Drawn width [m]" units="m"); + parameter real m=1.0 from [1:inf) `P(type="instance" info="Parallel multiplier" units="m"); + parameter real ns=1.0 from [1:inf) `P(type="instance" info="Series multiplier" units="m"); + parameter real dtemp = 0.0 from (-inf:inf) `P(type="instance" info="Difference sim. temp and device temp" units="C"); - // - intrinsic model - parameter real L=10u from [0:inf] - `P(type="instance" info="Drawn length [m]" unit="m"); - parameter real W=10u from [0:inf] - `P(type="instance" info="Drawn width [m]" unit="m"); - parameter real M=1 from [0:inf] - `P(type="instance" info="Parallel multiplier" unit="m"); -// parameter real N=1 from [0:inf] -// `P(type="instance" info="Series multiplier" unit="m"); + // - external parasitics + parameter real ad=0.0 from [0:inf) `P(type="instance" info="Drain area" units="m^2"); + parameter real as=0.0 from [0:inf) `P(type="instance" info="Source area" units="m^2"); + parameter real pd=0.0 from [0:inf) `P(type="instance" info="Drain perimeter" units="m"); + parameter real ps=0.0 from [0:inf) `P(type="instance" info="Source perimeter" units="m"); + parameter real nrd=0.0 from [0:inf) `P(type="instance" info="Drain no. squares"); + parameter real nrs=0.0 from [0:inf) `P(type="instance" info="Source no. squares"); - // - external parasitics - parameter real AD=((HDIF>0) ? (2*HDIF*W) : 0) from [0:inf) - `P(info="Drain area [m^2]" type="instance"); - parameter real AS=((HDIF>0) ? (2*HDIF*W) : 0) from [0:inf) - `P(info="Source area [m^2]" type="instance"); - parameter real PD=((HDIF>0) ? (4*HDIF+2*W) : 0) from [0:inf) - `P(info="Drain perimeter [m]" type="instance"); - parameter real PS=((HDIF>0) ? (4*HDIF+2*W) : 0) from [0:inf) - `P(info="Source perimeter [m]" type="instance"); - parameter real NRD=((HDIF>0) ? (HDIF/W) : 0) from [0:inf) - `P(info="Drain no. squares" type="instance"); - parameter real NRS=((HDIF>0) ? (HDIF/W) : 0) from [0:inf) - `P(info="Source no. squares" type="instance"); - parameter real RS=((RSH>0) ? (RSH*NRS) : 0) from [0:inf) - `P(info="Source resistance [ohms]" type="instance"); - parameter real RD=((RSH>0) ? (RSH*NRD) : 0) from [0:inf) - `P(info="Drain resistance [ohms]" type="instance"); + // Model parameters + parameter integer nmos=1 from [0:1] `P(info="MOS channel type"); + parameter integer pmos=1 from [0:1] `P(info="MOS channel type"); + parameter integer type=1 from [-1:1] exclude 0; + parameter real tnom=27.0 from [-273.15:inf) `P(info="Nominal temperature" units="C"); + parameter real imax=1.0 from [0:inf) `P(info="Maximum forward junction current before linearization" units="A"); - // Declaration of variables - integer mode; - real lc,isat_s,vexp_s,gexp_s,isat_d,vexp_d,gexp_d,fact, - weff,leff,np,ns,lmin,rd,rs,ceps,ca,xsi,dvrsce, - tempk,vt,sqrt_A,vto_a,kp_a,gamma_a,ucrit,phi,ibb,vc,qb0, - vg,vd,vs,tmp,vgprime,vp0,vsprime,vdprime,gamma0,gammaprime,vp,n,ifwd, - vdss,vdssprime,dv,vds,vip,dl,lprime,leq,irprime,irev,beta0,nau, - nq,xf,xr,qd,qs,qi,qb,qg,beta0prime,beta,vpprime,is,ids,vib, - idb,ibdj,ibsj,coxt,qdt,qst,qgt,qbt, - cbs0,cbs0sw,cbs,cbd0,cbd0sw,cbd, - fv,z0,z1,y; + // - intrinsic model (optional, section 4.2.1) + parameter real tox=0.0 from [0:inf) `P(info="Oxide thickness" units="m"); + parameter real nsub=0.0 from [0:inf) `P(info="Channel doping" units="cm^-3"); + parameter real vfb=-1.0 from (-inf:inf) `P(info="Flat-band voltage" units="V"); - real cgso,cgdo,cgbo; - + parameter real uo=0.0 from [0:inf) `P(info="Low-field mobility" units="cm^2/Vs"); + parameter real vmax=0.0 from [0:inf) `P(info="Saturation velocity" units="m/s"); + parameter real theta=0.0 from [0:inf) `P(info="Mobility reduction coefficient" units="V^-1"); - analog begin + // - intrinsic model (process related, section 4.1) + parameter real cox=0.7e-3 from [1e-6:inf) `P(info="Oxide capacitance" units="F/m^2"); + parameter real xj=0.1e-6 from [1n:inf) `P(info="Junction depth" units="m"); + parameter real dl=0.0 from (-inf:inf) `P(info="Length correction" units="m"); + parameter real dw=0.0 from (-inf:inf) `P(info="Width correction" units="m"); - `INITIAL_MODEL begin // Model Initialization + // - intrinsic model (basic, section 4.2) + parameter real gamma=0.7 from [0:inf) `P(info="Body effect parameter" units="V^0.5"); + parameter real phi=0.5 from [0.1:inf) `P(info="Bulk Fermi potential (*2)" units="V"); + parameter real vto=0.5 from (-inf:inf) `P(info="Long-channel threshold voltage" units="V"); + parameter real kp=20e-6 from [0.0:inf) `P(info="Transconductance parameter" units="A/V^2"); + parameter real ucrit=1.0e+6 from [100e+3:inf) `P(info="Longitudinal critical field" units="V/m"); + parameter real e0=1.0e-9 from [1e-12:inf) `P(info="Mobility reduction coefficient" units="V/m"); - lc = sqrt(`EPSSI/COX*XJ); - - end // INITIAL_MODEL + // - intrinsic model (channel length modulation and charge sharing, section 4.3) + parameter real lambda=0.5 from [0:inf) `P(info="Depletion length coefficient (CLM)"); + parameter real weta=0.25 from (-inf:inf) `P(info="Narrow-channel effect coefficient"); + parameter real leta=0.1 from (-inf:inf) `P(info="Short-channel effect coefficient"); - `INSTANCE begin // temperature independent device initialization + // - intrinsic model (reverse short channel effect, section 4.4) + parameter real q0=0.0 from (-inf:inf) `P(info="RSCE peak charge density" units="C/m^2"); + parameter real lk=0.29e-6 from [10n:inf) `P(info="RSCE characteristic length" units="m"); - weff = W+DW; - leff = L+DL; + // - intrinsic model (impact ionization, section 4.5) + parameter real iba=0.0 from (-inf:inf) `P(info="First impact ionization coefficient" units="m^-1"); + parameter real ibb=3e8 from [1e8:inf) `P(info="Second impact ionization coefficient" units="V/m"); + parameter real ibn=1.0 from [0.1:inf) `P(info="Saturation voltage factor for impact ionization"); - np = M; - ns = 1; + // - intrinsic model (temperature, section 4.6) + parameter real tcv=1e-3 from (-inf:inf) `P(info="Threshold voltage TC" units="V/deg"); + parameter real bex=-1.5 from (-inf:inf) `P(info="Mobility temperature exponent"); + parameter real ucex=0.8 from (-inf:inf) `P(info="Longitudinal critical field temperature exponent"); + parameter real ibbt=9e-4 from (-inf:inf) `P(info="Temperature coefficient for ibb" units="K^-1"); - // eq. 54 - lmin = 0.1*ns*leff; - - rs = ns/np*RS; - rd = ns/np*RD; + // - intrinsic model (matching, section 4.7) + parameter real avto=0.0 from (-inf:inf) `P(info="Area related vto mismatch parameter" units="Vm"); + parameter real akp=0.0 from (-inf:inf) `P(info="Area related kp mismatch parameter" units="m"); + parameter real agamma=0.0 from (-inf:inf) `P(info="Area related gamma mismatch parameter" units="V^0.5*m"); - ceps = 4*22e-3*22e-3; - ca = 0.028; - xsi = ca*(10*leff/LK-1); - dvrsce = 2*Q0/COX/`SQR(1+0.5*(xsi+sqrt(xsi*xsi+ceps))); + // - intrinsic model (flicker noise, section 4.8) + parameter real kf=0.0 from [0:inf) `P(info="Flicker noise coefficient"); + parameter real af=1.0 from (-inf:inf) `P(info="Flicker noise exponent"); - coxt = np*ns*COX*weff*leff; - - end // temperature independent - - `INSTANCE begin // temperature dependent device initialization - tempk = $temperature; - vt = `VT(tempk); - - sqrt_A = sqrt(np*weff*ns*leff); - - vto_a = MTYPE*(VTO+TCV*(tempk-(TNOM+273.15)))+AVTO/sqrt_A; - kp_a = KP*pow(tempk/(TNOM+273.15),BEX)*(1+AKP/sqrt_A); - gamma_a = GAMMA+AGAMMA/sqrt_A; - ucrit = UCRIT*pow(tempk/(TNOM+273.15),UCEX); - phi = PHI*tempk/(TNOM+273.15)-3*vt*ln(tempk/(TNOM+273.15))-`EG(TNOM+273.15)*tempk/(TNOM+273.15)+`EG(tempk); - ibb = IBB*(1+IBBT*(tempk-(TNOM+273.15))); + // - external parasitic parameters + parameter real hdif=0.0 from [0:inf) `P(info="S/D diffusion length (/2)" units="m"); + parameter real rsh=0.0 from [0:inf) `P(info="S/D sheet resistance" units="Ohm"); + parameter real js=0.0 from [0:inf) `P(info="S/D junction saturation current density" units="A/m^2"); + parameter real jsw=0.0 from [0:inf) `P(info="S/D junction sidewall saturation current density" units="A/m"); + parameter real xti=0.0 from [0:inf) `P(info="S/D diode saturation current temperature exponent"); + parameter real n=1 from [0.5:10] `P(info="S/D diode emission coefficient"); + parameter real cj=0.0 from [0:inf) `P(info="S/D zero-bias junction capacitance per area" units="F/m^2"); + parameter real cjsw=0.0 from [0:inf) `P(info="S/D zero-bias junction capacitance per perimeter" units="F/m"); + parameter real pb=0.8 from (0:inf) `P(info="S/D bottom junction builtin potential" units="V"); + parameter real pbsw=pb from (0:inf) `P(info="S/D sidewall junction builtin potential" units="V"); + parameter real mj=0.5 from (0:inf) `P(info="S/D bottom junction grading coefficient"); + parameter real mjsw=0.333 from (0:inf) `P(info="S/D sidewall junction grading coefficient"); + parameter real fc=0.5 from (0:inf) `P(info="S/D bottom junction forward-bias threshold"); + parameter real fcsw=fc from (0:inf) `P(info="S/D sidewall junction forward-bias threshold"); + parameter real cgso=1.5e-10 from [0:inf) `P(info="Gate-source overlap capacitance per width" units="F/m"); + parameter real cgdo=1.5e-10 from [0:inf) `P(info="Gate-drain overlap capacitance per width" units="F/m"); + parameter real cgbo=4.0e-10 from [0:inf) `P(info="Gate-bulk overlap capacitance per length" units="F/m"); - vc = ucrit*ns*leff; - - // eq. 60 - qb0 = gamma_a*sqrt(phi); + // Declaration of variables + integer mode, MOStype; + real lc,isat_s,vexp_s,gexp_s,isat_d,vexp_d,gexp_d,fact, + weff,leff,lmin,RDeff,RSeff,ceps,ca,xsi,dvrsce, + TempK,Vt,sqrt_A,vto_a,kp_a,gamma_a,ucrit_a,phi_a,ibb_a,vc,qb0, + vg,vd,vs,tmp,vgprime,vp0,vsprime,vdprime,gamma0,gammaprime,vp,nslope,ifwd, + vdss,vdssprime,dv,vds,vip,dl_a,lprime,leq,irprime,irev,beta0,nau, + nq,xf,xr,qd,qs,qi,qb,qg,beta0prime,beta,vpprime,is,ids,vib, + idb,ibdj,ibsj,coxt,qdt,qst,qdtx,qstx,qgt,qjs,qjd, + cbs0,cbs0sw,cbs,cbd0,cbd0sw,cbd,v_bp_dp, v_bp_sp, + fv,z0,z1,y; - fact = (`EG(TNOM+273.15)/`VT(TNOM+273.15)-`EG(tempk)/vt) * pow(tempk/(TNOM+273.15),XTI); - `expl(fact,tmp) - isat_s = np*ns*(JS*AS+JSW*PS)*tmp; - isat_d = np*ns*(JS*AD+JSW*PD)*tmp; + real ADeff, ASeff, PDeff, PSeff; + real cgso_s,cgdo_s,cgbo_s; + real gmin, TnomK; + real cox_p, gamma_p, phi_p, kp_p, vto_p, ucrit_p; - if (isat_s>0) begin - vexp_s = vt*ln(IMAX/isat_s+1); - gexp_s = (IMAX+isat_s)/vt; - end else begin - vexp_s = -1e9; - gexp_s = 0; - end + analog begin - if (isat_d>0) begin - vexp_d = vt*ln(IMAX/isat_d+1); - gexp_d = (IMAX+isat_d)/vt; - end else begin - vexp_d = -1e9; - gexp_d = 0; - end - - cbs0 = np*ns*CJ*AS; - cbd0 = np*ns*CJ*AD; - cbs0sw = np*ns*CJSW*PS; - cbd0sw = np*ns*CJSW*PD; + gmin = $simparam("gmin"); - cgso = np*ns*CGSO*weff; - cgdo = np*ns*CGDO*weff; - cgbo = np*ns*CGBO*leff; - - end // temperature dependent + `INITIAL_MODEL // Model Initialization + begin + if (`PGIVEN(nmos)) begin + MOStype = `NMOS; + end else if (`PGIVEN(pmos)) begin + MOStype = `PMOS; + end else begin + MOStype = (`PGIVEN(type)) ? type : `NMOS; + end - - begin //Bias-dependent model evaluation +//$strobe("MOStype %d", MOStype); - vg = MTYPE*V(g,b); - vd = MTYPE*V(di,b); - vs = MTYPE*V(si,b); - // $strobe("vg=%e vd=%e vs=%e",vg,vd,vs); - - if (vd>=vs) - mode = 1; - else begin - mode = -1; - tmp = vs; - vs = vd; - vd = tmp; - end + if (`PGIVEN(cox)) begin + cox_p = cox; + end else begin + cox_p = (tox>0) ? (`EPSOX/tox) : 0.7e-3; + end - // eq. 33 - vgprime = vg-vto_a-dvrsce+phi+gamma_a*sqrt(phi); - // eq. 35 - vsprime = 0.5*(vs+phi+sqrt(`SQR(vs+phi)+16*`SQR(vt))); - vdprime = 0.5*(vd+phi+sqrt(`SQR(vd+phi)+16*`SQR(vt))); - // $strobe("vgprime=%e vdprime=%e vsprime=%e",vgprime,vdprime,vsprime); - // eq. 34 - if (vgprime>=0) begin - vp0 = vgprime-phi-gamma_a*(sqrt(vgprime+0.25*`SQR(gamma_a))-0.5*gamma_a); - // eq. 36 - gamma0 = gamma_a-`EPSSI/COX*(LETA/leff*(sqrt(vsprime)+sqrt(vdprime))-3*WETA/weff*sqrt(vp0+phi)); - end else begin - vp0 = -phi; - // eq. 36 - skipped sqrt(vp0+phi) here, it produces inf on derivative - gamma0 = gamma_a-`EPSSI/COX*(LETA/leff*(sqrt(vsprime)+sqrt(vdprime)) ); - end - // eq. 37 - gammaprime = 0.5*(gamma0+sqrt(`SQR(gamma0)+0.1*vt)); - // eq. 38 - if (vgprime>=0) - vp = vgprime-phi-gammaprime*(sqrt(vgprime+0.25*`SQR(gammaprime))-0.5*gammaprime); - else - vp = -phi; - // $strobe("vp0=%e vp=%e gamma0=%e gammaprime=%e",vp0,vp,gamma0,gammaprime); - // eq. 39 - n = 1+gamma_a*0.5/sqrt(vp+phi+4*vt); + if (`PGIVEN(gamma)) begin + gamma_p = gamma; + end else begin + gamma_p = (nsub>0) ? (sqrt(2*`P_Q*`EPSSI*nsub*1e+6)/cox_p) : 0.7; + end - // Forward current (43-44) - fv=(vp-vs)/vt; - - if (fv > -0.35) begin - z0 = 2.0/(1.3 + fv - ln(fv+1.6)); - z1 = (2.0 + z0) / (1.0 + fv + ln(z0)); - y = (1.0 + fv + ln(z1)) / (2.0 + z1); - end - else if (fv > -15) begin - `expl(-fv,tmp) - z0 = 1.55 + tmp; - z1 = (2.0 + z0) / (1.0 + fv + ln(z0)); - y = (1.0 + fv + ln(z1)) / (2.0 + z1); - end - else if (fv > -23.0) begin - `expl(-fv,tmp) - y = 1.0 / (2.0 + tmp); - end - else begin - `expl(fv,tmp) - y = tmp + 1.0e-64; - end - - ifwd = y*(1.0 + y); - z0 = 1; - z1 = 1; - - // eq. 46 - vdss = vc*(sqrt(0.25+vt/vc*sqrt(ifwd))-0.5); - // eq. 47 - vdssprime = vc*(sqrt(0.25+vt/vc*(sqrt(ifwd)-0.75*ln(ifwd)))-0.5)+vt*(ln(0.5*vc/vt)-0.6); - // $strobe("ifwd=%e vdss=%e vdssprime=%e",ifwd,vdss,vdssprime); - // eq. 48 - dv = 4*vt*sqrt(LAMBDA*(sqrt(ifwd)-vdss/vt)+1.0/64); - // eq. 49 - vds = 0.5*(vd-vs); - // eq. 50 - vip = sqrt(`SQR(vdss)+`SQR(dv))-sqrt(`SQR(vds-vdss)+`SQR(dv)); - // eq. 52 - dl = LAMBDA*lc*ln(1+(vds-vip)/(lc*ucrit)); + if (`PGIVEN(phi)) begin + phi_p = phi; + end else begin + phi_p = (nsub>0) ? (2*`VT(tnom+273.15)*ln(nsub*1e+6/`NI(tnom+273.15))) : 0.5; + end - // eq. 53 - lprime = ns*leff-dl+(vds+vip)/ucrit; - // eq. 55 - leq = 0.5*(lprime+sqrt(`SQR(lprime)+`SQR(lmin))); + if (`PGIVEN(kp)) begin + kp_p = kp; + end else begin + kp_p = (uo>0) ? (uo*1e-4*cox_p) : 20e-6; + end - // eq. 56 - fv=(vp-vds-vs-sqrt(`SQR(vdssprime)+`SQR(dv))+sqrt(`SQR(vds-vdssprime)+`SQR(dv)))/vt; - - if (fv > -0.35) begin - z0 = 2.0/(1.3 + fv - ln(fv+1.6)); - z1 = (2.0 + z0) / (1.0 + fv + ln(z0)); - y = (1.0 + fv + ln(z1)) / (2.0 + z1); - end - else if (fv > -15) begin - `expl(-fv,tmp) - z0 = 1.55 + tmp; - z1 = (2.0 + z0) / (1.0 + fv + ln(z0)); - y = (1.0 + fv + ln(z1)) / (2.0 + z1); - end - else if (fv > -23.0) begin - `expl(-fv,tmp) - y = 1.0 / (2.0 + tmp); - end - else begin - `expl(fv,tmp) - y = tmp + 1.0e-64; - end - - irprime = y*(1.0 + y); - z0 = 1; - z1 = 1; + if (`PGIVEN(vto)) begin + vto_p = vto; + end else begin + vto_p = (`PGIVEN(vfb)) ? (vfb+phi_p+gamma_p*sqrt(phi_p)) : 0.5; + end - // eq. 57 - fv=(vp-vd)/vt; - - if (fv > -0.35) begin - z0 = 2.0/(1.3 + fv - ln(fv+1.6)); - z1 = (2.0 + z0) / (1.0 + fv + ln(z0)); - y = (1.0 + fv + ln(z1)) / (2.0 + z1); - end - else if (fv > -15) begin - `expl(-fv,tmp) - z0 = 1.55 + tmp; - z1 = (2.0 + z0) / (1.0 + fv + ln(z0)); - y = (1.0 + fv + ln(z1)) / (2.0 + z1); - end - else if (fv > -23.0) begin - `expl(-fv,tmp) - y = 1.0 / (2.0 + tmp); - end - else begin - `expl(fv,tmp) - y = tmp + 1.0e-64; - end - - irev = y*(1.0 + y); + if (`PGIVEN(ucrit)) begin + ucrit_p = ucrit; + end else begin + ucrit_p = (vmax>0 && uo>0) ? (vmax/(uo*1e-4)) : 100e+3; + end - // eq. 58 - beta0 = kp_a*np*weff/leq; - // eq. 59 - nau = (5+MTYPE)/12.0; + lc = sqrt(`EPSSI/cox_p*xj); - // eq. 69 - nq = 1+0.5*gamma_a/sqrt(vp+phi+1e-6); - - // eq. 70 - xf = sqrt(0.25+ifwd); - // eq. 71 - xr = sqrt(0.25+irev); - // eq. 72 - qd = -nq*(4.0/15*(3*`SQR(xr)*(xr+2*xf)+2*`SQR(xf)*(xf+2*xr))/`SQR(xf+xr)-0.5); - // eq. 73 - qs = -nq*(4.0/15*(3*`SQR(xf)*(xf+2*xr)+2*`SQR(xr)*(xr+2*xf))/`SQR(xf+xr)-0.5); - // eq. 74 - qi = qs+qd; - // eq. 75 - if (vgprime>=0) - qb = (-gamma_a*sqrt(vp+phi+1e-6))/vt-(nq-1)/nq*qi; - else - qb = -vgprime/vt; - // eq. 76 (qox removed since it is assumed to be zero) - qg = -qi-qb; + end // INITIAL_MODEL - if (E0!=0) begin - // eq. 61 - beta0prime = beta0*(1+COX/(E0*`EPSSI)*qb0); - // eq. 62 - beta = beta0prime/(1+COX/(E0*`EPSSI)*vt*abs(qb+nau*qi)); - end else begin - // eq. 63 - vpprime = 0.5*(vp+sqrt(`SQR(vp)+2*`SQR(vt))); - // eq. 64 - beta = beta0/(1+THETA*vpprime); - end // else: !if(e0!=0) - // eq. 65 - is = 2*n*beta*`SQR(vt); - // $strobe("beta0=%e beta0prime=%e beta=%e E0=%e qb0=%e qb=%e qi=%e",beta0,beta0prime,beta,E0,qb0,qb,qi); - // eq. 66 - ids = is*(ifwd-irprime); - // eq. 67 - vib = vd-vs-IBN*2*vdss; - // eq. 68 - if (vib>0) begin - `expl((-ibb*lc)/vib,tmp) - idb = ids*IBA/ibb*vib*tmp; - end else - idb = 0; - // $strobe("ids=%e idb=%e",ids,idb); + `INSTANCE // temperature independent device initialization + begin + weff = w+dw; + leff = l+dl; + + // eq. 54 + lmin = 0.1*ns*leff; + + if (hdif > 0) begin + RSeff = ns/m*rsh*hdif/weff; + RDeff = ns/m*rsh*hdif/weff; + ADeff = 2*hdif*weff; + ASeff = 2*hdif*weff; + PDeff = 4*hdif+2*weff; + PSeff = 4*hdif+2*weff; + end else begin + RSeff = ns/m*rsh*nrs; + RDeff = ns/m*rsh*nrd; + ADeff = ad; + ASeff = as; + PDeff = pd; + PSeff = ps; + end + if (RDeff < `MIN_R) begin + RDeff = `MIN_R; + end + if (RSeff < `MIN_R) begin + RSeff = `MIN_R; + end + + ceps = 4*22e-3*22e-3; + ca = 0.028; + xsi = ca*(10*leff/lk-1); + dvrsce = 2*q0/cox_p/`SQR(1+0.5*(xsi+sqrt(xsi*xsi+ceps))); + + coxt = m*ns*cox_p*weff*leff; + + cbs0 = m*ns*cj*ASeff; + cbd0 = m*ns*cj*ADeff; + cbs0sw = m*ns*cjsw*PSeff; + cbd0sw = m*ns*cjsw*PDeff; + + cgso_s = m*ns*cgso*weff; + cgdo_s = m*ns*cgdo*weff; + cgbo_s = m*ns*cgbo*leff; + + end // temperature independent + + `INSTANCE // temperature dependent device initialization + begin + if (dtemp > 0.0) begin + TempK = $temperature + dtemp; + end else begin + TempK = $temperature; + end + + TnomK = tnom + 273.15; + + Vt = `VT(TempK); + + sqrt_A = sqrt(m*weff*ns*leff); + + vto_a = MOStype*(vto_p+tcv*(TempK-TnomK))+avto/sqrt_A; + kp_a = m*kp_p*pow(TempK/TnomK,bex)*(1+akp/sqrt_A); + gamma_a = gamma_p+agamma/sqrt_A; + ucrit_a = ucrit_p*pow(TempK/TnomK,ucex); + phi_a = phi_p*TempK/TnomK-3*Vt*ln(TempK/TnomK)-`EG(TnomK)*TempK/TnomK+`EG(TempK); + ibb_a = ibb*(1+ibbt*(TempK-TnomK)); + + vc = ucrit_a*ns*leff; + + // eq. 60 + qb0 = gamma_a*sqrt(phi_a); + + fact = (`EG(TnomK)/`VT(TnomK)-`EG(TempK)/Vt) * pow(TempK/TnomK,xti); + `expLin(tmp,fact) + isat_s = m*ns*(js*ASeff+jsw*PSeff)*tmp; + isat_d = m*ns*(js*ADeff+jsw*PDeff)*tmp; - if (mode>1) begin if (isat_s>0) begin - if (-vs>vexp_s) - ibsj = IMAX+gexp_s*(-vs-vexp_s); - else begin - `expl(-vs/(N*vt),tmp) - ibsj = isat_s*(tmp-1); - end - end else - ibsj = 0; - + vexp_s = Vt*ln(imax/isat_s+1); + gexp_s = (imax+isat_s)/Vt; + end else begin + vexp_s = -1e9; + gexp_s = 0; + end + if (isat_d>0) begin - if (-vd>vexp_d) - ibdj = IMAX+gexp_d*(-vd-vexp_d); - else begin - `expl(-vd/(N*vt),tmp) - ibdj = isat_d*(tmp-1); - end + vexp_d = Vt*ln(imax/isat_d+1); + gexp_d = (imax+isat_d)/Vt; + end else begin + vexp_d = -1e9; + gexp_d = 0; + end + + end // temperature dependent + + + begin //Bias-dependent model evaluation + + vg = MOStype*V(gb); + vd = MOStype*V(dpb); + vs = MOStype*V(spb); + // $strobe("MOStype %d vg=%e vd=%e vs=%e",MOStype,vg,vd,vs); + + if (vd>=vs) + mode = 1; + else begin + mode = -1; + tmp = vs; + vs = vd; + vd = tmp; + end + + // eq. 33 + vgprime = vg-vto_a-dvrsce+phi_a+gamma_a*sqrt(phi_a); + // eq. 35 + vsprime = 0.5*(vs+phi_a+sqrt(`SQR(vs+phi_a)+16*`SQR(Vt))); + vdprime = 0.5*(vd+phi_a+sqrt(`SQR(vd+phi_a)+16*`SQR(Vt))); + // $strobe("vgprime=%e vdprime=%e vsprime=%e",vgprime,vdprime,vsprime); + // eq. 34 + if (vgprime>=0) begin + vp0 = vgprime-phi_a-gamma_a*(sqrt(vgprime+0.25*`SQR(gamma_a))-0.5*gamma_a); + // eq. 36 + gamma0 = gamma_a-`EPSSI/cox_p*(leta/leff*(sqrt(vsprime)+sqrt(vdprime))-3*weta/weff*sqrt(vp0+phi_a)); + end else begin + vp0 = -phi_a; + // eq. 36 - skipped sqrt(vp0+phi_a) here, it produces inf on derivative + gamma0 = gamma_a-`EPSSI/cox_p*(leta/leff*(sqrt(vsprime)+sqrt(vdprime)) ); + end + // eq. 37 + gammaprime = 0.5*(gamma0+sqrt(`SQR(gamma0)+0.1*Vt)); + // eq. 38 + if (vgprime>=0) begin + vp = vgprime-phi_a-gammaprime*(sqrt(vgprime+0.25*`SQR(gammaprime))-0.5*gammaprime); + end else begin + vp = -phi_a; + end + // $strobe("vp0=%e vp=%e gamma0=%e gammaprime=%e",vp0,vp,gamma0,gammaprime); + // eq. 39 + nslope = 1+gamma_a*0.5/sqrt(vp+phi_a+4*Vt); + + // Forward current (43-44) + fv=(vp-vs)/Vt; + + `y_fv(fv,y) + + ifwd = y*(1.0 + y); + + // eq. 46 + vdss = vc*(sqrt(0.25+Vt/vc*sqrt(ifwd))-0.5); + // eq. 47 + vdssprime = vc*(sqrt(0.25+Vt/vc*(sqrt(ifwd)-0.75*ln(ifwd)))-0.5)+Vt*(ln(0.5*vc/Vt)-0.6); + // $strobe("ifwd=%e vdss=%e vdssprime=%e",ifwd,vdss,vdssprime); + // eq. 48 + dv = 4*Vt*sqrt(lambda*(sqrt(ifwd)-vdss/Vt)+1.0/64); + // eq. 49 + vds = 0.5*(vd-vs); + // eq. 50 + vip = sqrt(`SQR(vdss)+`SQR(dv))-sqrt(`SQR(vds-vdss)+`SQR(dv)); + // eq. 52 + dl_a = lambda*lc*ln(1+(vds-vip)/(lc*ucrit_a)); + + // eq. 53 + lprime = ns*leff-dl_a+(vds+vip)/ucrit_a; + // eq. 55 + leq = 0.5*(lprime+sqrt(`SQR(lprime)+`SQR(lmin))); + + // eq. 56 + fv=(vp-vds-vs-sqrt(`SQR(vdssprime)+`SQR(dv))+sqrt(`SQR(vds-vdssprime)+`SQR(dv)))/Vt; + + `y_fv(fv,y) + + irprime = y*(1.0 + y); + + // eq. 57 + fv=(vp-vd)/Vt; + + `y_fv(fv,y) + + irev = y*(1.0 + y); + + // eq. 58 + beta0 = kp_a*weff/leq; + // eq. 59 + nau = (5+MOStype)/12.0; + + // eq. 69 + nq = 1+0.5*gamma_a/sqrt(vp+phi_a+1e-6); + + // eq. 70 + xf = sqrt(0.25+ifwd); + // eq. 71 + xr = sqrt(0.25+irev); + // eq. 72 + qd = -nq*(4.0/15*(3*`SQR(xr)*(xr+2*xf)+2*`SQR(xf)*(xf+2*xr))/`SQR(xf+xr)-0.5); + // eq. 73 + qs = -nq*(4.0/15*(3*`SQR(xf)*(xf+2*xr)+2*`SQR(xr)*(xr+2*xf))/`SQR(xf+xr)-0.5); + // eq. 74 + qi = qs+qd; + // eq. 75 + if (vgprime>=0) begin + qb = (-gamma_a*sqrt(vp+phi_a+1e-6))/Vt-(nq-1)/nq*qi; + end else begin + qb = -vgprime/Vt; + end + // eq. 76 (qox removed since it is assumed to be zero) + qg = -qi-qb; + + if (e0!=0) begin + // eq. 61 + beta0prime = beta0*(1+cox_p/(e0*`EPSSI)*qb0); + // eq. 62 + beta = beta0prime/(1+cox_p/(e0*`EPSSI)*Vt*abs(qb+nau*qi)); + end else begin + // eq. 63 + vpprime = 0.5*(vp+sqrt(`SQR(vp)+2*`SQR(Vt))); + // eq. 64 + beta = beta0/(1+theta*vpprime); + end // else: !if(e0!=0) + // eq. 65 + is = 2*nslope*beta*`SQR(Vt); + // $strobe("beta0=%e beta0prime=%e beta=%e e0=%e qb0=%e qb=%e qi=%e",beta0,beta0prime,beta,e0,qb0,qb,qi); + // eq. 66 + ids = is*(ifwd-irprime); + // eq. 67 + vib = vd-vs-ibn*2*vdss; + // eq. 68 + if (vib>0) begin + `expLin(tmp,(-ibb_a*lc)/vib) + idb = ids*iba/ibb_a*vib*tmp; end else - ibdj = 0; - - end else begin // if (mode>1) - if (isat_s>0) begin - if (-vd>vexp_s) - ibsj = IMAX+gexp_s*(-vd-vexp_s); - else begin - `expl(-vd/(N*vt),tmp) - ibsj = isat_s*(tmp-1); - end - end else - ibsj = 0; - - if (isat_d>0) begin - if (-vs>vexp_d) - ibdj = IMAX+gexp_d*(-vs-vexp_d); - else begin - `expl(-vs/(N*vt),tmp) - ibdj = isat_d*(tmp-1); - end - end else - ibdj = 0; - - end // else: !if(mode>1) + idb = 0; + // $strobe("ids=%e idb=%e",ids,idb); - qdt = coxt*vt*qd; - qst = coxt*vt*qs; - qgt = coxt*vt*qg; - qbt = coxt*vt*qb; + if (mode>1) begin + if (isat_s>0) begin + if (-vs>vexp_s) + ibsj = imax+gexp_s*(-vs-vexp_s); + else begin + `expLin(tmp,-vs/(n*Vt)) + ibsj = isat_s*(tmp-1); + end + end else + ibsj = 0; - cbs = 0; - cbd = 0; - - if (cbs0>0) begin - if (MTYPE*V(b,si)>FC*PB) - cbs = cbs+cbs0/pow(1-FC,MJ)*(1+MJ*(MTYPE*V(b,si)-PB*FC))/(PB*(1-FC)); - else - cbs = cbs+cbs0/pow(1-MTYPE*V(b,si),MJ); - end - if (cbd0>0) begin - if (MTYPE*V(b,di)>FC*PB) - cbd = cbd+cbd0/pow(1-FC,MJ)*(1+MJ*(MTYPE*V(b,di)-PB*FC))/(PB*(1-FC)); - else - cbd = cbd+cbd0/pow(1-MTYPE*V(b,di),MJ); - end - if (cbs0sw>0) begin - if (MTYPE*V(b,si)>FCSW*PBSW) - cbs = cbs+cbs0sw/pow(1-FCSW,MJSW)*(1+MJSW*(MTYPE*V(b,si)-PBSW*FCSW))/(PBSW*(1-FCSW)); - else - cbs = cbs+cbs0sw/pow(1-MTYPE*V(b,si),MJSW); - end - if (cbd0sw>0) begin - if (MTYPE*V(b,di)>FCSW*PBSW) - cbd = cbd+cbd0sw/pow(1-FCSW,MJSW)*(1+MJSW*(MTYPE*V(b,di)-PBSW*FCSW))/(PBSW*(1-FCSW)); - else - cbd = cbd+cbd0sw/pow(1-MTYPE*V(b,di),MJSW); - end - - end //Bias-dependent model evaluation + if (isat_d>0) begin + if (-vd>vexp_d) + ibdj = imax+gexp_d*(-vd-vexp_d); + else begin + `expLin(tmp,-vd/(n*Vt)) + ibdj = isat_d*(tmp-1); + end + end else + ibdj = 0; - begin //Define branch sources + end else begin // if (mode>1) + if (isat_s>0) begin + if (-vd>vexp_s) + ibsj = imax+gexp_s*(-vd-vexp_s); + else begin + `expLin(tmp,-vd/(n*Vt)) + ibsj = isat_s*(tmp-1); + end + end else + ibsj = 0; - I(di,si) <+ MTYPE*mode*ids; - if (mode>0) begin - I(di,b) <+ MTYPE*idb; + if (isat_d>0) begin + if (-vs>vexp_d) + ibdj = imax+gexp_d*(-vs-vexp_d); + else begin + `expLin(tmp,-vs/(n*Vt)) + ibdj = isat_d*(tmp-1); + end + end else + ibdj = 0; - I(di,g) <+ MTYPE*ddt(qdt); - I(si,g) <+ MTYPE*ddt(qst); - - end else begin - I(si,b) <+ MTYPE*idb; + end // else: !if(mode>1) - I(si,g) <+ MTYPE*ddt(qdt); - I(di,g) <+ MTYPE*ddt(qst); - - end // else: !if(mode>0) + qdt = coxt*Vt*qd; + qst = coxt*Vt*qs; + qgt = coxt*Vt*qg; +// qbt = coxt*Vt*qb; - I(b,si) <+ MTYPE*ibsj; - I(b,di) <+ MTYPE*ibdj; - - I(b,g) <+ MTYPE*ddt(qbt); - - I(g,si) <+ cgso*ddt(V(g,si)); - I(g,di) <+ cgdo*ddt(V(g,di)); - I(g,b) <+ cgbo*ddt(V(g,b)); - - if (RD>0) - I(d,di) <+ V(d,di)/rd; - else - V(d,di) <+ 0.0; - if (RS>0) - I(s,si) <+ V(s,si)/rs; - else - V(s,si) <+ 0.0; + cbs = 0; + cbd = 0; + v_bp_dp = MOStype*V(b,dp); + v_bp_sp = MOStype*V(b,sp); + if (cbs0>0) begin + if (v_bp_sp>fc*pb) begin + cbs = cbs+cbs0/pow(1-fc,mj)*(1+mj*(v_bp_sp-pb*fc))/(pb*(1-fc)); + end else begin + cbs = cbs+cbs0/pow(1-v_bp_sp,mj); + end + end + if (cbd0>0) begin + if (v_bp_dp>fc*pb) begin + cbd = cbd+cbd0/pow(1-fc,mj)*(1+mj*(v_bp_dp-pb*fc))/(pb*(1-fc)); + end else begin + cbd = cbd+cbd0/pow(1-v_bp_dp,mj); + end + end + if (cbs0sw>0) begin + if (v_bp_sp>fcsw*pbsw) begin + cbs = cbs+cbs0sw/pow(1-fcsw,mjsw)*(1+mjsw*(v_bp_sp-pbsw*fcsw))/(pbsw*(1-fcsw)); + end else begin + cbs = cbs+cbs0sw/pow(1-v_bp_sp,mjsw); + end + end + if (cbd0sw>0) begin + if (v_bp_dp>fcsw*pbsw) begin + cbd = cbd+cbd0sw/pow(1-fcsw,mjsw)*(1+mjsw*(v_bp_dp-pbsw*fcsw))/(pbsw*(1-fcsw)); + end else begin + cbd = cbd+cbd0sw/pow(1-v_bp_dp,mjsw); + end + end - I(b,si) <+ cbs*ddt(V(b,si)); - I(b,di) <+ cbd*ddt(V(b,di)); - - end // begin + end //Bias-dependent model evaluation -// `NOISE begin //Define noise sources -// -// end // noise - - end //analog + begin //Define branch sources + + I(dpsp) <+ MOStype*mode*ids; + I(dpsp) <+ gmin*V(dpsp); + + if (mode>0) begin + I(dpb) <+ MOStype*idb; + I(dpb) <+ gmin*V(dpb); + + qdtx = qdt; + qstx = qst; + + end else begin + I(spb) <+ MOStype*idb; + I(spb) <+ gmin*V(spb); + + qdtx = qst; + qstx = qdt; + + end // else: !if(mode>0) + + I(dpb) <+ MOStype*ddt(qdtx); + I(spb) <+ MOStype*ddt(qstx); + I(gb) <+ MOStype*ddt(qgt); + //$strobe("V(dpb): %e qdtx=%e V(spb): %e qstx=%e V(gb): %e qgt: %e" ,V(dpb),qdtx,V(spb),qstx,V(gb),qgt); + + I(b,sp) <+ MOStype*ibsj; + I(b,dp) <+ MOStype*ibdj; + + qjs = cbs * v_bp_sp; + qjd = cbd * v_bp_dp; + I(b,sp) <+ MOStype*ddt(qjs); + I(b,dp) <+ MOStype*ddt(qjd); + //$strobe("v_bp_sp: %e cbs=%e v_bp_dp: %e cbd=%e" ,v_bp_sp,cbs,v_bp_dp,cbd); + + I(gpsp) <+ ddt(cgso_s*V(gpsp)); + I(gpdp) <+ ddt(cgdo_s*V(gpdp)); + I(gb) <+ ddt(cgbo_s*V(gb)) + gmin*V(dpsp); + //$strobe("V(gpsp): %e cgso_s=%e V(gpdp): %e cgdo_s=%e V(gb): %e cgbo_s: %e" ,V(gpsp),cgso_s,V(gpdp),cgdo_s,V(gb),cgbo_s); + + I(ddp) <+ V(ddp)/RDeff; + I(ssp) <+ V(ssp)/RSeff; + + end // begin + +// `NOISE begin //Define noise sources +// +// end // noise + + end //analog endmodule