This package Mos2 contains functions and records with data of the mosfet model level 2.
Extends from Modelica.Icons.Package (Icon for standard packages).
| Name | Description | 
|---|---|
| Record for Mosfet model line parameters (for level 2) | |
| Record for Mosfet model line variables (for level 2) | |
| Further mosfet variables (for level 2) | |
| Initial precalculation | |
| Drain current calculation | |
| Parameter renaming to internal names | |
| Device parameter renaming to internal names | 
This record Mos1ModelLineParams contains the model line parameters that are used for the mosfet transistors level 2 in SPICE3.
Extends from Mos.MosModelLineParams (Record for Mosfet model line parameters (for level 1, 2, 3 and 6)).
| Type | Name | Default | Description | 
|---|---|---|---|
| Initialization | |||
| Real | m_jctSatCurDensity.start | 0.0 | JS, Bulk jct. sat. current density, input - use tSatCurDens | 
| Resistance | m_sheetResistance.start | 0.0 | RSH, Sheet resistance [Ohm] | 
| Real | m_bulkJctPotential.start | 0.8 | PB, Bulk junction potential, input - use tBulkPot | 
| Real | m_bulkJctBotGradingCoeff.start | 0.5 | MJ, Bottom grading coefficient | 
| Real | m_bulkJctSideGradingCoeff.start | 0.33 | MJSW, Side grading coefficient | 
| Real | m_oxideThickness.start | 1.0e-7 | TOX, Oxide thickness unit: micron | 
| Real | m_gateSourceOverlapCapFactor.start | 0.0 | CGS0, Gate-source overlap cap | 
| Real | m_gateDrainOverlapCapFactor.start | 0.0 | CGD0, Gate-drain overlap cap | 
| Real | m_gateBulkOverlapCapFactor.start | 0.0 | CGB0, Gate-bulk overlap cap | 
| Real | m_fNcoef.start | 0.0 | KF, Flicker noise coefficient | 
| Real | m_fNexp.start | 1.0 | AF, Flicker noise exponent | 
| Real | m_oxideCapFactor.start | 0.0 | |
| Voltage | m_vt0.start | 0.0 | VTO, Threshold voltage [V] | 
| Capacitance | m_capBD.start | 0.0 | CBD, B-D junction capacitance [F] | 
| Capacitance | m_capBS.start | 0.0 | CBS, B-S junction capacitance [F] | 
| CapacitancePerArea | m_bulkCapFactor.start | 0.0 | CJ, Bottom junction cap per area [F/m2] | 
| Permittivity | m_sideWallCapFactor.start | 0.0 | CJSW, Side grading coefficient [F/m] | 
| Real | m_fwdCapDepCoeff.start | 0.5 | FC, Forward bias jct. fit parm. | 
| Voltage | m_phi.start | 0.6 | PHI, Surface potential [V] | 
| Voltage | m_gamma.start | 0.0 | GAMMA, Bulk threshold parameter [V] | 
| InversePotential | m_lambda.start | 0.0 | Channel-length modulation [1/V] | 
| Real | m_substrateDoping.start | 0.0 | NSUB, Substrate doping | 
| Real | m_gateType.start | 1.0 | TPG, Gate type | 
| PerArea_cm | m_surfaceStateDensity.start | 0.0 | NSS, Gate type [1/cm2] | 
| Area_cmPerVoltageSecond | m_surfaceMobility.start | 600.0 | UO, Surface mobility [cm2/(V.s)] | 
| Length | m_latDiff.start | 0.0 | LD, Lateral diffusion [m] | 
| Current | m_jctSatCur.start | 1.0e-14 | IS, Bulk junction sat. current [A] | 
| Resistance | m_drainResistance.start | 0 | RD, Drain ohmic resistance [Ohm] | 
| Resistance | m_sourceResistance.start | 0 | RS, Source ohmic resistance [Ohm] | 
| Transconductance | m_transconductance.start | 2.0e-5 | input - use tTransconductance [A/V2] | 
record Mos2ModelLineParams 
  "Record for Mosfet model line parameters (for level 2)"
  extends Mos.MosModelLineParams(
    m_lambda(start=0.0),
    m_transconductance(start=2.0e-5),
    m_bulkJctSideGradingCoeff(start=0.33),
    m_oxideThickness(start=1.0e-7));
  Real m_narrowFactor( start = 0.0) "DELTA, Width effect on threshold";
  Real m_critFieldExp( start = 0.0) "UEXP, Crit. field exp for mob. deg";
  Real m_critField( start = 1.0e4) "UCRIT, Crit. field for mob. degradation";
  Real m_maxDriftVel( start = 0.0) "VMAX, Maximum carrier drift velocity";
  Real m_junctionDepth( start = 0.0) "XJ, Junction depth";
  Modelica.SIunits.Charge m_channelCharge( start = 1.0) 
    "NEFF, Total channel charge coeff";
  Real m_fastSurfaceStateDensity( start = 0.0) 
    "NFS, Fast surface state density";
end Mos2ModelLineParams;
 
