예제 #1
0
 /// <summary>
 /// Generate a BSIM1 transistor
 /// </summary>
 private BSIM1 CreateMosfet(string name, string drain, string gate, string source, string bulk, double w, double l, string model)
 {
     // Create the device
     var e = new BSIM1(name, drain, gate, source, bulk);
     e.SetParameter("w", w);
     e.SetParameter("l", l);
     e.Model = model;
     return e;
 }
예제 #2
0
        /// <summary>
        /// This routine evaluates the drain current, its derivatives and the
        /// charges associated with the gate,bulk and drain terminal
        /// using the B1(Berkeley Short-Channel IGFET Model) Equations.
        /// </summary>
        /// <param name="bsim1"></param>
        /// <param name="vds"></param>
        /// <param name="vbs"></param>
        /// <param name="vgs"></param>
        /// <param name="gmPointer"></param>
        /// <param name="gdsPointer"></param>
        /// <param name="gmbsPointer"></param>
        /// <param name="qgPointer"></param>
        /// <param name="qbPointer"></param>
        /// <param name="qdPointer"></param>
        /// <param name="cggbPointer"></param>
        /// <param name="cgdbPointer"></param>
        /// <param name="cgsbPointer"></param>
        /// <param name="cbgbPointer"></param>
        /// <param name="cbdbPointer"></param>
        /// <param name="cbsbPointer"></param>
        /// <param name="cdgbPointer"></param>
        /// <param name="cddbPointer"></param>
        /// <param name="cdsbPointer"></param>
        /// <param name="cdrainPointer"></param>
        /// <param name="vonPointer"></param>
        /// <param name="vdsatPointer"></param>
        /// <param name="ckt"></param>
        public static void B1evaluate(this BSIM1 bsim1, double vds, double vbs, double vgs, out double gmPointer, out double gdsPointer, out double gmbsPointer,
                                      out double qgPointer, out double qbPointer, out double qdPointer, out double cggbPointer, out double cgdbPointer, out double cgsbPointer,
                                      out double cbgbPointer, out double cbdbPointer, out double cbsbPointer, out double cdgbPointer, out double cddbPointer,
                                      out double cdsbPointer, out double cdrainPointer, out double vonPointer, out double vdsatPointer, Circuit ckt)
        {
            var    model = bsim1.Model as BSIM1Model;
            double gm, gds, gmbs, qg = 0.0, qb = 0.0, qd = 0.0, cggb = 0, cgdb = 0, cgsb = 0, cbgb = 0, cbdb = 0, cbsb = 0, cdgb = 0, cddb = 0, cdsb = 0, Vfb, Phi, K1, K2, Vdd, Ugs, Uds, dUgsdVbs,
                   Leff, dUdsdVbs, dUdsdVds, Eta, dEtadVds, dEtadVbs, Vpb, SqrtVpb, Von, Vth, dVthdVbs, dVthdVds, Vgs_Vth, DrainCurrent,
                   G, A, Arg, dGdVbs, dAdVbs, Beta, Beta_Vds_0, BetaVdd, dBetaVdd_dVds, Beta0, dBeta0dVds, dBeta0dVbs, VddSquare, C1, C2,
                   dBetaVdd_dVbs, dBeta_Vds_0_dVbs, dC1dVbs, dC2dVbs, dBetadVgs, dBetadVds, dBetadVbs, VdsSat = 0, Argl1, Argl2, Vc, Term1, K,
                   Args1, dVcdVgs, dVcdVds, dVcdVbs, dKdVc, dKdVgs, dKdVds, dKdVbs, Args2, Args3, Warg1, Vcut, N, N0, NB, ND, Warg2, Wds,
                   Wgs, Ilimit, Iexp, Temp1, Vth0, Arg1, Arg2, Arg3, Arg5, Ent, Vcom, Vgb, Vgb_Vfb, VdsPinchoff, EntSquare, Vgs_VthSquare,
                   Argl3, Argl4, Argl5, Argl6, Argl7, Argl8, Argl9, dEntdVds, dEntdVbs, cgbb, cdbb, cbbb, WLCox, Vtsquare, Temp3;
            bool   ChargeComputationNeeded;
            double co4v15;

            if (ckt.Method != null)
            {
                ChargeComputationNeeded = true;
            }
            else if (ckt.State.UseSmallSignal)
            {
                ChargeComputationNeeded = true;
            }
            else if (ckt.State.Domain == State.DomainTypes.Time && ckt.State.UseDC && ckt.State.UseIC)
            {
                ChargeComputationNeeded = true;
            }
            else
            {
                ChargeComputationNeeded = false;
            }

            Vfb = bsim1.B1vfb;
            Phi = bsim1.B1phi;
            K1  = bsim1.B1K1;
            K2  = bsim1.B1K2;
            Vdd = model.B1vdd;
            if ((Ugs = bsim1.B1ugs + bsim1.B1ugsB * vbs) <= 0)
            {
                Ugs      = 0;
                dUgsdVbs = 0.0;
            }
            else
            {
                dUgsdVbs = bsim1.B1ugsB;
            }
            if ((Uds = bsim1.B1uds + bsim1.B1udsB * vbs +
                       bsim1.B1udsD * (vds - Vdd)) <= 0)
            {
                Uds      = 0.0;
                dUdsdVbs = dUdsdVds = 0.0;
            }
            else
            {
                Leff     = bsim1.B1l * 1.0e6 - model.B1deltaL; /* Leff in um */
                Uds      = Uds / Leff;
                dUdsdVbs = bsim1.B1udsB / Leff;
                dUdsdVds = bsim1.B1udsD / Leff;
            }
            Eta = bsim1.B1eta + bsim1.B1etaB * vbs + bsim1.B1etaD *
                  (vds - Vdd);
            if (Eta <= 0)
            {
                Eta      = 0;
                dEtadVds = dEtadVbs = 0.0;
            }
            else if (Eta > 1)
            {
                Eta      = 1;
                dEtadVds = dEtadVbs = 0;
            }
            else
            {
                dEtadVds = bsim1.B1etaD;
                dEtadVbs = bsim1.B1etaB;
            }
            if (vbs < 0)
            {
                Vpb = Phi - vbs;
            }
            else
            {
                Vpb = Phi;
            }
            SqrtVpb  = Math.Sqrt(Vpb);
            Von      = Vfb + Phi + K1 * SqrtVpb - K2 * Vpb - Eta * vds;
            Vth      = Von;
            dVthdVds = -Eta - dEtadVds * vds;
            dVthdVbs = K2 - 0.5 * K1 / SqrtVpb - dEtadVbs * vds;
            Vgs_Vth  = vgs - Vth;

            G      = 1.0 - 1.0 / (1.744 + 0.8364 * Vpb);
            A      = 1.0 + 0.5 * G * K1 / SqrtVpb;
            A      = Math.Max(A, 1.0); /* Modified */
            Arg    = Math.Max((1 + Ugs * Vgs_Vth), 1.0);
            dGdVbs = -0.8364 * (1 - G) * (1 - G);
            dAdVbs = 0.25 * K1 / SqrtVpb * (2 * dGdVbs + G / Vpb);

            if (Vgs_Vth < 0)
            {
                /* cutoff */
                DrainCurrent = 0;
                gm           = 0;
                gds          = 0;
                gmbs         = 0;
                goto SubthresholdComputation;
            }

            /* Quadratic Interpolation for Beta0 (Beta at vgs  =  0, vds=Vds) */

            Beta_Vds_0    = (bsim1.B1betaZero + bsim1.B1betaZeroB * vbs);
            BetaVdd       = (bsim1.B1betaVdd + bsim1.B1betaVddB * vbs);
            dBetaVdd_dVds = Math.Max(bsim1.B1betaVddD, 0.0); /* Modified */
            if (vds > Vdd)
            {
                Beta0      = BetaVdd + dBetaVdd_dVds * (vds - Vdd);
                dBeta0dVds = dBetaVdd_dVds;
                dBeta0dVbs = bsim1.B1betaVddB;
            }
            else
            {
                VddSquare        = Vdd * Vdd;
                C1               = (-BetaVdd + Beta_Vds_0 + dBetaVdd_dVds * Vdd) / VddSquare;
                C2               = 2 * (BetaVdd - Beta_Vds_0) / Vdd - dBetaVdd_dVds;
                dBeta_Vds_0_dVbs = bsim1.B1betaZeroB;
                dBetaVdd_dVbs    = bsim1.B1betaVddB;
                dC1dVbs          = (dBeta_Vds_0_dVbs - dBetaVdd_dVbs) / VddSquare;
                dC2dVbs          = dC1dVbs * (-2) * Vdd;
                Beta0            = (C1 * vds + C2) * vds + Beta_Vds_0;
                dBeta0dVds       = 2 * C1 * vds + C2;
                dBeta0dVbs       = dC1dVbs * vds * vds + dC2dVbs * vds + dBeta_Vds_0_dVbs;
            }

            /*Beta  =  Beta0 / ( 1 + Ugs * Vgs_Vth );*/

            Beta      = Beta0 / Arg;
            dBetadVgs = -Beta * Ugs / Arg;
            dBetadVds = dBeta0dVds / Arg - dBetadVgs * dVthdVds;
            dBetadVbs = dBeta0dVbs / Arg + Beta * Ugs * dVthdVbs / Arg -
                        Beta * Vgs_Vth * dUgsdVbs / Arg;

            /*VdsSat  = Math.Max( Vgs_Vth / ( A + Uds * Vgs_Vth ),  0.0);*/

            if ((Vc = Uds * Vgs_Vth / A) < 0.0)
            {
                Vc = 0.0;
            }
            Term1  = Math.Sqrt(1 + 2 * Vc);
            K      = 0.5 * (1 + Vc + Term1);
            VdsSat = Math.Max(Vgs_Vth / (A * Math.Sqrt(K)), 0.0);

            if (vds < VdsSat)
            {
                /* Triode Region */
                /*Argl1  =  1 + Uds * vds;*/
                Argl1        = Math.Max((1 + Uds * vds), 1.0);
                Argl2        = Vgs_Vth - 0.5 * A * vds;
                DrainCurrent = Beta * Argl2 * vds / Argl1;
                gm           = (dBetadVgs * Argl2 * vds + Beta * vds) / Argl1;
                gds          = (dBetadVds * Argl2 * vds + Beta *
                                (Vgs_Vth - vds * dVthdVds - A * vds) -
                                DrainCurrent * (vds * dUdsdVds + Uds)) / Argl1;
                gmbs = (dBetadVbs * Argl2 * vds + Beta * vds *
                        (-dVthdVbs - 0.5 * vds * dAdVbs) -
                        DrainCurrent * vds * dUdsdVbs) / Argl1;
            }
            else
            {
                /* Pinchoff (Saturation) Region */
                Args1   = 1.0 + 1.0 / Term1;
                dVcdVgs = Uds / A;
                dVcdVds = Vgs_Vth * dUdsdVds / A - dVcdVgs * dVthdVds;
                dVcdVbs = (Vgs_Vth * dUdsdVbs - Uds *
                           (dVthdVbs + Vgs_Vth * dAdVbs / A)) / A;
                dKdVc        = 0.5 * Args1;
                dKdVgs       = dKdVc * dVcdVgs;
                dKdVds       = dKdVc * dVcdVds;
                dKdVbs       = dKdVc * dVcdVbs;
                Args2        = Vgs_Vth / A / K;
                Args3        = Args2 * Vgs_Vth;
                DrainCurrent = 0.5 * Beta * Args3;
                gm           = 0.5 * Args3 * dBetadVgs + Beta * Args2 -
                               DrainCurrent * dKdVgs / K;
                gds = 0.5 * Args3 * dBetadVds - Beta * Args2 * dVthdVds -
                      DrainCurrent * dKdVds / K;
                gmbs = 0.5 * dBetadVbs * Args3 - Beta * Args2 * dVthdVbs -
                       DrainCurrent * (dAdVbs / A + dKdVbs / K);
            }

SubthresholdComputation:

            N0   = bsim1.B1subthSlope;
            Vcut = -40.0 * N0 * Circuit.CONSTvt0;

            /* The following 'if' statement has been modified so that subthreshold  *
            * current computation is always executed unless N0 >= 200. This should *
            * get rid of the Ids kink seen on Ids-Vgs plots at low Vds.            *
            *                                                Peter M. Lee          *
            *                                                6/8/90                *
            *  Old 'if' statement:                                                 *
            *  if( (N0 >=  200) || (Vgs_Vth < Vcut ) || (Vgs_Vth > (-0.5*Vcut)))   */

            if (N0 >= 200)
            {
                goto ChargeComputation;
            }

            NB = bsim1.B1subthSlopeB;
            ND = bsim1.B1subthSlopeD;
            N  = N0 + NB * vbs + ND * vds; /* subthreshold slope */
            if (N < 0.5)
            {
                N = 0.5;
            }
            Warg1        = Math.Exp(-vds / Circuit.CONSTvt0);
            Wds          = 1 - Warg1;
            Wgs          = Math.Exp(Vgs_Vth / (N * Circuit.CONSTvt0));
            Vtsquare     = Circuit.CONSTvt0 * Circuit.CONSTvt0;
            Warg2        = 6.04965 * Vtsquare * bsim1.B1betaZero;
            Ilimit       = 4.5 * Vtsquare * bsim1.B1betaZero;
            Iexp         = Warg2 * Wgs * Wds;
            DrainCurrent = DrainCurrent + Ilimit * Iexp / (Ilimit + Iexp);
            Temp1        = Ilimit / (Ilimit + Iexp);
            Temp1        = Temp1 * Temp1;
            Temp3        = Ilimit / (Ilimit + Wgs * Warg2);
            Temp3        = Temp3 * Temp3 * Warg2 * Wgs;
            /*    if ( Temp3 > Ilimit ) Temp3=Ilimit;*/
            gm = gm + Temp1 * Iexp / (N * Circuit.CONSTvt0);
            /* gds term has been modified to prevent blow up at Vds=0 */
            gds = gds + Temp3 * (-Wds / N / Circuit.CONSTvt0 * (dVthdVds +
                                                                Vgs_Vth * ND / N) + Warg1 / Circuit.CONSTvt0);
            gmbs = gmbs - Temp1 * Iexp * (dVthdVbs + Vgs_Vth * NB / N) /
                   (N * Circuit.CONSTvt0);

ChargeComputation:

            /* Some Limiting of DC Parameters */
            if (DrainCurrent < 0.0)
            {
                DrainCurrent = 0.0;
            }
            if (gm < 0.0)
            {
                gm = 0.0;
            }
            if (gds < 0.0)
            {
                gds = 0.0;
            }
            if (gmbs < 0.0)
            {
                gmbs = 0.0;
            }

            WLCox = model.B1Cox *
                    (bsim1.B1l - model.B1deltaL * 1.0e-6) *
                    (bsim1.B1w - model.B1deltaW * 1.0e-6) * 1.0e4; /* F */

            if (!ChargeComputationNeeded)
            {
                qg   = 0;
                qd   = 0;
                qb   = 0;
                cggb = 0;
                cgsb = 0;
                cgdb = 0;
                cdgb = 0;
                cdsb = 0;
                cddb = 0;
                cbgb = 0;
                cbsb = 0;
                cbdb = 0;
                goto finished;
            }
            G = 1.0 - 1.0 / (1.744 + 0.8364 * Vpb);
            A = 1.0 + 0.5 * G * K1 / SqrtVpb;
            A = Math.Max(A, 1.0);   /* Modified */
                                    /*Arg  =  1 + Ugs * Vgs_Vth;*/
            dGdVbs = -0.8364 * (1 - G) * (1 - G);
            dAdVbs = 0.25 * K1 / SqrtVpb * (2 * dGdVbs + G / Vpb);
            Phi    = Math.Max(0.1, Phi);

            if (model.B1channelChargePartitionFlag >= 1)
            {
                /*0/100 partitioning for drain/source chArges at the saturation region*/
                Vth0     = Vfb + Phi + K1 * SqrtVpb;
                Vgs_Vth  = vgs - Vth0;
                Arg1     = A * vds;
                Arg2     = Vgs_Vth - 0.5 * Arg1;
                Arg3     = vds - Arg1;
                Arg5     = Arg1 * Arg1;
                dVthdVbs = -0.5 * K1 / SqrtVpb;
                dAdVbs   = 0.5 * K1 * (0.5 * G / Vpb - 0.8364 * (1 - G) * (1 - G)) /
                           SqrtVpb;
                Ent      = Math.Max(Arg2, 1.0e-8);
                dEntdVds = -0.5 * A;
                dEntdVbs = -dVthdVbs - 0.5 * vds * dAdVbs;
                Vcom     = Vgs_Vth * Vgs_Vth / 6.0 - 1.25e-1 * Arg1 *
                           Vgs_Vth + 2.5e-2 * Arg5;
                VdsPinchoff = Math.Max(Vgs_Vth / A, 0.0);
                Vgb         = vgs - vbs;
                Vgb_Vfb     = Vgb - Vfb;

                if (Vgb_Vfb < 0)
                {
                    /* Accumulation Region */
                    qg   = WLCox * Vgb_Vfb;
                    qb   = -qg;
                    qd   = 0.0;
                    cggb = WLCox;
                    cgdb = 0.0;
                    cgsb = 0.0;
                    cbgb = -WLCox;
                    cbdb = 0.0;
                    cbsb = 0.0;
                    cdgb = 0.0;
                    cddb = 0.0;
                    cdsb = 0.0;
                    goto finished;
                }
                else if (vgs < Vth0)
                {
                    /* Subthreshold Region */
                    qg = 0.5 * WLCox * K1 * K1 * (-1 +
                                                  Math.Sqrt(1 + 4 * Vgb_Vfb / (K1 * K1)));
                    qb   = -qg;
                    qd   = 0.0;
                    cggb = WLCox / Math.Sqrt(1 + 4 * Vgb_Vfb / (K1 * K1));
                    cgdb = cgsb = 0.0;
                    cbgb = -cggb;
                    cbdb = cbsb = cdgb = cddb = cdsb = 0.0;
                    goto finished;
                }
                else if (vds < VdsPinchoff)
                {    /* triode region  */
                     /*Vgs_Vth2 = Vgs_Vth*Vgs_Vth;*/
                    EntSquare = Ent * Ent;
                    Argl1     = 1.2e1 * EntSquare;
                    Argl2     = 1.0 - A;
                    Argl3     = Arg1 * vds;
                    /*Argl4 = Vcom/Ent/EntSquare;*/
                    if (Ent > 1.0e-8)
                    {
                        Argl5 = Arg1 / Ent;
                        /*Argl6 = Vcom/EntSquare;*/
                    }
                    else
                    {
                        Argl5 = 2.0;
                        Argl6 = 4.0 / 1.5e1;
                    }
                    Argl7 = Argl5 / 1.2e1;
                    Argl8 = 6.0 * Ent;
                    Argl9 = 0.125 * Argl5 * Argl5;
                    qg    = WLCox * (vgs - Vfb - Phi - 0.5 * vds + vds * Argl7);
                    qb    = WLCox * (-Vth0 + Vfb + Phi + 0.5 * Arg3 - Arg3 * Argl7);
                    qd    = -WLCox * (0.5 * Vgs_Vth - 0.75 * Arg1 +
                                      0.125 * Arg1 * Argl5);
                    cggb = WLCox * (1.0 - Argl3 / Argl1);
                    cgdb = WLCox * (-0.5 + Arg1 / Argl8 - Argl3 * dEntdVds /
                                    Argl1);
                    cgbb = WLCox * (vds * vds * dAdVbs * Ent - Argl3 * dEntdVbs) /
                           Argl1;
                    cgsb = -(cggb + cgdb + cgbb);
                    cbgb = WLCox * Argl3 * Argl2 / Argl1;
                    cbdb = WLCox * Argl2 * (0.5 - Arg1 / Argl8 + Argl3 * dEntdVds /
                                            Argl1);
                    cbbb = -WLCox * (dVthdVbs + 0.5 * vds * dAdVbs + vds *
                                     vds * ((1.0 - 2.0 * A) * dAdVbs * Ent - Argl2 *
                                            A * dEntdVbs) / Argl1);
                    cbsb = -(cbgb + cbdb + cbbb);
                    cdgb = -WLCox * (0.5 - Argl9);
                    cddb = WLCox * (0.75 * A - 0.25 * A * Arg1 / Ent +
                                    Argl9 * dEntdVds);
                    cdbb = WLCox * (0.5 * dVthdVbs + vds * dAdVbs *
                                    (0.75 - 0.25 * Argl5) + Argl9 * dEntdVbs);
                    cdsb = -(cdgb + cddb + cdbb);
                    goto finished;
                }
                else if (vds >= VdsPinchoff)
                {    /* saturation region   */
                    Args1 = 1.0 / (3.0 * A);
                    qg    = WLCox * (vgs - Vfb - Phi - Vgs_Vth * Args1);
                    qb    = WLCox * (Vfb + Phi - Vth0 + (1.0 - A) * Vgs_Vth * Args1);
                    qd    = 0.0;
                    cggb  = WLCox * (1.0 - Args1);
                    cgdb  = 0.0;
                    cgbb  = WLCox * Args1 * (dVthdVbs + Vgs_Vth * dAdVbs / A);
                    cgsb  = -(cggb + cgdb + cgbb);
                    cbgb  = WLCox * (Args1 - 1.0 / 3.0);
                    cbdb  = 0.0;
                    cbbb  = -WLCox * ((2.0 / 3.0 + Args1) * dVthdVbs +
                                      Vgs_Vth * Args1 * dAdVbs / A); /* Modified */
                    cbsb = -(cbgb + cbdb + cbbb);
                    cdgb = 0.0;
                    cddb = 0.0;
                    cdsb = 0.0;
                    goto finished;
                }

                goto finished;
            }
            else
            {
                /* ChannelChargePartionFlag  < = 0 */

                /*40/60 partitioning for drain/source chArges at the saturation region*/
                co4v15      = 4.0 / 15.0;
                Vth0        = Vfb + Phi + K1 * SqrtVpb;
                Vgs_Vth     = vgs - Vth0;
                Arg1        = A * vds;
                Arg2        = Vgs_Vth - 0.5 * Arg1;
                Arg3        = vds - Arg1;
                Arg5        = Arg1 * Arg1;
                dVthdVbs    = -0.5 * K1 / SqrtVpb;
                dAdVbs      = 0.5 * K1 * (0.5 * G / Vpb - 0.8364 * (1 - G) * (1 - G)) / SqrtVpb;
                Ent         = Math.Max(Arg2, 1.0e-8);
                dEntdVds    = -0.5 * A;
                dEntdVbs    = -dVthdVbs - 0.5 * vds * dAdVbs;
                Vcom        = Vgs_Vth * Vgs_Vth / 6.0 - 1.25e-1 * Arg1 * Vgs_Vth + 2.5e-2 * Arg5;
                VdsPinchoff = Math.Max(Vgs_Vth / A, 0.0);
                Vgb         = vgs - vbs;
                Vgb_Vfb     = Vgb - Vfb;

                if (Vgb_Vfb < 0)
                {           /* Accumulation Region */
                    qg   = WLCox * Vgb_Vfb;
                    qb   = -qg;
                    qd   = 0.0;
                    cggb = WLCox;
                    cgdb = 0.0;
                    cgsb = 0.0;
                    cbgb = -WLCox;
                    cbdb = 0.0;
                    cbsb = 0.0;
                    cdgb = 0.0;
                    cddb = 0.0;
                    cdsb = 0.0;
                    goto finished;
                }
                else if (vgs < Vth0)
                {    /* Subthreshold Region */
                    qg   = 0.5 * WLCox * K1 * K1 * (-1 + Math.Sqrt(1 + 4 * Vgb_Vfb / (K1 * K1)));
                    qb   = -qg;
                    qd   = 0.0;
                    cggb = WLCox / Math.Sqrt(1 + 4 * Vgb_Vfb / (K1 * K1));
                    cgdb = cgsb = 0.0;
                    cbgb = -cggb;
                    cbdb = cbsb = cdgb = cddb = cdsb = 0.0;
                    goto finished;
                }
                else if (vds < VdsPinchoff)
                {      /* triode region */
                    Vgs_VthSquare = Vgs_Vth * Vgs_Vth;
                    EntSquare     = Ent * Ent;
                    Argl1         = 1.2e1 * EntSquare;
                    Argl2         = 1.0 - A;
                    Argl3         = Arg1 * vds;
                    Argl4         = Vcom / Ent / EntSquare;
                    if (Ent > 1.0e-8)
                    {
                        Argl5 = Arg1 / Ent;
                        Argl6 = Vcom / EntSquare;
                    }
                    else
                    {
                        Argl5 = 2.0;
                        Argl6 = 4.0 / 1.5e1;
                    }
                    Argl7 = Argl5 / 1.2e1;
                    Argl8 = 6.0 * Ent;
                    qg    = WLCox * (vgs - Vfb - Phi - 0.5 * vds + vds * Argl7);
                    qb    = WLCox * (-Vth0 + Vfb + Phi + 0.5 * Arg3 - Arg3 * Argl7);
                    qd    = -WLCox * (0.5 * (Vgs_Vth - Arg1) + Arg1 * Argl6);
                    cggb  = WLCox * (1.0 - Argl3 / Argl1);
                    cgdb  = WLCox * (-0.5 + Arg1 / Argl8 - Argl3 * dEntdVds / Argl1);
                    cgbb  = WLCox * (vds * vds * dAdVbs * Ent - Argl3 * dEntdVbs) / Argl1;
                    cgsb  = -(cggb + cgdb + cgbb);
                    cbgb  = WLCox * Argl3 * Argl2 / Argl1;
                    cbdb  = WLCox * Argl2 * (0.5 - Arg1 / Argl8 + Argl3 * dEntdVds / Argl1);
                    cbbb  = -WLCox * (dVthdVbs + 0.5 * vds * dAdVbs + vds * vds * ((1.0 - 2.0 * A)
                                                                                   * dAdVbs * Ent - Argl2 * A * dEntdVbs) / Argl1);
                    cbsb = -(cbgb + cbdb + cbbb);
                    cdgb = -WLCox * (0.5 + Arg1 * (4.0 * Vgs_Vth - 1.5 * Arg1) / Argl1 -
                                     2.0 * Arg1 * Argl4);
                    cddb = WLCox * (0.5 * A + 2.0 * Arg1 * dEntdVds * Argl4 - A * (2.0 * Vgs_VthSquare
                                                                                   - 3.0 * Arg1 * Vgs_Vth + 0.9 * Arg5) / Argl1);
                    cdbb = WLCox * (0.5 * dVthdVbs + 0.5 * vds * dAdVbs + 2.0 * Arg1 * dEntdVbs
                                    * Argl4 - vds * (2.0 * Vgs_VthSquare * dAdVbs - 4.0 * A * Vgs_Vth * dVthdVbs - 3.0
                                                     * Arg1 * Vgs_Vth * dAdVbs + 1.5 * A * Arg1 * dVthdVbs + 0.9 * Arg5 * dAdVbs)
                                    / Argl1);
                    cdsb = -(cdgb + cddb + cdbb);
                    goto finished;
                }
                else if (vds >= VdsPinchoff)
                {      /* saturation region */
                    Args1 = 1.0 / (3.0 * A);
                    qg    = WLCox * (vgs - Vfb - Phi - Vgs_Vth * Args1);
                    qb    = WLCox * (Vfb + Phi - Vth0 + (1.0 - A) * Vgs_Vth * Args1);
                    qd    = -co4v15 * WLCox * Vgs_Vth;
                    cggb  = WLCox * (1.0 - Args1);
                    cgdb  = 0.0;
                    cgbb  = WLCox * Args1 * (dVthdVbs + Vgs_Vth * dAdVbs / A);
                    cgsb  = -(cggb + cgdb + cgbb);
                    cbgb  = WLCox * (Args1 - 1.0 / 3.0);
                    cbdb  = 0.0;
                    cbbb  = -WLCox * ((2.0 / 3.0 + Args1) * dVthdVbs + Vgs_Vth * Args1 * dAdVbs / A);
                    cbsb  = -(cbgb + cbdb + cbbb);
                    cdgb  = -co4v15 * WLCox;
                    cddb  = 0.0;
                    cdbb  = co4v15 * WLCox * dVthdVbs;
                    cdsb  = -(cdgb + cddb + cdbb);
                    goto finished;
                }
            }

finished:   /* returning Values to Calling Routine */


            gmPointer     = Math.Max(gm, 0.0);
            gdsPointer    = Math.Max(gds, 0.0);
            gmbsPointer   = Math.Max(gmbs, 0.0);
            qgPointer     = qg;
            qbPointer     = qb;
            qdPointer     = qd;
            cggbPointer   = cggb;
            cgdbPointer   = cgdb;
            cgsbPointer   = cgsb;
            cbgbPointer   = cbgb;
            cbdbPointer   = cbdb;
            cbsbPointer   = cbsb;
            cdgbPointer   = cdgb;
            cddbPointer   = cddb;
            cdsbPointer   = cdsb;
            cdrainPointer = Math.Max(DrainCurrent, 0.0);
            vonPointer    = Von;
            vdsatPointer  = VdsSat;
        }