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