This record MosModelLineVariables contains the model line variables that are used for the mosfet transistors level 2 SPICE3.
Extends from Mos.MosModelLineVariables (Record for Mosfet model line variables (for level 1)).
record Mos2ModelLineVariables "Record for Mosfet model line variables (for level 2)" extends Mos.MosModelLineVariables; Real m_bulkCapFactor; Real m_substrateDoping; Real m_xd;end Mos2ModelLineVariables; 
This record Mos1Calc contains further mosfet variables (for level 2) that are needed for the calculations.
Extends from Mos.MosCalc (Further mosfet variables (for level 1, 2, 3 and 6)).
| Type | Name | Default | Description | 
|---|---|---|---|
| Initialization | |||
| Integer | m_mode.start | 1 | Mode | 
| Transconductance | m_tTransconductance.start | 0. | [A/V2] | 
| Real | m_tSurfMob.start | 0. | |
| Voltage | m_tPhi.start | 0.7 | [V] | 
| Voltage | m_tVto.start | 1. | [V] | 
| Real | m_tSatCurDens.start | 0. | |
| Current | m_tDrainSatCur.start | 0. | [A] | 
| Current | m_tSourceSatCur.start | 0. | [A] | 
| Capacitance | m_tCBDb.start | 0. | [F] | 
| Capacitance | m_tCBDs.start | 0. | [F] | 
| Capacitance | m_tCBSb.start | 0. | [F] | 
| Capacitance | m_tCBSs.start | 0. | [F] | 
| Real | m_tCj.start | 0. | |
| Real | m_tCjsw.start | 0. | |
| Voltage | m_tBulkPot.start | 0.7 | [V] | 
| Real | m_tDepCap.start | 0.35 | |
| Voltage | m_tVbi.start | 1. | [V] | 
| Voltage | m_VBScrit.start | 0.7 | [V] | 
| Voltage | m_VBDcrit.start | 0.7 | [V] | 
| Real | m_f1b.start | 0. | |
| Real | m_f2b.start | 0. | |
| Real | m_f3b.start | 0. | |
| Real | m_f1s.start | 0. | |
| Real | m_f2s.start | 0. | |
| Real | m_f3s.start | 0. | |
| Real | m_dVt.start | 0. | |
| Capacitance | m_capgd.start | 0. | [F] | 
| Capacitance | m_capgs.start | 0. | [F] | 
| Capacitance | m_capgb.start | 0. | [F] | 
| Charge | m_qgs.start | 0. | [C] | 
| Charge | m_qgd.start | 0. | [C] | 
| Charge | m_qgb.start | 0. | [C] | 
record Mos2Calc "Further mosfet variables (for level 2)" extends Mos.MosCalc;end Mos2Calc; 
This function mos1ModelLineParamsInitEquation does the initial precalculation of the mosfet model line parameters for level 2.
| Type | Name | Default | Description | 
|---|---|---|---|
| Mos2ModelLineParams | in_p | Input record model line parameters for MOS2 | |
| SpiceConstants | in_C | Spice constants | |
| Integer | in_m_type | Type of MOS transistor | 
| Type | Name | Description | 
|---|---|---|
| Mos2ModelLineVariables | out_v | Output record with model line variables | 
function mos2ModelLineParamsInitEquations "Initial precalculation"
  input Mos2ModelLineParams in_p "Input record model line parameters for MOS2";
  input SpiceConstants in_C "Spice constants";
  input Integer in_m_type "Type of MOS transistor";
  output Mos2ModelLineVariables out_v "Output record with model line variables";
protected 
  Modelica.SIunits.Voltage vtnom;
  Modelica.SIunits.Voltage fermis;
  Real fermig;
  Real wkfng;
  Real wkfngs;
  Real egfet1;
  Real vfb;
algorithm 
  out_v.m_oxideCapFactor   := in_p.m_oxideCapFactor;
  out_v.m_transconductance := in_p.m_transconductance;
  out_v.m_phi              := in_p.m_phi;
  out_v.m_gamma            := in_p.m_gamma;
  out_v.m_vt0              := in_p.m_vt0;
  out_v.m_substrateDoping  := in_p.m_substrateDoping;
  out_v.m_bulkCapFactor    := in_p.m_bulkCapFactor;
  vtnom                  := in_p.m_tnom * in_C.CONSTKoverQ;
  egfet1                 := 1.16 - (7.02e-4 * in_p.m_tnom * in_p.m_tnom) / (in_p.m_tnom + 1108);
  out_v.m_oxideCapFactor := 3.9 * 8.854214871e-12 / in_p.m_oxideThickness;
  if ( not (in_p.m_transconductanceIsGiven > 0.5)) then
    out_v.m_transconductance := in_p.m_surfaceMobility * 1.0e-4 * out_v.m_oxideCapFactor;
  end if;
  if  (in_p.m_substrateDopingIsGiven > 0.5) then
    if ( out_v.m_substrateDoping * 1.0e6 > 1.45e16) then
      if ( not (in_p.m_phiIsGiven > 0.5)) then
        out_v.m_phi := 2 * vtnom * Modelica.Math.log( out_v.m_substrateDoping * 1.0e6 / 1.45e16);
        out_v.m_phi := max( 0.1, out_v.m_phi);
      end if;
      fermis := in_m_type * 0.5 * out_v.m_phi;
      wkfng  := 3.2;
      if ( in_p.m_gateType <> 0) then
        fermig := in_m_type * in_p.m_gateType * 0.5 * egfet1;
        wkfng  := 3.25 + 0.5 * egfet1 - fermig;
      end if;
      wkfngs := wkfng - (3.25 + 0.5 * egfet1 + fermis);
      if ( not (in_p.m_gammaIsGiven > 0.5)) then
        out_v.m_gamma := sqrt(2.0 * 11.70 * 8.854214871e-12 * in_C.CHARGE * out_v.m_substrateDoping
                           * 1.0e6) / out_v.m_oxideCapFactor;
      end if;
      if ( not (in_p.m_vtOIsGiven > 0.5)) then
        vfb         := wkfngs - in_p.m_surfaceStateDensity * 1.0e4 * in_C.CHARGE / out_v.m_oxideCapFactor;
        out_v.m_vt0 := vfb + in_m_type * (out_v.m_gamma * sqrt(out_v.m_phi)+ out_v.m_phi);
      else
        vfb        := out_v.m_vt0 - in_m_type * (out_v.m_gamma * sqrt(out_v.m_phi) + out_v.m_phi);
      end if;
      out_v.m_xd := sqrt( (in_C.EPSSIL + in_C.EPSSIL) / (in_C.CHARGE * out_v.m_substrateDoping * 1.0e6));
    else
      out_v.m_substrateDoping := 0.0;
    end if;
  end if;
  if ( not (in_p.m_bulkCapFactorIsGiven > 0.5)) then
    out_v.m_bulkCapFactor := sqrt( in_C.EPSSIL * in_C.CHARGE * out_v.m_substrateDoping
                              * 1e6 /(2 * in_p.m_bulkJctPotential));
  end if;
