File indexing completed on 2024-04-28 05:43:16

0001 /***************************************************************************
0002  *   Copyright (C) 2005 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #include "mosfet.h"
0012 
0013 #include <cmath>
0014 using namespace std;
0015 
0016 // BEGIN class MOSFETSettings
0017 MOSFETSettings::MOSFETSettings()
0018 {
0019     I_S = 1e-14;
0020     N = 1.0;
0021     K_P = 2e-5;
0022     L = 1e-4;
0023     W = 1e-4;
0024 
0025 #if 0
0026     phi = 0.6;
0027     T_OX = 1e-7;
0028     P_b = 0.8;
0029     M_J = 0.5;
0030     F_C = 0.5;
0031     M_JSW = 0.33;
0032     U_0 = 600.0;
0033     N_RD = 1;
0034     N_RS = 1;
0035 #endif
0036 }
0037 // END class MOSFETSettings
0038 
0039 // BEGIN class MOSFETState
0040 MOSFETState::MOSFETState()
0041 {
0042     reset();
0043 }
0044 
0045 void MOSFETState::reset()
0046 {
0047     for (unsigned i = 0; i < 4; ++i) {
0048         for (unsigned j = 0; j < 4; ++j)
0049             A[i][j] = 0.0;
0050 
0051         I[i] = 0.0;
0052     }
0053 }
0054 
0055 MOSFETState MOSFETState::operator-(const MOSFETState &s) const
0056 {
0057     MOSFETState newState(*this);
0058 
0059     for (unsigned i = 0; i < 4; ++i) {
0060         for (unsigned j = 0; j < 4; ++j)
0061             newState.A[i][j] -= s.A[i][j];
0062 
0063         newState.I[i] -= s.I[i];
0064     }
0065 
0066     return newState;
0067 }
0068 // END class MOSFETState
0069 
0070 // BEGIN class MOSFET
0071 const uint MOSFET::PinD = 0;
0072 const uint MOSFET::PinG = 1;
0073 const uint MOSFET::PinS = 2;
0074 const uint MOSFET::PinB = 3;
0075 
0076 MOSFET::MOSFET(MOSFET_type type)
0077 {
0078     m_pol = 10;
0079     switch (type) {
0080     case neMOSFET:
0081         //      case ndMOSFET:
0082         m_pol = 1;
0083         break;
0084 
0085     case peMOSFET:
0086         //      case pdMOSFET:
0087         m_pol = -1;
0088         break;
0089     }
0090 
0091     V_GS_prev = V_GD_prev = V_BD_prev = V_DS_prev = V_BS_prev = 0.0;
0092     m_numCNodes = 4;
0093     updateLim();
0094 }
0095 
0096 MOSFET::~MOSFET()
0097 {
0098 }
0099 
0100 void MOSFET::add_initial_dc()
0101 {
0102     V_GS_prev = V_GD_prev = V_BD_prev = V_DS_prev = V_BS_prev = 0.0;
0103     m_os.reset();
0104     update_dc();
0105 }
0106 
0107 void MOSFET::updateCurrents()
0108 {
0109     if (!b_status)
0110         return;
0111 
0112     double V_D = p_cnode[PinD]->v;
0113     double V_G = p_cnode[PinG]->v;
0114     double V_S = p_cnode[PinS]->v;
0115     double V_B = p_cnode[PinB]->v;
0116 
0117     double V_GD = (V_G - V_D) * m_pol;
0118     double V_GS = (V_G - V_S) * m_pol;
0119     double V_BS = (V_B - V_S) * m_pol;
0120     double V_BD = (V_B - V_D) * m_pol;
0121     double V_DS = (V_D - V_S) * m_pol;
0122 
0123     double I_BS, I_BD, I_DS, g_BS, g_BD, g_DS, g_M;
0124     calcIg(V_BS, V_BD, V_DS, V_GS, V_GD, &I_BS, &I_BD, &I_DS, &g_BS, &g_BD, &g_DS, &g_M);
0125 
0126     m_cnodeI[PinD] = -I_DS + I_BD;
0127     m_cnodeI[PinB] = -I_BD - I_BS;
0128     m_cnodeI[PinS] = +I_DS + I_BS;
0129 }
0130 
0131 void MOSFET::update_dc()
0132 {
0133     if (!b_status)
0134         return;
0135 
0136     calc_eq();
0137 
0138     MOSFETState diff = m_ns - m_os;
0139     for (unsigned i = 0; i < 4; ++i) {
0140         for (unsigned j = 0; j < 4; ++j)
0141             A_g(i, j) += diff.A[i][j];
0142 
0143         b_i(i) += diff.I[i];
0144     }
0145 
0146     m_os = m_ns;
0147 }
0148 
0149 void MOSFET::calc_eq()
0150 {
0151     double N = m_mosfetSettings.N;
0152 
0153     double V_D = p_cnode[PinD]->v;
0154     double V_G = p_cnode[PinG]->v;
0155     double V_S = p_cnode[PinS]->v;
0156     double V_B = p_cnode[PinB]->v;
0157 
0158     double V_GD = (V_G - V_D) * m_pol;
0159     double V_GS = (V_G - V_S) * m_pol;
0160     double V_BS = (V_B - V_S) * m_pol;
0161     double V_BD = (V_B - V_D) * m_pol;
0162     double V_DS = (V_D - V_S) * m_pol;
0163 
0164     // help convergence
0165     if (V_DS >= 0) {
0166         V_GS = fetVoltage(V_GS, V_GS_prev, m_pol);
0167 
0168         // recalculate V_DS, same for other similar lines
0169         V_DS = V_GS - V_GD;
0170 
0171         V_DS = fetVoltageDS(V_DS, V_DS_prev);
0172         V_GD = V_GS - V_DS;
0173 
0174         V_BS = diodeVoltage(V_BS, V_BS_prev, N, V_lim);
0175         V_BD = V_BS - V_DS;
0176     } else {
0177         V_GD = fetVoltage(V_GD, V_GD_prev, m_pol);
0178         V_DS = V_GS - V_GD;
0179 
0180         V_DS = -fetVoltageDS(-V_DS, -V_DS_prev);
0181         V_GS = V_GD + V_DS;
0182 
0183         V_BD = diodeVoltage(V_BD, V_BD_prev, N, V_lim);
0184         V_BS = V_BD + V_DS;
0185     }
0186 
0187     V_GS_prev = V_GS;
0188     V_GD_prev = V_GD;
0189     V_BD_prev = V_BD;
0190     V_DS_prev = V_DS;
0191     V_BS_prev = V_BS;
0192 
0193     double I_BS, I_BD, I_DS, g_BS, g_BD, g_DS, g_M;
0194     calcIg(V_BS, V_BD, V_DS, V_GS, V_GD, &I_BS, &I_BD, &I_DS, &g_BS, &g_BD, &g_DS, &g_M);
0195 
0196     double I_BD_eq = I_BD - g_BD * V_BD;
0197     double I_BS_eq = I_BS - g_BS * V_BS;
0198 
0199     double sc = (V_DS >= 0) ? g_M : 0;
0200     double dc = (V_DS < 0) ? g_M : 0;
0201     double I_DS_eq = I_DS - (g_DS * V_DS) - (g_M * ((V_DS >= 0) ? V_GS : V_GD));
0202 
0203     m_ns.A[PinG][PinG] = 0;
0204     m_ns.A[PinG][PinD] = 0;
0205     m_ns.A[PinG][PinS] = 0;
0206     m_ns.A[PinG][PinB] = 0;
0207 
0208     m_ns.A[PinD][PinG] = g_M;
0209     m_ns.A[PinD][PinD] = g_DS + g_BD - dc;
0210     m_ns.A[PinD][PinS] = -g_DS - sc;
0211     m_ns.A[PinD][PinB] = -g_BD;
0212 
0213     m_ns.A[PinS][PinG] = -g_M;
0214     m_ns.A[PinS][PinD] = -g_DS + dc;
0215     m_ns.A[PinS][PinS] = g_BS + g_DS + sc;
0216     m_ns.A[PinS][PinB] = -g_BS;
0217 
0218     m_ns.A[PinB][PinG] = 0;
0219     m_ns.A[PinB][PinD] = -g_BD;
0220     m_ns.A[PinB][PinS] = -g_BS;
0221     m_ns.A[PinB][PinB] = g_BS + g_BD;
0222 
0223     m_ns.I[PinG] = 0;
0224     m_ns.I[PinD] = (+I_BD_eq - I_DS_eq) * m_pol;
0225     m_ns.I[PinS] = (+I_BS_eq + I_DS_eq) * m_pol;
0226     m_ns.I[PinB] = (-I_BD_eq - I_BS_eq) * m_pol;
0227 }
0228 
0229 void MOSFET::calcIg(double V_BS, double V_BD, double V_DS, double V_GS, double V_GD, double *I_BS, double *I_BD, double *I_DS, double *g_BS, double *g_BD, double *g_DS, double *g_M) const
0230 {
0231     double I_S = m_mosfetSettings.I_S;
0232     double N = m_mosfetSettings.N;
0233     double beta = m_mosfetSettings.beta();
0234 
0235     // BD and BS diodes
0236     mosDiodeJunction(V_BS, I_S, N, I_BS, g_BS);
0237     mosDiodeJunction(V_BD, I_S, N, I_BD, g_BD);
0238 
0239     // bias-dependent threshold voltage
0240     double V_tst = ((V_DS >= 0) ? V_GS : V_GD) - m_pol;
0241 
0242     *g_DS = 0;
0243     *I_DS = 0;
0244     *g_M = 0;
0245 
0246     if (V_tst > 0) {
0247         double V_DS_abs = std::abs(V_DS);
0248         if (V_tst <= V_DS_abs) {
0249             // saturation region
0250             *g_M = beta * V_tst;
0251             *I_DS = *g_M * V_tst / 2;
0252         } else {
0253             // linear region
0254             *g_M = beta * V_DS_abs;
0255             *I_DS = *g_M * (V_tst - V_DS_abs / 2);
0256             *g_DS = beta * (V_tst - V_DS_abs);
0257         }
0258     }
0259 
0260     if (V_DS < 0)
0261         *I_DS = -*I_DS;
0262 }
0263 
0264 void MOSFET::setMOSFETSettings(const MOSFETSettings &settings)
0265 {
0266     m_mosfetSettings = settings;
0267     updateLim();
0268     if (p_eSet)
0269         p_eSet->setCacheInvalidated();
0270 }
0271 
0272 void MOSFET::updateLim()
0273 {
0274     double I_S = m_mosfetSettings.I_S;
0275     double N = m_mosfetSettings.N;
0276     V_lim = diodeLimitedVoltage(I_S, N);
0277 }
0278 // END class MOSFET