DIRECTORY Rope USING [ROPE], RealFns USING [Exp], RealOps USING [SqRt], spGlobals USING [EnterModels, model, Retreat]; spModels: CEDAR PROGRAM IMPORTS RealFns, RealOps, spGlobals EXPORTS spGlobals= BEGIN modelError: SIGNAL[s: Rope.ROPE]= CODE; NFET: spGlobals.model= { VgX: NAT= 0; VsX: NAT= 1; VdX: NAT= 2; VbX: NAT= 3; VtX: NAT= 0; hKp: NAT= 1; Phi2: NAT= 2; Phi2fb: NAT= 3; Kb: NAT= 4; ftKb: NAT= 5; hKbsq: NAT= 6; qKbsq: NAT= 7; Vfb: NAT= 8; Cox: NAT= 9; Cgsd0: NAT= 10; Cgsdp: NAT= 11; Ioff: NAT= 12; Io: NAT= 13; kTq: NAT= 14; expMax: NAT= 15; IdX: NAT= 0; CgbX: NAT= 1; CgsX: NAT= 2; CgdX: NAT= 3; Vg, Vs, Vd, Vb, Id: REAL; Cgs, Cgd: REAL; Vt, Vgst, Vgdt, VdSAT, Vsbphi2, Vdx, SqrtV: REAL; t1, t2: REAL; reverse: BOOL_ FALSE; Vg_ args[VgX]; Vb_ args[VbX]; Vd_ args[VdX]; Vs_ args[VsX]; t1_ Vb - Vs; IF t1 > 0.0 THEN { t1_ t1/parms[kTq]; IF t1 >= parms[expMax] THEN SIGNAL spGlobals.Retreat["NFET -- Source."]; results[4]_ parms[Io]*(RealFns.Exp[t1] - 1.0); } ELSE results[4]_ -parms[Io]; t2_ Vb - Vd; IF t2 > 0.0 THEN { t2_ t2/parms[kTq]; IF t2 >= parms[expMax] THEN SIGNAL spGlobals.Retreat["NFET -- Drain."]; results[5]_ parms[Io]*(RealFns.Exp[t2] - 1.0); } ELSE results[5]_ -parms[Io]; IF Vs > Vd THEN { reverse_ TRUE; t1_ Vs; Vs_ Vd; Vd_ t1; }; Vsbphi2_ MAX[Vs - Vb + parms[Phi2], 0.0]; SqrtV_ RealOps.SqRt[MAX[0.0, parms[qKbsq] + Vg - parms[Vfb] - Vb]]; Vt_ IF Vs= Vb THEN parms[VtX] ELSE parms[Phi2fb] + parms[Kb]*RealOps.SqRt[Vsbphi2]; Vgst_ Vg - Vs - Vt; IF Vgst > 0 THEN { VdSAT_ Vg - parms[Phi2fb] + parms[hKbsq] - parms[Kb]*SqrtV; IF VdSAT < Vs THEN SIGNAL modelError["Negative VdSAT"]; Vdx_ IF Vd > VdSAT THEN VdSAT ELSE Vd; t1_ Vsbphi2*RealOps.SqRt[Vsbphi2]; t2_ Vdx - Vb + parms[Phi2]; t2_ t2*RealOps.SqRt[t2]; Id_ parms[hKp]*((2.0*(Vg - parms[Phi2fb]) - Vs - Vdx)* (Vdx - Vs) + parms[ftKb]*(t1 - t2)); } ELSE Id_ parms[Ioff]; IF Id < 0.0 THEN IF Id < -parms[Ioff] THEN SIGNAL modelError["Negative drain current"] ELSE Id_ parms[Ioff]; t1_ Vg - Vb - parms[Vfb]; IF t1 <= 0.0 THEN results[CgbX]_ parms[Cox] ELSE results[CgbX]_ 0.5*parms[Kb]*parms[Cox]/SqrtV; Vgdt_ Vg - Vd - Vt; t1_ Vgst + Vgdt; t1_ t1*t1; IF Vgst <= 0.0 THEN Cgs_ parms[Cgsdp] ELSE IF Vgdt < 0.0 THEN Cgs_ parms[Cgsd0] + parms[Cgsdp] ELSE Cgs_ parms[Cgsdp] + parms[Cgsd0]*(1.0 - Vgdt*Vgdt/t1); IF Vgdt <= 0.0 THEN Cgd_ parms[Cgsdp] ELSE Cgd_ parms[Cgsdp] + parms[Cgsd0]*(1.0 - Vgst*Vgst/t1); IF reverse THEN { results[IdX] _ -Id; results[CgsX]_ Cgd; results[CgdX]_ Cgs; } ELSE { results[IdX] _ Id; results[CgsX]_ Cgs; results[CgdX]_ Cgd; }; }; -- NFET PFET: spGlobals.model= { VgX: NAT= 0; VsX: NAT= 1; VdX: NAT= 2; VbX: NAT= 3; VtX: NAT= 0; hKp: NAT= 1; Phi2: NAT= 2; Phi2fb: NAT= 3; Kb: NAT= 4; ftKb: NAT= 5; hKbsq: NAT= 6; qKbsq: NAT= 7; Vfb: NAT= 8; Cox: NAT= 9; Cgsd0: NAT= 10; Cgsdp: NAT= 11; Ioff: NAT= 12; Io: NAT= 13; kTq: NAT= 14; expMax: NAT= 15; IdX: NAT= 0; CgbX: NAT= 1; CgsX: NAT= 2; CgdX: NAT= 3; Vg, Vs, Vd, Vb, Id: REAL; Cgs, Cgd: REAL; Vt, Vgst, Vgdt, VdSAT, Vsbphi2, Vdx, SqrtV: REAL; t1, t2: REAL; reverse: BOOL_ FALSE; Vg_ args[VgX]; Vb_ args[VbX]; Vd_ args[VdX]; Vs_ args[VsX]; t1_ Vs - Vb; IF t1 > 0.0 THEN { t1_ t1/parms[kTq]; IF t1 >= parms[expMax] THEN SIGNAL spGlobals.Retreat["PFET -- Source."]; results[4]_ parms[Io]*(RealFns.Exp[t1] - 1.0); } ELSE results[4]_ -parms[Io]; t2_ Vd - Vb; IF t2 > 0.0 THEN { t2_ t2/parms[kTq]; IF t2 >= parms[expMax] THEN SIGNAL spGlobals.Retreat["PFET -- Drain."]; results[5]_ parms[Io]*(RealFns.Exp[t2] - 1.0); } ELSE results[5]_ -parms[Io]; IF Vs < Vd THEN { reverse_ TRUE; t1_ Vs; Vs_ Vd; Vd_ t1; }; Vsbphi2_ MIN[Vs - Vb + parms[Phi2], 0.0]; SqrtV_ RealOps.SqRt[-MIN[0.0, -parms[qKbsq] + Vg - parms[Vfb] - Vb]]; Vt_ IF Vs= Vb THEN parms[VtX] ELSE parms[Phi2fb] - parms[Kb]*RealOps.SqRt[-Vsbphi2]; Vgst_ Vg - Vs - Vt; IF Vgst < 0 THEN { VdSAT_ Vg - parms[Phi2fb] - parms[hKbsq] + parms[Kb]*SqrtV; IF VdSAT > Vs THEN SIGNAL modelError["Positive VdSAT"]; Vdx_ IF Vd < VdSAT THEN VdSAT ELSE Vd; t1_ Vsbphi2*RealOps.SqRt[-Vsbphi2]; t2_ Vdx - Vb + parms[Phi2]; t2_ t2*RealOps.SqRt[-t2]; Id_ parms[hKp]*((2.0*(Vg - parms[Phi2fb]) - Vs - Vdx)* (Vdx - Vs) - parms[ftKb]*(t1 - t2)); } ELSE Id_ parms[Ioff]; IF Id < 0.0 THEN IF Id < -parms[Ioff]THEN SIGNAL modelError["Negative drain current"] ELSE Id_ parms[Ioff]; t1_ Vg - Vb - parms[Vfb]; IF t1 >= 0.0 THEN results[CgbX]_ parms[Cox] ELSE results[CgbX]_ 0.5*parms[Kb]*parms[Cox]/SqrtV; Vgdt_ Vg - Vd - Vt; t1_ Vgst + Vgdt; t1_ t1*t1; IF Vgst >= 0.0 THEN Cgs_ parms[Cgsdp] ELSE IF Vgdt > 0.0 THEN Cgs_ parms[Cgsd0] + parms[Cgsdp] ELSE Cgs_ parms[Cgsdp] + parms[Cgsd0]*(1.0 - Vgdt*Vgdt/t1); IF Vgdt >= 0.0 THEN Cgd_ parms[Cgsdp] ELSE Cgd_ parms[Cgsdp] + parms[Cgsd0]*(1.0 - Vgst*Vgst/t1); IF reverse THEN { results[IdX] _ -Id; results[CgsX]_ Cgd; results[CgdX]_ Cgs; } ELSE { results[IdX] _ Id; results[CgsX]_ Cgs; results[CgdX]_ Cgd; }; }; -- PFET dcDiode: spGlobals.model= { Vd, e: REAL; Va: NAT= 0; Vc: NAT= 1; Io: NAT= 0; kTq: NAT= 1; expMax: NAT= 2; Vd_ args[Va] - args[Vc]; IF Vd + parms[kTq] <= 0.0 THEN results[0]_ -parms[Io] ELSE { e_ Vd/parms[kTq]; IF e >= parms[expMax] THEN SIGNAL spGlobals.Retreat["dcDiode."]; results[0]_ parms[Io]*(RealFns.Exp[e] - 1.0); }; }; -- dcDiode CSIM: spGlobals.model= { VgX: NAT= 0; VsX: NAT= 1; VdX: NAT= 2; VbX: NAT= 3; vfb: NAT= 0; twoPhiF: NAT= 1; k1: NAT= 2; k2: NAT= 3; eta: NAT= 4; beta0: NAT= 5; u0: NAT= 6; u1: NAT= 7; MCgbo: NAT= 8; Cgbo23rds: NAT= 9; Cov: NAT= 10; Cbso: NAT= 11; Cbdo: NAT= 12; phiB: NAT= 13; Ios: NAT= 14; Iod: NAT= 15; kTq: NAT= 16; expMax: NAT= 17; NoCap: NAT= 18; nChannel: NAT= 19; -- -1: pType; else nType; IdX : NAT= 0; CgbX: NAT= 1; CgsX: NAT= 2; CgdX: NAT= 3; CbsX: NAT= 4; CbdX: NAT= 5; Ibs: NAT= 6; Ibd: NAT= 7; Vg, Vs, Vd, Vb, Vds, Vgs, Vbs, Vbd: REAL; Id, Cgs, Cgd, Cbs, Cbd: REAL; reverse: BOOL_ FALSE; t1, TwoPhiFMVbs, Sqrt2PhiFMVbs, EtaVds, VgsMVth, VgdMVth, Vth: REAL; IF parms[nChannel]= -1 THEN { Vg_ -args[VgX]; Vb_ -args[VbX]; Vd_ -args[VdX]; Vs_ -args[VsX]; } ELSE { parms[nChannel]_ 1; Vg_ args[VgX]; Vb_ args[VbX]; Vd_ args[VdX]; Vs_ args[VsX]; }; IF Vb > Vs THEN { t1_ (Vb-Vs)/parms[kTq]; IF t1 >= parms[expMax] THEN SIGNAL spGlobals.Retreat[ "CSIM -> Vbs forward biased too much"]; results[Ibs]_ parms[nChannel]*parms[Ios]*(RealFns.Exp[t1]- 1.0); } ELSE results[Ibs]_ -parms[nChannel]*parms[Ios]; IF Vb > Vd THEN { t1_ (Vb-Vd)/parms[kTq]; IF t1 >= parms[expMax] THEN SIGNAL spGlobals.Retreat[ "CSIM -> Vbd forward biased too much"]; results[Ibd]_ parms[nChannel]*parms[Iod]*(RealFns.Exp[t1]- 1.0); } ELSE results[Ibd]_ -parms[nChannel]*parms[Iod]; IF Vs > Vd THEN {reverse_ TRUE; t1_ Vs; Vs_ Vd; Vd_ t1; }; Vds_ Vd - Vs; Vgs_ Vg - Vs; Vbs_ Vb - Vs; Vbd_ Vb - Vd; TwoPhiFMVbs_ parms[twoPhiF]-Vbs; Sqrt2PhiFMVbs_ RealOps.SqRt[TwoPhiFMVbs]; EtaVds_ parms[eta]*Vds; Vth_ parms[vfb]+parms[twoPhiF]+parms[k1]*Sqrt2PhiFMVbs-EtaVds -parms[k2]*TwoPhiFMVbs; VgsMVth_ Vgs - Vth; IF VgsMVth <= 0.0 THEN Id_ 0 ELSE { -- Vgs>Vth: g: REAL_ 1.0-1.0/(1.744+0.8364*TwoPhiFMVbs); a: REAL_ 1.0 + 0.5*g*parms[k1]/Sqrt2PhiFMVbs; alpha: REAL_ a*(1.0 + parms[u1]*VgsMVth); -- a(1+u1*(Vgs-Vth)) VdSat: REAL_ VgsMVth/alpha; BetaP: REAL_ parms[nChannel]*parms[beta0] /(1.0+parms[u0]*VgsMVth); -- beta0/(1+u0(Vgs-Vth)) Id_ IF VdsVth IF parms[NoCap]#0 THEN { results[CgbX]_ results[CgsX]_ results[CgdX]_ results[CbsX]_ results[CbdX]_ 0; results[IdX]_ IF reverse THEN -Id ELSE Id; RETURN; }; VgdMVth_ Vg - Vd - Vth; results[CgbX]_ IF VgsMVth <= 0 THEN parms[MCgbo] ELSE 0; t1_ VgsMVth+VgdMVth; t1_ t1*t1; -- (Vgs + Vgd - 2Vth)^2 Cgs_ IF VgsMVth <= 0.0 THEN parms[Cov] ELSE IF VgdMVth <= 0.0 THEN parms[Cgbo23rds] + parms[Cov] ELSE parms[Cov] + parms[Cgbo23rds]*(1.0 - VgdMVth*VgdMVth/t1); Cgd_ IF VgdMVth <= 0.0 THEN parms[Cov] ELSE parms[Cov] + parms[Cgbo23rds]*(1.0 - VgsMVth*VgsMVth/t1); Cbs_ parms[Cbso]/RealOps.SqRt[1.0 - Vbs/parms[phiB]]; Cbd_ parms[Cbdo]/RealOps.SqRt[1.0 - Vbd/parms[phiB]]; IF reverse THEN { results[IdX]_ -Id; results[CgsX]_ Cgd; results[CgdX]_ Cgs; results[CbsX]_ Cbd; results[CbdX]_ Cbs; } ELSE { results[IdX]_ Id; results[CgsX]_ Cgs; results[CgdX]_ Cgd; results[CbsX]_ Cbs; results[CbdX]_ Cbd; }; }; -- CSIM acDiode: spGlobals.model= { Vc: NAT= 0; -- cathode voltage index Va: NAT= 1; -- anode voltage index Co: NAT= 0; Pb: NAT= 1; Vt: NAT= 2; Io: NAT= 3; expMax: NAT= 4; C: NAT= 0; I: NAT= 1; t1: REAL; V: REAL_ args[Va] - args[Vc]; IF V > 0 THEN { -- forward biased t1_ V/parms[Vt]; IF t1 >= parms[expMax] THEN SIGNAL spGlobals.Retreat[ "acDiode forward biased too much"]; results[I]_ -parms[Io]*(RealFns.Exp[t1]- 1.0); } ELSE results[I]_ parms[Io]; results[C]_ parms[Co]/RealOps.SqRt[1.0 - V/parms[Pb]]; }; -- acDiode spGlobals.EnterModels["CSIM", CSIM, 4, 20, 8]; spGlobals.EnterModels["acDiode", acDiode, 2, 5, 2]; spGlobals.EnterModels["dcDiode", dcDiode, 2, 3, 1]; spGlobals.EnterModels["NFET", NFET, 4, 16, 6]; spGlobals.EnterModels["PFET", PFET, 4, 16, 6]; END. File: [Cherry]Cedar5.1>System>spModels.mesa Last editted: Chen June 7, 1984 8:14:41 pm PDT Last Edited by: SChen, June 11, 1984 7:41:49 pm PDT args: The 8 electrical parameters of CSIM model. cf. Scharfetter's memo of 12/30/82. The 6 capacitance parameters for MOSAID model. cf. MOSAID documentation by Dick Foss. other parameters: results: get Ibs: get Ibd: If it ever gets here, Vbs must be less than 2phif. cf. expMax calculation in ThymeBasics.thy Cgb: Cgs and Cgd: Cbs and Cbd: Since phiB>2phif, the following should never blow up. CHANGE LOG Wilhelm, April 12, 1982 9:28 AM Barth, 7-May-82 10:43:16 PDT Chen, April 29, 1983 12:03 PM, added and "enter"ed CSIM and acDiode model. Chen, June 7, 1984 8:14:49 pm PDT, cedarized. ʈ˜JšÏc2™2Jš.™.J™3J˜JšÏf ˜ Jšœž˜Jšœž˜Jšœž˜Jšœž.˜0J˜Jšž˜Jšž9˜9J˜Jšž˜Jšž(˜(JšžÃÐctž˜ËJšžÌŸ ˜ÕJšžèŸ ž˜óJšž˜J™Jšž™Jšž:˜:JšŸP™PJšžt˜tJšœW™WJšœžc˜dJšœ™JšœždŸ˜~J˜JšžŸž™ Jšžö˜öJšŸ ™ Jšœž’˜”JšŸ ™ Jšž˜Jšœž2™4Jšœž)™+JšœžŸ žÉŸžÖ˜ÊJšŸ™JšœžD˜GJšŸ™Jšœž!Ÿž«˜æJšŸE™EJšœž‚Ÿž˜Jšž˜Jšœž$˜&Jšœž%˜'Jšœž ˜ Jšœž ˜ Jšœž ˜ Jšœž ˜ Jšœž˜Jšœž ˜ Jšœž ˜Jšœž ˜ Jšœž˜JšœžŸž˜7Jšœž5˜:Jšœž#˜*JšœžO˜RJšœž6˜9JšžŸ ž˜ Jšž4˜4Jšž4˜4Jšž4˜4Jšž4˜4Jšž4˜4J˜Jšž˜J˜JšŸ ™ J˜Jšœ ™ Jšœ™Jšœ4Ïkœ™KJšœ-™-—…—&Ú,h