summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/analog/nld_mosfet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/analog/nld_mosfet.cpp')
-rw-r--r--src/lib/netlist/analog/nld_mosfet.cpp114
1 files changed, 60 insertions, 54 deletions
diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp
index a07233deb2d..1e976933224 100644
--- a/src/lib/netlist/analog/nld_mosfet.cpp
+++ b/src/lib/netlist/analog/nld_mosfet.cpp
@@ -1,22 +1,28 @@
// license:BSD-3-Clause
// copyright-holders:Couriersud
+// Names
+// spell-checker: words Farid, Naim, Jahn, Margraf, Habchi, Raimund, Qucs
//
-// nld_mosfet.cpp
-//
-// Formulas in here based on the following Sources:
-//
-// https://www.imperial.ac.uk/pls/portallive/docs/1/7292573.PDF
-// http://www3.imperial.ac.uk/pls/portallive/docs/1/56133736.PDF
-// https://people.rit.edu/lffeee/SPICE_MOSFET_Model_Intro.pdf
-// https://people.rit.edu/lffeee/SPICE.pdf
-// http://web.mit.edu/course/6/6.012/SPR98/www/lectures/S98_Lecture10.pdf
-// http://homepages.rpi.edu/~sawyes/Models_review.pdf
-// http://jaco.ec.t.kanazawa-u.ac.jp/edu/mix/pdf/3.pdf
-//
-// Farid N. Naim, Circuit Simulation (Wiley-IEEE Press, 2010).
-// Stefan Jahn, Michael Margraf, Vincent Habchi and Raimund Jacob, "Qucs Technical Papers" (2007)
-//
+// Specific technical terms
+// spell-checker: words Cgso, Cgdo, Cgbo, Cjsw, Mjsw, Ucrit, Uexp, Utra, Neff, Tnom, capval, Udsat, Utst
+
+///
+/// \file nld_mosfet.cpp
+///
+/// Formulas in here based on the following Sources:
+///
+/// https:///www.imperial.ac.uk/pls/portallive/docs/1/7292573.PDF
+/// http://www3.imperial.ac.uk/pls/portallive/docs/1/56133736.PDF
+/// https://people.rit.edu/lffeee/SPICE_MOSFET_Model_Intro.pdf
+/// https://people.rit.edu/lffeee/SPICE.pdf
+/// http://web.mit.edu/course/6/6.012/SPR98/www/lectures/S98_Lecture10.pdf
+/// http://homepages.rpi.edu/~sawyes/Models_review.pdf
+/// http://jaco.ec.t.kanazawa-u.ac.jp/edu/mix/pdf/3.pdf
+///
+/// Farid N. Naim, Circuit Simulation (Wiley-IEEE Press, 2010).
+/// Stefan Jahn, Michael Margraf, Vincent Habchi and Raimund Jacob, "Qucs Technical Papers" (2007)
+///
#include "solver/nld_solver.h"
#include "../nl_setup.h"
@@ -35,7 +41,7 @@ namespace analog
// nld_FET - Base classes
// -----------------------------------------------------------------------------
- /// \brief Class representing the nmos/pmos model paramers.
+ /// \brief Class representing the nmos/pmos model parameters.
///
/// This is the model representation of the nmos model.
///
@@ -202,10 +208,10 @@ namespace analog
, m_Cgb(nlconst::zero())
, m_Cgs(nlconst::zero())
, m_Cgd(nlconst::zero())
- , m_capmod(2)
+ , m_capacitor_model(2)
, m_Vgs(*this, "m_Vgs", nlconst::zero())
, m_Vgd(*this, "m_Vgd", nlconst::zero())
- , m_modacc(m_model)
+ , m_model_acc(m_model)
{
register_subalias("S", m_SG.P()); // Source
register_subalias("G", m_SG.N()); // Gate
@@ -219,9 +225,9 @@ namespace analog
set_qtype((m_model.type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS);
m_polarity = (qtype() == FET_NMOS ? nlconst::one() : -nlconst::one());
- m_capmod = m_modacc.m_CAPMOD;
- // printf("capmod %d %g %g\n", m_capmod, (nl_fptype)m_modacc.m_VTO, m_polarity);
- nl_assert_always(m_capmod == 0 || m_capmod == 2, "Error: CAPMODEL invalid value");
+ m_capacitor_model = m_model_acc.m_CAPMOD;
+ //# printf("capmod %d %g %g\n", m_capacitor_model, (nl_fptype)m_model_acc.m_VTO, m_polarity);
+ nl_assert_always(m_capacitor_model == 0 || m_capacitor_model == 2, "Error: CAPMODEL invalid value");
//
// From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm :
@@ -233,51 +239,51 @@ namespace analog
// But couldn't find a formula for lambda anywhere
//
- m_lambda = m_modacc.m_LAMBDA; // FIXME: m_lambda only set once
+ m_lambda = m_model_acc.m_LAMBDA; // FIXME: m_lambda only set once
// calculate effective channel length
- m_Leff = m_modacc.m_L - 2 * m_modacc.m_LD;
+ m_Leff = m_model_acc.m_L - 2 * m_model_acc.m_LD;
nl_assert_always(m_Leff > nlconst::zero(), "Effective Lateral diffusion would be negative for model");
- nl_fptype Cox = (m_modacc.m_TOX > nlconst::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_modacc.m_TOX) : nlconst::zero();
+ nl_fptype Cox = (m_model_acc.m_TOX > nlconst::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model_acc.m_TOX) : nlconst::zero();
// calculate DC transconductance coefficient
- if (m_modacc.m_KP > nlconst::zero())
- m_beta = m_modacc.m_KP * m_modacc.m_W / m_Leff;
- else if (Cox > nlconst::zero() && m_modacc.m_UO > nlconst::zero())
- m_beta = m_modacc.m_UO * nlconst::magic(1e-4) * Cox * m_modacc.m_W / m_Leff;
+ if (m_model_acc.m_KP > nlconst::zero())
+ m_beta = m_model_acc.m_KP * m_model_acc.m_W / m_Leff;
+ else if (Cox > nlconst::zero() && m_model_acc.m_UO > nlconst::zero())
+ m_beta = m_model_acc.m_UO * nlconst::magic(1e-4) * Cox * m_model_acc.m_W / m_Leff;
else
- m_beta = nlconst::magic(2e-5) * m_modacc.m_W / m_Leff;
+ m_beta = nlconst::magic(2e-5) * m_model_acc.m_W / m_Leff;
//FIXME::UT can disappear
const nl_fptype Vt = constants::T0() * constants::k_b() / constants::Q_e();
// calculate surface potential if not given
- if (m_modacc.m_PHI > nlconst::zero())
- m_phi = m_modacc.m_PHI;
- else if (m_modacc.m_NSUB > nlconst::zero())
+ if (m_model_acc.m_PHI > nlconst::zero())
+ m_phi = m_model_acc.m_PHI;
+ else if (m_model_acc.m_NSUB > nlconst::zero())
{
- nl_assert_always(m_modacc.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model");
- m_phi = nlconst::two() * Vt * plib::log (m_modacc.m_NSUB * nlconst::magic(1e6) / constants::NiSi());
+ nl_assert_always(m_model_acc.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model");
+ m_phi = nlconst::two() * Vt * plib::log (m_model_acc.m_NSUB * nlconst::magic(1e6) / constants::NiSi());
}
else
m_phi = nlconst::magic(0.6);
// calculate bulk threshold if not given
- if (m_modacc.m_GAMMA > nlconst::zero())
- m_gamma = m_modacc.m_GAMMA;
+ if (m_model_acc.m_GAMMA > nlconst::zero())
+ m_gamma = m_model_acc.m_GAMMA;
else
{
- if (Cox > nlconst::zero() && m_modacc.m_NSUB > nlconst::zero())
+ if (Cox > nlconst::zero() && m_model_acc.m_NSUB > nlconst::zero())
m_gamma = plib::sqrt (nlconst::two()
* constants::Q_e() * constants::eps_Si() * constants::eps_0()
- * m_modacc.m_NSUB * nlconst::magic(1e6)) / Cox;
+ * m_model_acc.m_NSUB * nlconst::magic(1e6)) / Cox;
else
m_gamma = nlconst::zero();
}
- m_vto = m_modacc.m_VTO;
+ m_vto = m_model_acc.m_VTO;
// FIXME zero conversion
if(m_vto == nlconst::zero())
log().warning(MW_MOSFET_THRESHOLD_VOLTAGE(m_model.name()));
@@ -285,21 +291,21 @@ namespace analog
// FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models
// specify VTO so skip this here.
- m_CoxWL = Cox * m_modacc.m_W * m_Leff;
+ m_CoxWL = Cox * m_model_acc.m_W * m_Leff;
- //printf("Cox: %g\n", m_Cox);
+ //#printf("Cox: %g\n", m_Cox);
}
- NETLIB_IS_TIMESTEP(true || m_capmod != 0)
+ NETLIB_IS_TIMESTEP(true || m_capacitor_model != 0)
NETLIB_TIMESTEPI()
{
- if (m_capmod != 0)
+ if (m_capacitor_model != 0)
{
if (ts_type == timestep_type::FORWARD)
{
- //const nl_nl_fptype Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain
- //const nl_nl_fptype Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source
+ //#const nl_nl_fptype Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain
+ //#const nl_nl_fptype Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source
const nl_fptype Ugd = m_Vgd; // Gate - Drain
const nl_fptype Ugs = m_Vgs; // Gate - Source
const nl_fptype Ubs = nlconst::zero(); // Bulk - Source == 0 if connected
@@ -325,9 +331,9 @@ namespace analog
NETLIB_NAME(FET)::reset();
// Bulk diodes
- m_D_BD.set_param(m_modacc.m_ISD, m_modacc.m_N, exec().gmin(), constants::T0());
+ m_D_BD.set_param(m_model_acc.m_ISD, m_model_acc.m_N, exec().gmin(), constants::T0());
#if (!BODY_CONNECTED_TO_SOURCE)
- m_D_BS.set_param(m_modacc.m_ISS, m_modacc.m_N, exec().gmin(), constants::T0());
+ m_D_BS.set_param(m_model_acc.m_ISS, m_model_acc.m_N, exec().gmin(), constants::T0());
#endif
}
@@ -375,10 +381,10 @@ namespace analog
nl_fptype m_Cgs;
nl_fptype m_Cgd;
- int m_capmod;
+ int m_capacitor_model;
state_var<nl_fptype> m_Vgs;
state_var<nl_fptype> m_Vgd;
- fet_model_t m_modacc;
+ fet_model_t m_model_acc;
void set_cap(generic_capacitor<capacitor_e::VARIABLE_CAPACITY> &cap,
nl_fptype capval, nl_fptype V,
@@ -515,7 +521,7 @@ namespace analog
gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / nlconst::two());
}
- // backgate transconductance
+ // back gate transconductance
const nl_fptype bgtc = (phi_m_Vbulk != nlconst::zero()) ? (m_gamma / phi_m_Vbulk / nlconst::two()) : nlconst::zero();
gmb = gm * bgtc;
}
@@ -570,7 +576,7 @@ namespace analog
const nl_fptype gBS = -gbs;
nl_fptype gBB = gbs + gbd;
- if (m_capmod != 0)
+ if (m_capacitor_model != 0)
{
const nl_fptype Vgb = Vgs - Vbs;
@@ -579,9 +585,9 @@ namespace analog
else
calculate_caps(Vgd, Vgs, Vth, m_Cgd, m_Cgs, m_Cgb);
- set_cap(m_cap_gb, m_Cgb + m_modacc.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB);
- set_cap(m_cap_gs, m_Cgs + m_modacc.m_CGSO * m_modacc.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS);
- set_cap(m_cap_gd, m_Cgd + m_modacc.m_CGDO * m_modacc.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID);
+ set_cap(m_cap_gb, m_Cgb + m_model_acc.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB);
+ set_cap(m_cap_gs, m_Cgs + m_model_acc.m_CGSO * m_model_acc.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS);
+ set_cap(m_cap_gd, m_Cgd + m_model_acc.m_CGDO * m_model_acc.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID);
}
// Source connected to body, Diode S-B shorted!