1 /* $Id: d_mos4.model,v 26.92 2008/08/23 05:40:00 al Exp $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
23 * derived from Spice3f4,Copyright 1990 Regents of the University of California
24 * 1985 Hong J. Park, Thomas L. Quarles
25 * Recoded for Gnucap model compiler, Al Davis, 2000
28 #include "d_mos_base.h"
32 /*--------------------------------------------------------------------------*/
39 dev_type BUILT_IN_MOS;
40 inherit BUILT_IN_MOS_BASE;
43 double mjsw "" final_default=.33;
44 double pb "" final_default=0.1 quiet_min=0.1;
45 double pbsw "" final_default=pb quiet_min=0.1;
46 double cjo "" default=0.0;
47 int cmodel "CMODEL" print_test="cmodel!=1"
48 calculate="((!cmodel)?1:cmodel)";
49 int mos_level "back-annotate for diode" name=DIODElevel
50 print_test="mos_level != LEVEL" default=LEVEL;
53 double dl_u "Channel length reduction"
55 double dw_u "Channel width reduction"
57 double tox_u "Gate oxide thickness"
58 name=TOX default=0. quiet_min=1e-20;
59 double vdd "Supply voltage to specify mus"
61 double wdf "Default width of source drain diffusion (ignored)"
63 double dell "Length reduction of source drain diff (ignored)"
65 double temp "temperature (ignored)"
66 name=TEMP default=300.15;
67 double xpart "Flag for channel charge partitioning"
68 name=XPART default=0.;
70 calculated_parameters {
71 double dl "" calculate="dl_u*MICRON2METER";
72 double dw "" calculate="dw_u*MICRON2METER";
73 double tox "" calculate="tox_u*MICRON2METER";
74 double cox "" calculate="3.453e-11 /*E_OX*/ / tox";
79 double phi "Strong inversion surface potential"
80 name=PHI default=0. positive quiet_min=.1;
81 double vfb "Flat band voltage"
83 double k1 "Bulk effect coefficient 1"
84 name=K1 default=0. positive;
85 double k2 "Bulk effect coefficient 2"
86 name=K2 default=0. positive;
87 double eta "VDS dependence of threshold voltage"
89 double etaB "VBS dependence of eta (x2e)"
91 double etaD "VDS dependence of eta (x3e)"
93 double mobZero "Zero field mobility at VDS=0 VGS=VTH (muz)"
95 double mobZeroB "VBS dependence of muz (x2mz)"
97 double mobVdd "Mobility @ VDS=VDD VGS=VTH, chan len modulation"
99 double mobVddB "VBS dependence of mus (x2ms)"
100 name=X2MS default=0.;
101 double mobVddD "VDS dependence of mus (x3ms)"
102 name=X3MS default=0.;
103 double ugs "VGS dependence of mobility (u0)"
105 double ugsB "VBS dependence of u0 (x2u0)"
106 name=X2U0 default=0.;
107 double uds "VDS dependence of mobility, velocity saturation"
109 double udsB "VBS dependence of u1 (x2u1)"
110 name=X2U1 default=0.;
111 double udsD "VDS dependence of u1 (x3u1)"
112 name=X3U1 default=0.;
113 double n0 "Subthreshold slope (n0)"
115 double nB "VBS dependence of subthreshold slope (nb)"
117 double nD "VDS dependence of subthreshold slope (nd)"
120 calculated_parameters {
121 double betaZero "Beta at vds = 0 and vgs = Vth"
122 calculate="mobZero * CoxWoverL";
123 double betaZeroB "Vbs dependence of BetaZero"
124 calculate="mobZeroB * CoxWoverL";
125 double betaVdd "Beta at vds=Vdd and vgs=Vth"
126 calculate="mobVdd * CoxWoverL";
127 double betaVddB "Vbs dependence of BVdd"
128 calculate="mobVddB * CoxWoverL";
129 double betaVddD "Vds dependence of BVdd"
130 calculate="mobVddD * CoxWoverL";
131 double vt0 "" calculate="vfb + phi + k1 * sqrt(phi) - k2 * phi";
136 double L = l_eff/MICRON2METER;
137 double W = w_eff/MICRON2METER;
138 double CoxWoverL = 1e-4 * m->cox * w_eff / l_eff;
141 double cgate "" calculate="m->cox * w_eff * l_eff";
144 /*-----------------------------------------------------------------------*/
146 trace3("", d->vds, d->vgs, d->vbs);
147 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
148 d->reverse_if_needed();
149 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
150 trace2("", m->dl, m->dw);
151 trace3("", s->ugs, s->ugsB, d->vbs);
152 double Ugs = s->ugs + s->ugsB * d->vbs;
161 trace2("", Ugs, dUgsdVbs);
163 double Uds = s->uds + s->udsB * d->vbs + s->udsD * (d->vds - m->vdd);
169 dUdsdVbs = dUdsdVds = 0.0;
171 double Leff = s->l_eff * 1e6; /* Leff in um */
173 dUdsdVbs = s->udsB / Leff;
174 dUdsdVds = s->udsD / Leff;
176 trace3("", Uds, dUdsdVbs, dUdsdVds);
180 Vpb = s->phi - d->vbs;
186 double SqrtVpb = sqrt(Vpb);
187 trace2("", Vpb, SqrtVpb);
188 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
189 /* threshold voltage */
193 double Eta = s->eta + s->etaB * d->vbs + s->etaD * (d->vds - m->vdd);
198 dEtadVds = dEtadVbs = 0.0 ;
202 dEtadVds = dEtadVbs = 0;
208 trace3("", Eta, dEtadVds, dEtadVbs);
209 d->von = s->vfb + s->phi + s->k1 * SqrtVpb - s->k2 * Vpb - Eta * d->vds;
210 dVthdVds = -Eta - dEtadVds * d->vds;
211 dVthdVbs = s->k2 - 0.5 * s->k1 / SqrtVpb - dEtadVbs * d->vds;
212 d->vgst = d->vgs - d->von;
213 trace4("", d->von, dVthdVds, dVthdVbs, d->vgst);
215 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
216 double G = 1. - 1./(1.744+0.8364 * Vpb);
217 double A = 1. + 0.5*G*s->k1/SqrtVpb;
218 A = std::max(A, 1.0); /* Modified */
219 double Arg = std::max((1 + Ugs * d->vgst), 1.0);
220 double dGdVbs = -0.8364 * (1-G) * (1-G);
221 double dAdVbs = 0.25 * s->k1 / SqrtVpb *(2*dGdVbs + G/Vpb);
222 trace3("", G, A, Arg);
223 trace2("", dGdVbs, dAdVbs);
224 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
225 /* ids and derivatives calculation */
234 trace4("cutoff", d->ids, d->gmf, d->gds, d->gmbf);
237 /* Quadratic Interpolation for Beta0 (Beta at d->vgs = 0, vds=Vds) */
242 trace2("", m->tox, m->cox*1e-4);
243 trace3("", s->betaVdd, s->betaVddB, d->vbs);
244 double BetaVdd = (s->betaVdd + s->betaVddB * d->vbs);
245 double dBetaVdd_dVds = std::max(s->betaVddD, 0.0); /* Modified */
246 trace2("", BetaVdd, dBetaVdd_dVds);
247 if(d->vds > m->vdd) {
248 Beta0 = BetaVdd + dBetaVdd_dVds * (d->vds - m->vdd);
249 dBeta0dVds = dBetaVdd_dVds;
250 dBeta0dVbs = s->betaVddB;
251 trace3("vds>vdd", Beta0, dBeta0dVds, dBeta0dVbs);
253 double Beta_Vds_0 = (s->betaZero + s->betaZeroB * d->vbs);
254 double VddSquare = m->vdd * m->vdd;
255 double C1 = (-BetaVdd + Beta_Vds_0+dBetaVdd_dVds*m->vdd) / VddSquare;
256 double C2 = 2 * (BetaVdd - Beta_Vds_0) / m->vdd - dBetaVdd_dVds;
257 trace4("", Beta_Vds_0, VddSquare, C1, C2);
258 double dBeta_Vds_0_dVbs = s->betaZeroB;
259 double dBetaVdd_dVbs = s->betaVddB;
260 double dC1dVbs = (dBeta_Vds_0_dVbs - dBetaVdd_dVbs) / VddSquare;
261 double dC2dVbs = dC1dVbs * (-2) * m->vdd;
262 trace4("", dBeta_Vds_0_dVbs, dBetaVdd_dVbs, dC1dVbs, dC2dVbs);
263 Beta0 = (C1 * d->vds + C2) * d->vds + Beta_Vds_0;
264 dBeta0dVds = 2*C1*d->vds + C2;
265 dBeta0dVbs = dC1dVbs * d->vds * d->vds
266 + dC2dVbs * d->vds + dBeta_Vds_0_dVbs;
267 trace3("vds<vdd", Beta0, dBeta0dVds, dBeta0dVbs);
271 /*Beta = Beta0 / ( 1 + Ugs * d->vgst );*/
272 double Beta = Beta0 / Arg ;
273 double dBetadVgs = -Beta * Ugs / Arg;
274 double dBetadVds = dBeta0dVds / Arg - dBetadVgs * dVthdVds ;
275 double dBetadVbs = dBeta0dVbs / Arg
276 + Beta * Ugs * dVthdVbs / Arg - Beta * d->vgst * dUgsdVbs / Arg;
277 trace4("", Beta, dBetadVgs, dBetadVds, dBetadVbs);
279 /*d->vdsat = std::max(d->vgst / ( A + Uds * d->vgst ), 0.0);*/
280 double Vc = Uds * d->vgst / A;
286 double Term1 = sqrt(1 + 2 * Vc);
287 double K = 0.5 * (1 + Vc + Term1);
288 d->vdsat = std::max(d->vgst / (A * sqrt(K)) , 0.0);
289 trace4("", Vc, Term1, K, d->vdsat);
291 if(d->vds < d->vdsat) { /* Triode Region */
292 d->saturated = false;
293 /*Argl1 = 1 + Uds * d->vds;*/
294 double Argl1 = std::max((1 + Uds * d->vds), 1.);
295 double Argl2 = d->vgst - 0.5 * A * d->vds;
296 trace2("", Argl1, Argl2);
297 d->ids = Beta * Argl2 * d->vds / Argl1;
298 d->gmf = (dBetadVgs * Argl2 * d->vds + Beta * d->vds) / Argl1;
299 d->gds = (dBetadVds * Argl2 * d->vds
300 + Beta * (d->vgst - d->vds * dVthdVds - A * d->vds)
301 - d->ids * (d->vds * dUdsdVds + Uds)) / Argl1;
302 d->gmbf = (dBetadVbs * Argl2 * d->vds
303 + Beta * d->vds * (-dVthdVbs - 0.5 * d->vds * dAdVbs)
304 - d->ids * d->vds * dUdsdVbs) / Argl1;
305 trace4("triode", d->ids, d->gmf, d->gds, d->gmbf);
306 }else{ /* Pinchoff (Saturation) Region */
308 double Args1 = 1. + 1. / Term1;
309 double dVcdVgs = Uds / A;
310 double dVcdVds = d->vgst * dUdsdVds / A - dVcdVgs * dVthdVds;
311 double dVcdVbs = (d->vgst * dUdsdVbs
312 - Uds * (dVthdVbs + d->vgst * dAdVbs / A )) / A;
313 double dKdVc = 0.5 * Args1;
314 double dKdVgs = dKdVc * dVcdVgs;
315 double dKdVds = dKdVc * dVcdVds;
316 double dKdVbs = dKdVc * dVcdVbs;
317 double Args2 = d->vgst / A / K;
318 double Args3 = Args2 * d->vgst;
319 trace3("", Args1, Args2, Args3);
320 trace3("", dVcdVgs, dVcdVds, dVcdVbs);
321 trace4("", dKdVc, dKdVgs, dKdVds, dKdVbs);
322 d->ids = 0.5 * Beta * Args3;
323 d->gmf = 0.5 * Args3 * dBetadVgs + Beta * Args2 - d->ids * dKdVgs / K;
324 d->gds = 0.5*Args3*dBetadVds - Beta*Args2*dVthdVds - d->ids*dKdVds/K;
325 d->gmbf = 0.5 * dBetadVbs * Args3 - Beta * Args2 *dVthdVbs
326 - d->ids * (dAdVbs / A + dKdVbs / K);
327 trace4("sat", d->ids, d->gmf, d->gds, d->gmbf);
330 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
331 /* SubthresholdComputation */
333 /* The following 'if' statement has been modified so that subthreshold *
334 * current computation is always executed unless N0 >= 200. This should *
335 * get rid of the Ids kink seen on Ids-Vgs plots at low Vds. *
338 * Old 'if' statement: (reversed) *
339 * if( (N0 >= 200) || (d->vgst < Vcut ) || (d->vgst > (-0.5*Vcut))) */
341 //double Vcut = - 40. * s->n0 * t->vt ;
343 double N = s->n0 + s->nB*d->vbs + s->nD*d->vds; /* subthreshold slope */
344 trace4("", s->n0, s->nB, s->nD, N);
349 const double ref_temp = 300.15; // ignore real temp for spice compatibility
350 const double vt0 = ref_temp * P_K_Q;
351 const double Vtsquare = vt0 * vt0 ;
352 const double nvt0 = N * vt0;
353 double Warg1 = exp(-d->vds / vt0);
354 double Wds = 1 - Warg1;
355 double Wgs = exp( d->vgst / nvt0);
356 double Warg2 = 6.04965 * Vtsquare * s->betaZero;
357 double Ilimit = 4.5 * Vtsquare * s->betaZero;
358 double Iexp = Warg2 * Wgs * Wds;
359 d->ids += Ilimit * Iexp / (Ilimit + Iexp);
360 double Temp1 = Ilimit / (Ilimit + Iexp);
361 Temp1 = Temp1 * Temp1;
362 double Temp3 = Ilimit / (Ilimit + Wgs * Warg2);
363 Temp3 = Temp3 * Temp3 * Warg2 * Wgs;
364 /* if ( Temp3 > Ilimit ) Temp3=Ilimit;*/
365 d->gmf += Temp1 * Iexp / nvt0;
366 /* gds term has been modified to prevent blow up at Vds=0 */
368 * (Wds / nvt0 * (dVthdVds + d->vgst * s->nD / N)
370 d->gmbf -= Temp1 * Iexp * (dVthdVbs + d->vgst * s->nB / N) / nvt0;
371 trace3("", vt0, Vtsquare, nvt0);
372 trace4("", Warg1, Wds, Wgs, Warg2);
373 trace4("", Ilimit, Iexp, Temp1, Temp3);
374 trace4("sub", d->ids, d->gmf, d->gds, d->gmbf);
378 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
379 /* Some Limiting of DC Parameters */
380 if(d->ids < 0.0) d->ids = 0.0;
381 if(d->gmf < 0.0) d->gmf = 0.0;
382 if(d->gds < 0.0) d->gds = 0.0;
383 if(d->gmbf < 0.0) d->gmbf = 0.0;
384 trace4("final", d->ids, d->gmf, d->gds, d->gmbf);
386 trace3("", G, A, s->phi);
387 trace1("", m->xpart);
389 double Vth0 = s->vfb + s->phi + s->k1 * SqrtVpb; // almost same as d->von
390 double Vgs_Vth = d->vgs - Vth0; // almost same as d->vgst
391 trace2("", Vth0, Vgs_Vth);
392 double Arg1 = A * d->vds;
393 double Arg2 = Vgs_Vth - 0.5 * Arg1;
394 double Arg3 = d->vds - Arg1;
395 trace3("", Arg1, Arg2, Arg3);
396 /*double*/ dVthdVbs = -0.5 * s->k1 / SqrtVpb;
397 /*dbl*/ dAdVbs = 0.5 * s->k1 * (0.5*G/Vpb - 0.8364*(1-G)*(1-G)) / SqrtVpb;
398 trace2("", dVthdVbs, dAdVbs);
399 double Ent = std::max(Arg2,1.0e-8);
400 double dEntdVds = -0.5 * A;
401 double dEntdVbs = -dVthdVbs - 0.5 * d->vds * dAdVbs;
402 trace3("", Ent, dEntdVds, dEntdVbs);
403 double VdsPinchoff = std::max(Vgs_Vth / A, 0.0);
404 double Vgb = d->vgs - d->vbs ;
405 double Vgb_Vfb = Vgb - s->vfb;
406 trace3("", VdsPinchoff, Vgb, Vgb_Vfb);
408 if(Vgb_Vfb < 0) { /* Accumulation Region */
410 d->qgate = s->cgate * Vgb_Vfb;
411 d->qbulk = -d->qgate;
422 trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
423 trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
424 trace4("acc", d->qdrn, d->cdgb, d->cddb, d->cdsb);
425 }else if (d->vgs < Vth0) { /* Subthreshold Region */
426 d->qgate = 0.5*s->cgate*s->k1*s->k1*(-1+sqrt(1+4*Vgb_Vfb/(s->k1*s->k1)));
427 d->cggb = s->cgate / sqrt(1 + 4 * Vgb_Vfb / (s->k1 * s->k1));
428 d->cgdb = d->cgsb = 0.;
429 d->qbulk = -d->qgate;
431 d->cbdb = d->cbsb = 0.0;
433 d->cdgb = d->cddb = d->cdsb = 0.0;
434 trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
435 trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
436 trace4("sub", d->qdrn, d->cdgb, d->cddb, d->cdsb);
437 }else if (d->vds < VdsPinchoff) { /* triode region */
438 double EntSquare = Ent * Ent;
439 trace1("tri", EntSquare);
440 double Argl1 = 1.2e1 * EntSquare;
441 double Argl2 = 1.0 - A;
442 double Argl3 = Arg1 * d->vds;
443 trace3("", Argl1, Argl2, Argl3);
451 double Argl7 = Argl5 / 1.2e1;
452 double Argl8 = 6.0 * Ent;
453 trace3("", Argl5, Argl7, Argl8);
456 * (d->vgs - s->vfb - s->phi - 0.5 * d->vds + d->vds * Argl7);
457 d->cggb = s->cgate * (1.0 - Argl3 / Argl1);
458 d->cgdb = s->cgate * (-0.5 + Arg1 / Argl8 - Argl3 * dEntdVds / Argl1);
459 double cgbb = s->cgate * (d->vds*d->vds*dAdVbs*Ent-Argl3*dEntdVbs)/Argl1;
460 d->cgsb = -(d->cggb + d->cgdb + cgbb);
461 trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
463 d->qbulk = s->cgate * (-Vth0 + s->vfb + s->phi + 0.5*Arg3 - Arg3*Argl7);
464 d->cbgb = s->cgate * Argl3 * Argl2 / Argl1;
465 d->cbdb = s->cgate * Argl2 * (0.5 - Arg1/Argl8 + Argl3 * dEntdVds/Argl1);
466 double cbbb = -s->cgate * (dVthdVbs + 0.5 * d->vds * dAdVbs
467 +d->vds*d->vds*((1.0-2.0*A)*dAdVbs*Ent-Argl2*A*dEntdVbs)/Argl1);
468 d->cbsb = -(d->cbgb + d->cbdb + cbbb);
469 trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
472 /*0/100 partitioning for drain/source chArges at saturation region*/
473 double Argl9 = 0.125 * Argl5 * Argl5; //t
474 d->qdrn = -s->cgate * (0.5*Vgs_Vth - 0.75*Arg1 + 0.125*Arg1*Argl5);
475 d->cdgb = -s->cgate * (0.5 - Argl9);
476 d->cddb = s->cgate * (0.75*A - 0.25*A*Arg1/Ent + Argl9*dEntdVds);
477 double cdbb = s->cgate * (0.5 * dVthdVbs + d->vds * dAdVbs *
478 (0.75 - 0.25 * Argl5 ) + Argl9 * dEntdVbs);
479 d->cdsb = -(d->cdgb + d->cddb + cdbb);
480 trace2("", Argl9, cdbb);
481 trace4("tri 0/100", d->qdrn, d->cdgb, d->cddb, d->cdsb);
483 /*40/60 partitioning for drain/source chArges at saturation region*/
484 double Vgs_VthSquare = Vgs_Vth*Vgs_Vth;
485 trace2("", Vgs_Vth, Vgs_VthSquare);
486 double Arg5 = Arg1*Arg1;
487 double Vcom = Vgs_Vth*Vgs_Vth/6.0-1.25e-1*Arg1*Vgs_Vth+2.5e-2*Arg5;
488 double Argl4 = Vcom/Ent/EntSquare;
491 Argl6 = Vcom / EntSquare;
496 d->qdrn = -s->cgate * (0.5 * (Vgs_Vth-Arg1) + Arg1 * Argl6);
498 * (0.5 + Arg1*(4.0*Vgs_Vth-1.5*Arg1)/Argl1 - 2.0*Arg1*Argl4);
499 d->cddb = s->cgate*(0.5*A+2.0*Arg1*dEntdVds*Argl4-A*(2.0*Vgs_VthSquare
500 -3.0*Arg1*Vgs_Vth+0.9*Arg5)/Argl1);
501 double cdbb =s->cgate*(0.5*dVthdVbs+0.5*d->vds*dAdVbs+2.0*Arg1*dEntdVbs
502 *Argl4-d->vds*(2.0*Vgs_VthSquare*dAdVbs-4.0*A*Vgs_Vth*dVthdVbs-3.0
503 *Arg1*Vgs_Vth*dAdVbs+1.5*A*Arg1*dVthdVbs+0.9*Arg5*dAdVbs)
505 d->cdsb = -(d->cdgb + d->cddb + cdbb);
506 trace4("", Vcom, Argl4, Argl6, cdbb);
507 trace4("lin 40/60", d->qdrn, d->cdgb, d->cddb, d->cdsb);
509 }else{ /* saturation region */
510 assert(d->vds >= VdsPinchoff);
511 double Args1 = 1.0 / (3.0 * A);
512 trace2("sat", s->cgate, Args1);
514 d->qgate = s->cgate * (d->vgs - s->vfb - s->phi - Vgs_Vth * Args1);
515 d->cggb = s->cgate * (1.0 - Args1);
517 double cgbb = s->cgate * Args1 * (dVthdVbs + Vgs_Vth * dAdVbs / A);
518 d->cgsb = -(d->cggb + d->cgdb + cgbb);
519 trace4("", d->qgate, d->cggb, d->cgdb, d->cgsb);
521 d->qbulk = s->cgate * (s->vfb + s->phi - Vth0 + (1.0-A)*Vgs_Vth*Args1);
522 d->cbgb = s->cgate * (Args1 - 1.0 / 3.0);
524 double cbbb = -s->cgate * ((2.0 / 3.0 + Args1) * dVthdVbs
525 + Vgs_Vth * Args1 * dAdVbs / A);
526 d->cbsb = -(d->cbgb + d->cbdb + cbbb);
527 trace4("", d->qbulk, d->cbgb, d->cbdb, d->cbsb);
530 /*0/100 partitioning for drain/source chArges at saturation region*/
535 trace4("sat 0/100", d->qdrn, d->cdgb, d->cddb, d->cdsb);
537 /*40/60 partitioning for drain/source chArges at saturation region*/
538 const double co4v15 = 4./15.;
539 d->qdrn = -co4v15 * s->cgate * Vgs_Vth;
540 d->cdgb = -co4v15 * s->cgate;
542 double cdbb = co4v15 * s->cgate * dVthdVbs;
543 d->cdsb = -(d->cdgb + d->cddb + cdbb);
544 trace4("sat 40/60", d->qdrn, d->cdgb, d->cddb, d->cdsb);
551 d->gmf = d->gmbf = 0;
553 d->gmr = d->gmbr = 0.;
557 /*--------------------------------------------------------------------------*/
558 /*--------------------------------------------------------------------------*/