end mos2ModelLineParamsInitEquations;
 
This function drainCur calculates the main currents that flows from drain node to source node (level 2).
| Type | Name | Default | Description | 
|---|---|---|---|
| Voltage | vbs | [V] | |
| Voltage | vgs | [V] | |
| Voltage | vds | [V] | |
| Mosfet | in_m | Record mosfet | |
| Mos2Calc | in_c | Input record Mos2Calc | |
| Mos2ModelLineParams | in_p | Input record model line parameters for MOS2 | |
| SpiceConstants | in_C | Spice constants | |
| Mos2ModelLineVariables | in_vp | Input record model line variables | |
| Integer | in_m_type | Type of MOS transistor | 
| Type | Name | Description | 
|---|---|---|
| Mos2Calc | out_c | Output record Mos2Calc | 
function drainCur "Drain current calculation"
   input Modelica.SIunits.Voltage vbs;
   input Modelica.SIunits.Voltage vgs;
   input Modelica.SIunits.Voltage vds;
   input Mosfet.Mosfet in_m "Record mosfet";
   input Mos2Calc in_c "Input record Mos2Calc";
   input Mos2ModelLineParams in_p "Input record model line parameters for MOS2";
   input SpiceConstants in_C "Spice constants";
   input Mos2ModelLineVariables in_vp "Input record model line variables";
   input Integer in_m_type "Type of MOS transistor";
   output Mos2Calc out_c "Output record Mos2Calc";
protected 
  Real vt;      // K * T / Q
  Real beta1;
  Real dsrgdb;
  Real d2sdb2;
  Real sphi = 0.0;
  Real sphi3 = 1.0;    // square root of phi
  Real barg;
  Real sarg;
  Real bsarg = 0.0;
  Real sarg3;
  Real d2bdb2;
  Real factor;
  Real dbrgdb;
  Real eta;
  Real vbin;
  Real vth;
  Real dgddb2;
  Real dgddvb;
  Real dgdvds;
  Real gamasd;
  Real gammad;
  Real xn =   1.0;
  Real argg = 0.0;
  Real vgst;
  Real vgsx;
  Real dgdvbs;
  Real body;
  Real bodys = 0.0;
  Real gdbdv;
  Real dodvbs;
  Real dodvds = 0.0;
  Real dxndvd = 0.0;
  Real dxndvb = 0.0;
  Real dudvgs;
  Real dudvds;
  Real dudvbs;
  Real ufact;
  Real ueff;
  Real dsdvgs;
  Real dsdvbs;
  Real dbsrdb;
  Real gdbdvs = 0.0;
  Real dldvgs;
  Real dldvds;
  Real dldvbs;
  Real clfact;
  Real xleff;
  Real deltal;
  Real xwb;
  Real xld;
  Real xlamda = in_p.m_lambda;
  Real phiMinVbs;
  Real tmp;
  Real argss;
  Real argsd;
  Real args = 0.0;
  Real argd = 0.0;
  Real argxs = 0.0;
  Real argxd = 0.0;
  Real dbargs;
  Real dbargd;
  Real dbxws;
  Real dbxwd;
  Real xwd;
  Real xws;
  Real daddb2;
  Real dasdb2;
  Real ddxwd;
  Real cfs;
  Real cdonco;
  Real argv;
  Real gammd2;
  Real arg;
  Real y3;
  Real xvalid = 0.0;
  Real[4] sig1;
  Real[4] sig2;
  Real[4] a4;
  Real[4] b4;
  Real[8] x4;
  Real[8] poly4;
  Real delta4;
  Integer j;
  Integer iknt = 0;
  Integer i;
  Integer jknt = 0;
  Real v1;
  Real v2;
  Real xv;
  Real a1;
  Real b1;
  Real c1;
  Real d1;
  Real b2;
  Real r1;
  Real s1;
  Real s2;
  Real p1;
  Real p0;
  Real p2;
  Real a3;
  Real b3;
  Real sargv;
  Real dldsat;
  Real xlfact;
  Real xdv;
  Real xlv;
  Real vqchan;
  Real dqdsat;
  Real vl;
  Real dfunds;
  Real dfundg;
  Real dfundb;
  Real xls;
  Real dfact;
  Real vdson;
  Real cdson;
  Real gdson;
  Real didvds;
  Real gmw;
  Real gbson;
  Real expg;
