1 /* $Id: d_mos1.model,v 26.133 2009/11/26 04:58:04 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 *------------------------------------------------------------------
22 * mos model equations: spice level 1 equivalent
29 /*--------------------------------------------------------------------------*/
38 dev_type BUILT_IN_MOS;
39 inherit BUILT_IN_MOS123;
42 double mjsw "" default=.5;
43 double cox "" final_default=0.;
44 double vto "" final_default=0.;
45 double gamma "" final_default=0.;
46 double phi "" final_default=.6;
47 int mos_level "back-annotate for diode" name=DIODElevel
48 print_test="mos_level != LEVEL" default=LEVEL;
51 double kp "transconductance parameter"
52 name=KP final_default=2e-5
53 print_test="!calc_kp" calc_print_test="calc_kp";
55 calculated_parameters {
56 bool calc_kp "" default=false;
67 phi = (2. * P_K_Q) * tnom_k * log(nsub/NI);
70 error(((!_sim->is_first_expand()) ? (bDEBUG) : (bWARNING)),
71 long_label() + ": calculated phi too small, using .1\n");
77 gamma = sqrt(2. * P_EPS_SI * P_Q * nsub) / cox;
81 double phi_ms = (tpg == gtMETAL)
82 ? polarity * (-.05 - (egap + polarity * phi) / 2.)
83 : -(tpg * egap + phi) / 2.;
84 double vfb = phi_ms - polarity * P_Q * nss / cox;
85 vto = vfb + phi + gamma * sqrt(phi);
89 // tox is input, nsub isn't
94 temperature_dependent {
95 calculated_parameters {
96 double phi "" calculate="m->phi*tempratio + (-2*vt*(1.5*log(tempratio)+P_Q*(arg)))";
97 double beta "" calculate="(m->kp / tempratio4) * s->w_eff / s->l_eff";
98 double sqrt_phi "" calculate="sqrt(phi)";
99 double egap "" calculate="egap_";
102 double temp = d->_sim->_temp_c + P_CELSIUS0;
103 double tempratio = temp / m->tnom_k;
104 double tempratio4 = tempratio * sqrt(tempratio);
105 double kt = temp * P_K;
106 double vt = temp * P_K_Q;
107 double egap_ = 1.16 - (7.02e-4*temp*temp) / (temp+1108.);
108 double arg = (m->egap*tempratio - egap_) / (2*kt);
111 /*-----------------------------------------------------------------------*/
113 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
114 trace0(d->long_label().c_str());
115 trace3("", d->vds, d->vgs, d->vbs);
116 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
117 d->reverse_if_needed();
118 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
119 double sarg, dsarg_dvbs;
122 sarg = sqrt(t->phi - d->vbs);
123 dsarg_dvbs = -.5 / sarg;
125 trace2("sb-ok", sarg, dsarg_dvbs);
128 sarg = t->sqrt_phi / (1. + .5 * d->vbs / t->phi);
129 dsarg_dvbs = -.5 * sarg * sarg / t->phi*t->sqrt_phi; /* is wrong!! */
131 trace2("***sb-reversed***", sarg, dsarg_dvbs);
134 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
135 d->von = m->vto + m->gamma * (sarg - sqrt(m->phi))
136 + .5 * (m->egap - t->egap) + .5 * (t->phi - m->phi);
137 d->vgst = d->vdsat = d->vgs - d->von;
141 d->cutoff = (d->vgst < 0.);
142 d->saturated = (d->vds > d->vdsat);
143 trace3("", d->von, d->vgst, d->vdsat);
144 double Lambda = (m->lambda != NA) ? m->lambda : 0.;
145 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
147 d->gds = d->gmf = d->ids = d->gmbf = 0.;
148 trace4("cut", d->ids, d->gmf, d->gds, d->gmbf);
149 }else if (d->saturated) {
150 d->gmf = t->beta * d->vgst * (1. + Lambda * d->vds);
151 d->ids = d->gmf * (.5 * d->vgst);
152 d->gds = .5 * t->beta * Lambda * d->vgst * d->vgst;
153 d->gmbf = - d->gmf * m->gamma * dsarg_dvbs;
154 trace4("sat", d->ids, d->gmf, d->gds, d->gmbf);
156 d->gmf = t->beta * d->vds * (1. + Lambda * d->vds);
157 d->ids = d->gmf * (d->vgst - .5*d->vds);
158 d->gds = t->beta * ((d->vgst - d->vds)
159 + Lambda * d->vds * (2.*d->vgst - 1.5*d->vds));
160 d->gmbf = -d->gmf * m->gamma * dsarg_dvbs;
161 trace4("lin", d->ids, d->gmf, d->gds, d->gmbf);
167 d->gmf = d->gmbf = 0;
169 d->gmr = d->gmbr = 0.;
173 /*--------------------------------------------------------------------------*/
174 /*--------------------------------------------------------------------------*/