algorithm 
   out_c := in_c;
  vt := in_C.CONSTKoverQ * in_C.REFTEMP;
  phiMinVbs := out_c.m_tPhi - vbs;
  if ( vbs <= 0.0) then
    sarg   := sqrt( phiMinVbs);
    dsrgdb := -0.5 / sarg;
    d2sdb2 := 0.5 * dsrgdb / phiMinVbs;
  else
    sphi   :=sqrt(out_c.m_tPhi);
    sphi3  :=out_c.m_tPhi*sphi;
    sarg   :=sphi/(1.0 + 0.5*vbs/out_c.m_tPhi);
    tmp    :=sarg/sphi3;
    dsrgdb :=-0.5*sarg*tmp;
    d2sdb2 :=-dsrgdb*tmp;
  end if;
  if ( (vds-vbs) >= 0) then
    barg   := sqrt( phiMinVbs + vds);
    dbrgdb := -0.5 / barg;
    d2bdb2 := 0.5 * dbrgdb / (phiMinVbs + vds);
  else
    barg   := sphi / (1.0 + 0.5 * (vbs - vds) / out_c.m_tPhi);
    tmp    := barg / sphi3;
    dbrgdb := -0.5 * barg * tmp;
    d2bdb2 := -dbrgdb * tmp;
  end if;
  factor := 0.125 * in_p.m_narrowFactor * 2.0 * Modelica.Constants.pi*in_C.EPSSIL / out_c.m_capOx * out_c.m_lEff;
  eta    := 1.0 + factor;
  vbin   := out_c.m_tVbi * in_m_type + factor * phiMinVbs;
  if ( (in_vp.m_gamma > 0.0) or (in_vp.m_substrateDoping > 0.0)) then
    xwd := in_vp.m_xd * barg;
    xws := in_vp.m_xd * sarg;
    argss  := 0.0;
    argsd  := 0.0;
    dbargs := 0.0;
    dbargd := 0.0;
    dgdvds := 0.0;
    dgddb2 := 0.0;
    if ( in_p.m_junctionDepth > 0) then
      tmp   := 2.0 / in_p.m_junctionDepth;
      argxs := 1.0 + xws * tmp;
      argxd := 1.0 + xwd * tmp;
      args  := sqrt( argxs);
      argd  := sqrt( argxd);
      tmp   := 0.5 * in_p.m_junctionDepth / out_c.m_lEff;
      argss := tmp * (args - 1.0);
      argsd := tmp * (argd - 1.0);
    end if;
    gamasd := in_vp.m_gamma * (1.0 - argss - argsd);
    dbxwd  := in_vp.m_xd * dbrgdb;
    dbxws  := in_vp.m_xd * dsrgdb;
    if ( in_p.m_junctionDepth > 0) then
      tmp    := 0.5 / out_c.m_lEff;
      dbargs := tmp * dbxws / args;
      dbargd := tmp * dbxwd / argd;
      dasdb2 := -in_vp.m_xd * (d2sdb2 + dsrgdb * dsrgdb * in_vp.m_xd
                / (in_p.m_junctionDepth * argxs)) / (out_c.m_lEff * args);
      daddb2 := -in_vp.m_xd * (d2bdb2 + dbrgdb * dbrgdb * in_vp.m_xd
                / (in_p.m_junctionDepth * argxd))
                / (out_c.m_lEff * argd);
      dgddb2 := -0.5 * in_vp.m_gamma * (dasdb2 + daddb2);
    end if;
    dgddvb := -in_vp.m_gamma * (dbargs + dbargd);
    if ( in_p.m_junctionDepth > 0) then
      ddxwd  := -dbxwd;
      dgdvds := -in_vp.m_gamma * 0.5 * ddxwd / (out_c.m_lEff * argd);
    end if;
  else
    gamasd := in_vp.m_gamma;
    gammad := in_vp.m_gamma;
    dgddvb := 0.0;
    dgdvds := 0.0;
    dgddb2 := 0.0;
  end if;
  out_c.m_von   := vbin + gamasd * sarg;
  vth           := out_c.m_von;
  out_c.m_vdsat := 0.0;
  if ( in_p.m_fastSurfaceStateDensity <> 0.0 and out_c.m_capOx <> 0.0) then
    cfs          := in_C.CHARGE * in_p.m_fastSurfaceStateDensity * 1.0e4;
    cdonco       := -(gamasd * dsrgdb + dgddvb * sarg) + factor;
    xn           := 1.0 + cfs / out_c.m_capOx * in_m.m_width * out_c.m_lEff + cdonco;
    tmp          := vt * xn;
    out_c.m_von  := out_c.m_von + tmp;
    argg         := 1.0 / tmp;
    vgst         := vgs - out_c.m_von;
  else
    vgst := vgs - out_c.m_von;
    if ( vgs <= out_c.m_von) then
      // cutoff region
      out_c.m_gds    := 0.0;
      out_c.m_cdrain := 0.0;
      out_c.m_gm     := 0.0;
      out_c.m_gmbs   := 0.0;
      return;
    end if;
  end if;
  sarg3  := sarg * sarg * sarg;
  gammad := gamasd;
  dgdvbs := dgddvb;
  body   := barg * barg * barg - sarg3;
  gdbdv  := 2.0 * gammad * (barg * barg * dbrgdb - sarg * sarg * dsrgdb);
  dodvbs := -factor + dgdvbs * sarg + gammad * dsrgdb;
  if ( (in_p.m_fastSurfaceStateDensity <> 0.0) and (out_c.m_capOx <> 0.0)) then
    dxndvb := 2.0 * dgdvbs * dsrgdb + gammad * d2sdb2 + dgddb2 * sarg;
    dodvbs := dodvbs + vt * dxndvb;
    dxndvd := dgdvds * dsrgdb;
    dodvds := dgdvds * sarg + vt * dxndvd;
  end if;
  // evaluate effective mobility and its derivatives
  ufact  := 1.0;
  ueff   := in_p.m_surfaceMobility * 1e-4;
  dudvgs := 0.0;
  dudvds := 0.0;
  dudvbs := 0.0;
  if (out_c.m_capOx > 0.0) then
    tmp := in_p.m_critField * in_C.EPSSIL * 100 / in_vp.m_oxideCapFactor;
    if (vgst > tmp) then
      ufact  := exp( in_p.m_critFieldExp * Modelica.Math.log( tmp / vgst));
      ueff   := in_p.m_surfaceMobility * 1.0e-4 * ufact;
      dudvgs := -ufact * in_p.m_critFieldExp / vgst;
      dudvds := 0.0;
      dudvbs := in_p.m_critFieldExp * ufact * dodvbs / vgst;
    end if;
  end if;
  // evaluate saturation voltage and its derivatives according to
  // grove-frohman equation
  vgsx   := vgs;
  gammad := gamasd / eta;
  dgdvbs := dgddvb;
  if (in_p.m_fastSurfaceStateDensity <> 0 and out_c.m_capOx <> 0) then
    vgsx := max( vgs, out_c.m_von);
  end if;
  if (gammad > 0) then
    gammd2 := gammad * gammad;
    argv   := (vgsx - vbin) / eta + phiMinVbs;
    if (argv <= 0.0) then
      out_c.m_vdsat := 0.0;
      dsdvgs        := 0.0;
      dsdvbs        := 0.0;
    else
      arg           := sqrt( 1.0 + 4.0 * argv / gammd2);
      out_c.m_vdsat := (vgsx - vbin) / eta + gammd2 * (1.0 - arg) / 2.0;
      out_c.m_vdsat := max( out_c.m_vdsat, 0.0);
      dsdvgs        := (1.0 - 1.0 / arg) / eta;
      dsdvbs        := (gammad * (1.0 - arg) + 2.0 * argv / (gammad * arg))
                       / eta * dgdvbs + 1.0 / arg + factor * dsdvgs;
    end if;
  else
    out_c.m_vdsat := (vgsx - vbin) / eta;
    out_c.m_vdsat := max( out_c.m_vdsat, 0.0);
    dsdvgs        := 1.0;
    dsdvbs        := 0.0;
  end if;
  if (in_p.m_maxDriftVel > 0) then
    // evaluate saturation voltage and its derivatives
    // according to baum's theory of scattering velocity saturation
    v1 := (vgsx - vbin) / eta + phiMinVbs;
    v2 := phiMinVbs;
    xv := in_p.m_maxDriftVel * out_c.m_lEff / ueff;
    a1 := gammad / 0.75;
    b1 := -2.0 * (v1 + xv);
    c1 := -2.0 * gammad * xv;
    d1 := 2.0 * v1 * (v2 + xv) - v2 * v2 - 4.0 / 3.0 * gammad * sarg3;
    b2 := a1 * c1 - 4.0 * d1;
    r1 := -b1 * b1 / 3.0 + b2;
    s1 := 2.0 * b1 * b1 * (-b1) / 27.0 + b1 * b2 / 3.0 + (-d1) * (a1 * a1 - 4.0 * b1) - c1 * c1;
    s2 := s1 * s1;
    p1 := s2 / 4.0 + r1 * r1 * r1 / 27.0;
    p0 := abs( p1);
    p2 := sqrt( p0);
    sig1[1] :=  1.0;
    sig1[2] := -1.0;
    sig1[3] :=  1.0;
    sig1[4] := -1.0;
    sig2[1] :=  1.0;
    sig2[2] :=  1.0;
    sig2[3] := -1.0;
    sig2[4] := -1.0;
    if (p1 < 0) then
      y3 := 2.0 * exp( Modelica.Math.log( sqrt( s2 / 4.0 + p0)) / 3.0)
            * cos( Modelica.Math.atan( -2.0 * p2 / s1) / 3.0) + b1 / 3.0;
    else
      y3 := exp( Modelica.Math.log( abs( -s1 / 2.0 + p2)) / 3.0)
            + exp( Modelica.Math.log( abs( -s1 / 2.0 - p2)) / 3.0)
            + b1 / 3.0;
    end if;
    a3 := sqrt( a1 * a1 / 4.0 - b1 + y3);
    b3 := sqrt( y3 * y3 / 4.0 - d1);
    for i in 1:4 loop
      a4[i]  := a1/2.0+sig1[i]*a3;
      b4[i]  := y3/2.0+sig2[i]*b3;
      delta4 := a4[i]*a4[i]/4.0-b4[i];
      if (delta4 >= 0) then
        iknt     := iknt+1;
        tmp      := sqrt(delta4);
        x4[iknt] := -a4[i]/2.0+tmp;
        iknt     := iknt+1;
        x4[iknt] := -a4[i]/2.0-tmp;
      end if;
    end for;
    jknt := 0;
    for j in 1:iknt loop
      if (x4[j] > 0) then
        poly4[j] := x4[j]*x4[j]*x4[j]*x4[j]+a1*x4[j]*x4[j]*x4[j];
        poly4[j] := poly4[j]+b1*x4[j]*x4[j]+c1*x4[j]+d1;
        if (abs(poly4[j]) <= 1.0e-6) then
          jknt := jknt+1;
          if (jknt <= 1) then
            xvalid := x4[j];
          end if;
          if (x4[j] <= xvalid) then
            xvalid := x4[j];
          end if;
        end if;
      end if;
    end for;
    if (jknt > 0) then
      out_c.m_vdsat := xvalid * xvalid - phiMinVbs;
    end if;
  end if;
  // evaluate effective channel length and its derivatives
  dldvgs := 0.0;
  dldvds := 0.0;
  dldvbs := 0.0;
  if (vds <> 0.0) then
    gammad :=gamasd;
    if ((vbs - out_c.m_vdsat) <= 0) then
      bsarg  := sqrt(out_c.m_vdsat + phiMinVbs);
      dbsrdb := -0.5 / bsarg;
    else
      bsarg  :=sphi/(1.0 + 0.5*(vbs - out_c.m_vdsat)/out_c.m_tPhi);
      dbsrdb :=-0.5*bsarg*bsarg/sphi3;
    end if;
    bodys  := bsarg * bsarg * bsarg - sarg3;
    gdbdvs := 2.0 * gammad * (bsarg * bsarg * dbsrdb - sarg * sarg * dsrgdb);
    if (in_p.m_maxDriftVel <= 0) then
      if (in_vp.m_substrateDoping <> 0.0 and (xlamda <= 0.0)) then
        argv   := (vds - out_c.m_vdsat) / 4.0;
        sargv  := sqrt(1.0 + argv * argv);
        arg    := sqrt(argv + sargv);
        xlfact := in_vp.m_xd / (out_c.m_lEff * vds);
        xlamda := xlfact * arg;
        dldsat := vds * xlamda / (8.0 * sargv);
        dldvgs := dldsat * dsdvgs;
        dldvds := -xlamda + dldsat;
        dldvbs := dldsat * dsdvbs;
      end if;
    else
      argv   := (vgsx - vbin) / eta - out_c.m_vdsat;
      xdv    := in_vp.m_xd / sqrt(in_p.m_channelCharge);
      xlv    := in_p.m_maxDriftVel * xdv / (2.0 * ueff);
      vqchan := argv - gammad * bsarg;
      dqdsat := -1.0 + gammad * dbsrdb;
      vl     := in_p.m_maxDriftVel *out_c. m_lEff;
      dfunds := vl * dqdsat - ueff * vqchan;
      dfundg := (vl - ueff * out_c.m_vdsat) / eta;
      dfundb := -vl * (1.0 + dqdsat - factor / eta) + ueff *
         (gdbdvs - dgdvbs * bodys / 1.5) / eta;
      dsdvgs := -dfundg / dfunds;
      dsdvbs := -dfundb / dfunds;
      if ((in_vp.m_substrateDoping <> 0.0) and (xlamda <= 0.0)) then
        argv   := vds - out_c.m_vdsat;
        argv   := max(argv,0.0);
        xls    := sqrt(xlv * xlv + argv);
        dldsat := xdv / (2.0 * xls);
        xlfact := xdv / (out_c.m_lEff * vds);
        xlamda := xlfact * (xls - xlv);
        dldsat := dldsat / out_c.m_lEff;
        dldvgs := dldsat * dsdvgs;
        dldvds := -xlamda + dldsat;
        dldvbs := dldsat * dsdvbs;
      end if;
    end if;
  end if;
  // limit channel shortening at punch-through
  xwb    :=in_vp.m_xd*sqrt(out_c.m_tBulkPot);
  xld    :=out_c.m_lEff - xwb;
  clfact :=1.0 - xlamda*vds;
  dldvds :=-xlamda - dldvds;
  xleff  :=out_c.m_lEff*clfact;
  deltal :=xlamda*vds*out_c.m_lEff;
  if (in_vp.m_substrateDoping == 0.0) then
    xwb := 0.25e-6;
  end if;
  if (xleff < xwb) then
    xleff  := xwb / (1.0 + (deltal - xld) / xwb);
    clfact := xleff / out_c.m_lEff;
    dfact  := xleff * xleff / (xwb * xwb);
    dldvgs := dfact * dldvgs;
    dldvds := dfact * dldvds;
    dldvbs := dfact * dldvbs;
  end if;
  // evaluate effective beta (effective kp)
  beta1 := out_c.m_Beta * ufact / clfact;
  // test for mode of operation and branch appropriately
  gammad := gamasd;
  dgdvbs := dgddvb;
  if (vds <= 1.0e-10) then
    if (vgs <= out_c.m_von) then
      if ((in_p.m_fastSurfaceStateDensity == 0.0) or (out_c.m_capOx == 0.0)) then
        out_c.m_gds := 0.0;
      else
        out_c.m_gds := beta1 * (out_c.m_von - vbin - gammad * sarg) * exp(argg * (vgs - out_c.m_von));
      end if;
    else
      out_c.m_gds :=beta1*(vgs - vbin - gammad*sarg);
    end if;
    out_c.m_cdrain :=0.0;
    out_c.m_gm     :=0.0;
    out_c.m_gmbs   :=0.0;
    return;
  end if;
  if (vgs <= out_c.m_von) then
    // subthreshold region
    if (out_c.m_vdsat <= 0) then
      out_c.m_gds    := 0.0;
      if (vgs > vth) then
        return;
      end if;
      out_c.m_cdrain := 0.0;
      out_c.m_gm     := 0.0;
      out_c.m_gmbs   := 0.0;
      return;
    end if;
    vdson := min(out_c.m_vdsat, vds);
    if (vds > out_c.m_vdsat) then
      barg   := bsarg;
      dbrgdb := dbsrdb;
      body   := bodys;
      gdbdv  := gdbdvs;
    end if;
    cdson  := beta1 * ((out_c.m_von - vbin - eta * vdson * 0.5) * vdson - gammad * body / 1.5);
    didvds := beta1 * (out_c.m_von - vbin - eta * vdson - gammad * barg);
    gdson  := -cdson * dldvds / clfact - beta1 * dgdvds * body / 1.5;
    if (vds < out_c.m_vdsat) then
      gdson := gdson + didvds;
    end if;
    gbson := -cdson * dldvbs / clfact + beta1 *
             (dodvbs * vdson + factor * vdson - dgdvbs * body / 1.5 - gdbdv);
    if (vds > out_c.m_vdsat) then
      gbson := gbson + didvds * dsdvbs;
    end if;
    expg           := exp(argg * (vgs - out_c.m_von));
    out_c.m_cdrain := cdson * expg;
    gmw            := out_c.m_cdrain * argg;
    out_c.m_gm     := gmw;
    if (vds > out_c.m_vdsat) then
      out_c.m_gm := gmw + didvds * dsdvgs * expg;
    end if;
    tmp          := gmw * (vgs - out_c.m_von) / xn;
    out_c.m_gds  := gdson * expg - out_c.m_gm * dodvds - tmp * dxndvd;
    out_c.m_gmbs := gbson * expg - out_c.m_gm * dodvbs - tmp * dxndvb;
  elseif (vds <= out_c.m_vdsat) then
    // linear region
    out_c.m_cdrain := beta1 * ((vgs - vbin - eta * vds / 2.0) * vds - gammad * body / 1.5);
    arg            := out_c.m_cdrain * (dudvgs / ufact - dldvgs / clfact);
    out_c.m_gm     := arg + beta1 * vds;
    arg            := out_c.m_cdrain * (dudvds / ufact - dldvds / clfact);
    out_c.m_gds    := arg + beta1 * (vgs - vbin - eta *
                      vds - gammad * barg - dgdvds * body / 1.5);
    arg            := out_c.m_cdrain * (dudvbs / ufact - dldvbs / clfact);
    out_c.m_gmbs   := arg - beta1 * (gdbdv + dgdvbs * body / 1.5 - factor * vds);
  else
    // saturation region
    out_c.m_cdrain := beta1 * ((vgs - vbin - eta *
                     out_c.m_vdsat / 2.0) * out_c.m_vdsat - gammad * bodys / 1.5);
    arg            := out_c.m_cdrain * (dudvgs / ufact - dldvgs / clfact);
    out_c.m_gm     := arg + beta1 * out_c.m_vdsat
                     + beta1 * (vgs - vbin - eta * out_c.m_vdsat - gammad * bsarg) * dsdvgs;
    out_c.m_gds    := -out_c.m_cdrain * dldvds / clfact - beta1 * dgdvds * bodys / 1.5;
    arg            := out_c.m_cdrain * (dudvbs / ufact - dldvbs / clfact);
    out_c.m_gmbs   := arg - beta1 * (gdbdvs + dgdvbs * bodys / 1.5 - factor * out_c.m_vdsat)
                     + beta1 *  (vgs - vbin - eta * out_c.m_vdsat - gammad * bsarg) * dsdvbs;
  end if;
end drainCur;
 
This function mos2RenameParameters assigns the external (given by the user, e.g., RD) technology parameters to the internal parameters (e.g., m_drainResistance). It also does the analysis of the IsGiven values (level 2).
| Type | Name | Default | Description | 
|---|---|---|---|
| ModelcardMOS2 | ex | Modelcard with technologie parameters | |
| SpiceConstants | con | Spice constants | 
| Type | Name | Description | 
|---|---|---|
| Mos2ModelLineParams | intern | Output record model line parameters | 
function mos2RenameParameters "Parameter renaming to internal names"
  input ModelcardMOS2 ex "Modelcard with technologie parameters";
  input SpiceConstants con "Spice constants";
  output Mos2ModelLineParams intern "Output record model line parameters";
algorithm 
   intern.m_narrowFactor := ex.DELTA;           // DELTA, Width effect on threshold
   intern.m_critFieldExp := ex.UEXP;            // UEXP, Crit. field exp for mob. deg
   intern.m_critField := ex.UCRIT;              // UCRIT, Crit. field for mob. degradation
   intern.m_maxDriftVel := ex.VMAX;             // VMAX, Maximum carrier drift velocity
   intern.m_junctionDepth := ex.XJ;             // XJ, Junction depth
   intern.m_channelCharge := ex.NEFF;           // NEFF, Total channel charge coeff
   intern.m_fastSurfaceStateDensity := ex.NFS;  // NFS, Fast surface state density
   intern.m_oxideCapFactor := 0;
    intern.m_vtOIsGiven := if          (ex.VTO > -1e40) then 1 else 0;
    intern.m_vt0 := if         (ex.VTO > -1e40) then ex.VTO else 0;
    intern.m_capBDIsGiven := if          (ex.CBD > -1e40) then 1 else 0;
    intern.m_capBD := if         (ex.CBD > -1e40) then ex.CBD else 0;
    intern.m_capBSIsGiven := if          (ex.CBS > -1e40) then 1 else 0;
    intern.m_capBS := if         (ex.CBS > -1e40) then ex.CBS else 0;
    intern.m_bulkCapFactor := ex.CJ;           // F/(m*m) zero-bias bulk junction bottom cap. per sq-meter of junction area (default 0)
    intern.m_sideWallCapFactor := ex.CJSW;     // F/m zero-bias junction sidewall cap. per meter of junction perimeter (default 0)
    intern.m_fwdCapDepCoeff := ex.FC;          // coefficient for forward-bias depletion capacitance formula (default 0.5)
    intern.m_phiIsGiven := if          (ex.PHI > -1e40) then 1 else 0;
    intern.m_phi := if         (ex.PHI > -1e40) then ex.PHI else 0.6;
    intern.m_gammaIsGiven := if          (ex.GAMMA > -1e40) then 1 else 0;
    intern.m_gamma := if         (ex.GAMMA > -1e40) then ex.GAMMA else 0;
    intern.m_lambda := ex.LAMBDA;              // 1/V channel-length modulation (default 0)
    intern.m_substrateDopingIsGiven := if          (ex.NSUB > -1e40) then 1 else 0;
    intern.m_substrateDoping := if         (ex.NSUB > -1e40) then ex.NSUB else 0;
    intern.m_gateType := ex.TPG;               // type of gate material: +1 opp. to substrate, -1 same as substrate, 0 Al gate (default 1)
    intern.m_surfaceStateDensity := ex.NSS;    // 1/(cm*cm) surface state density (default 0)
    intern.m_surfaceMobility := ex.UO;         // (cm*cm)/(Vs) surface mobility (default 600)
    intern.m_latDiff := ex.LD;                 // m lateral diffusion (default 0)
    intern.m_jctSatCur := ex.IS;               // A bulk junction saturation current (defaul 1e-14)
    intern.m_drainResistanceIsGiven := if 
                                         (ex.RD > -1e40) then 1 else 0;
    intern.m_drainResistance := if 
                                 (ex.RD > -1e40) then ex.RD else 0;
          intern.m_sourceResistanceIsGiven := if 
                                         (ex.RS > -1e40) then 1 else 0;
    intern.m_sourceResistance := if 
                                 (ex.RS > -1e40) then ex.RS else 0;
    intern.m_transconductanceIsGiven := if          (ex.KP > -1e40) then 1 else 0;
    intern.m_transconductance := if         (ex.KP > -1e40) then ex.KP else 2e-5;
  intern.m_tnom := if (ex.TNOM > -1e40) then ex.TNOM + SpiceConstants.CONSTCtoK else 
    300.15;
   intern.m_jctSatCurDensity := ex.JS;             // A/(m*m) bulk junction saturation current per sq-meter of junction area (default 0)
   intern.m_sheetResistance := ex.RSH;             // Ohm drain and source diffusion sheet resistance (default 0)
   intern.m_bulkJctPotential := ex.PB;             // V bulk junction potential (default 0.8)
   intern.m_bulkJctBotGradingCoeff := ex.MJ;       // bulk junction bottom grading coeff. (default 0.5)
   intern.m_bulkJctSideGradingCoeff := ex.MJSW;    // bulk junction sidewall grading coeff. (default 0.5)
   intern.m_oxideThickness := ex.TOX;              // m oxide thickness (default 1e-7)
   intern.m_oxideThicknessIsGiven := if          (ex.TOX > -1e40) then 1 else 0;
   intern.m_oxideThickness := if         (ex.TOX > -1e40) then ex.TOX else 1e-7;
   intern.m_gateSourceOverlapCapFactor := ex.CGSO; // F/m gate-source overlap capacitance per meter channel width (default 0)
   intern.m_gateDrainOverlapCapFactor := ex.CGDO;  // F/m gate-drain overlap capacitance per meter channel width (default 0)
   intern.m_gateBulkOverlapCapFactor := ex.CGBO;   // F/m gate-bulk overlap capacitance per meter channel width (default 0)
   intern.m_fNcoef := ex.KF;                       // flicker-noise coefficient (default 0)
   intern.m_fNexp := ex.AF;                        // flicker-noise exponent (default 1)
end mos2RenameParameters;
 
This function mos2RenameParameters assigns the external (given by the user) device parameters to the internal parameters. It also does the analysis of the IsGiven values (level 2).
| Type | Name | Default | Description | 
|---|---|---|---|
| ModelcardMOS2 | ex | ||
| Integer | mtype | ||
| Length | W | Width of channel region [m] | |
| Length | L | Length of channel region [m] | |
| Area | AD | Area of drain diffusion [m2] | |
| Area | AS | Area of source diffusion [m2] | |
| Length | PD | Drain perimeter [m] | |
| Length | PS | Source perimeter [m] | |
| Real | NRD | Length of drain squares | |
| Real | NRS | Length of Source squares | |
| Integer | OFF | Optional initial condition: 0 - IC not used, 1 - IC used, not implemented yet | |
| Real | IC | Initial condition values, not implemented yet | |
| Temp_C | TEMP | Temperature [degC] | 
| Type | Name | Description | 
|---|---|---|
| Mosfet | dev | Output record Mosfet | 
function mos2RenameParametersDev 
  "Device parameter renaming to internal names"
  input ModelcardMOS2 ex;
  input Integer mtype;
  input Modelica.SIunits.Length W "Width of channel region";
  input Modelica.SIunits.Length L "Length of channel region";
  input Modelica.SIunits.Area AD "Area of drain diffusion";
  input Modelica.SIunits.Area AS "Area of source diffusion";
  input Modelica.SIunits.Length PD "Drain perimeter";
  input Modelica.SIunits.Length PS "Source perimeter";
  input Real NRD "Length of drain squares";
  input Real NRS "Length of Source squares";
  input Integer OFF 
    "Optional initial condition: 0 - IC not used, 1 - IC used, not implemented yet";
  input Real IC "Initial condition values, not implemented yet";
  input Modelica.SIunits.Temp_C TEMP "Temperature";
  output Mosfet.Mosfet dev "Output record Mosfet";
algorithm 
/*device parameters*/
  dev.m_len := L;               // L, length of channel region
  dev.m_width := W;             // W, width of channel region
  dev.m_drainArea := AD;        // AD, area of drain diffusion
  dev.m_sourceArea := AS;       // AS, area of source diffusion
  dev.m_drainSquares := NRD;    // NRD, length of drain in squares
  dev.m_sourceSquares := NRS;   // NRS, length of source in squares
  dev.m_drainPerimiter := PD;   // PD, Drain perimeter;
  dev.m_sourcePerimiter := PS;  // PS, Source perimeter
    dev.m_dICVDSIsGiven := if          (IC > -1e40) then 1 else 0;
    dev.m_dICVDS := if         (IC > -1e40) then IC else 0;
    dev.m_dICVGSIsGiven := if          (IC > -1e40) then 1 else 0;
    dev.m_dICVGS := if         (IC > -1e40) then IC else 0;
    dev.m_dICVBSIsGiven := if          (IC > -1e40) then 1 else 0;
    dev.m_dICVBS := if         (IC > -1e40) then IC else 0;
  dev.m_off := OFF;             // non-zero to indicate device is off for dc analysis
  dev.m_bPMOS := mtype;         // P type MOSfet model
  dev.m_nLevel := ex.LEVEL;
  assert(ex.LEVEL== 1, "only MOS Level1 implemented");
  dev.m_dTemp :=TEMP + SpiceConstants.CONSTCtoK;
end mos2RenameParametersDev;