
//
// Verilog-A definition of VBIC
//

`include "disciplines.vams"
`include "constants.vams"

`define CONSTroot2 1.41421356237309504880
//
//  There are 8 separate versions of VBIC, defined as follows:
//
//              #Elect  Electro Excess
//      Name        Terms   Thermal Phase
//      =============   ======= ======= ======
//      vbic_3T_it_cf   3   no  no
//      vbic_3T_it_xf   3   no  yes
//      vbic_3T_et_cf   3   yes no
//      vbic_3T_et_xf   3   yes yes
//      vbic_4T_it_cf   4   no  no
//      vbic_4T_it_xf   4   no  yes
//      vbic_4T_et_cf   4   yes no
//      vbic_4T_et_xf   4   yes yes
//
//  These can be selected by appropriate specification of
//  the following `define text macros. Note that the specification
//  of a 3- or 4-terminal model relates to the number of
//  electrical terminals, and does not include the local temperature
//  node for the electrothermal version of the model.
//
//  There are two separate versions of each of the above,
//  with and without homotopy. When the homotopy is included
//  this code will not work in Verilog-A, but will be
//  handled by the VBIC code generator properly.
//
//  The excess phase version does not need to be implemented strictly
//  using 3 extra system variables, as at first seems to be the
//  case for MNA, the inductor current and the two node voltages.
//  The resistor in the excess phase network is 1 ohm, therefore
//  the voltage at node xf2 is the same as the current through
//  the inductor. The extra system equations to solve are then:
//  Itzf-V(xf2)-j*w*C*V(xf1)=0
//  j*w*L*V(xf2)+V(xf2)-V(xf1)=0
//  where C=TD and L=TD/3.
//

//`define ThreeTerminal     // default is FourTerminal
//`define ExcessPhase       // default is ConstantPhase
//`define ElectroThermal    // default is IsoThermal
//`define WithHomotopy      // default is NoHomotopy

//
//  Start of VBIC model code
//

module vbic_4T_et_cf(c,b,e,s,dt);

//
//  Node definitions
//

    inout       c,b,e,s,dt;         // external nodes
    electrical  c,b,e,s,dt;         // external nodes
    electrical  cx,ci,bx,bi,ei,bp,si;       // internal nodes

//
//  Branch definitions
//

    branch (b ,e )      be;         //           base-emit
    branch (b ,c )      bc;         //           base-coll
    branch (bi,ei)      bei;            // intrinsic base-emit
    branch (bx,ei)      bex;            // extrinsic base-emit
    branch (bi,ci)      bci;            // intrinsic base-coll
    branch (bi,cx)      bcx;            // extrinsic base-coll
    branch (ci,ei)      cei;            // intrinsic coll-emit
    branch (ei,ci)      eci;            // intrinsic emit-coll
    branch (bx,bp)      bep;            // parasitic base-emit
    branch (e ,ei)      re;         // emit resistance
    branch (c ,cx)      rcx;            // coll resistance, extrinsic
    branch (cx,ci)      rci;            // coll resistance, intrinsic
    branch (b ,bx)      rbx;            // base resistance, extrinsic
    branch (bx,bi)      rbi;            // base resistance, intrinsic
    branch (bp,cx)      rbp;            // base resistance, parasitic
    branch (si,bp)      bcp;            // parasitic base-coll
    branch (bx,si)      cep;            // parasitic coll-emit
    branch (s ,si)      rs;         // subs resistance
    branch (dt)     rth;            // local thermal branch
    branch (dt)     ith;            // local thermal branch

//
//  Parameter definitions
//

    parameter   real    TNOM    =  27.0;
    parameter   real    RCX =   0.0     from[0.0:inf);
    parameter   real    RCI =   0.0     from[0.0:inf);
    parameter   real    VO  =   0.0     from[0.0:inf);
    parameter   real    GAMM    =   0.0     from[0.0:inf);
    parameter   real    HRCF    =   0.0     from[0.0:inf);
    parameter   real    RBX =   0.0     from[0.0:inf);
    parameter   real    RBI =   0.0     from[0.0:inf);
    parameter   real    RE  =   0.0     from[0.0:inf);
    parameter   real    RS  =   0.0     from[0.0:inf);
    parameter   real    RBP =   0.0     from[0.0:inf);
    parameter   real    IS  =   1.0e-16 from(0.0:inf);
    parameter   real    NF  =   1.0     from(0.0:inf);
    parameter   real    NR  =   1.0     from(0.0:inf);
    parameter   real    FC  =   0.9     from[0.0:1.0);
    parameter   real    CBEO    =   0.0     from[0.0:inf);
    parameter   real    CJE =   0.0     from[0.0:inf);
    parameter   real    PE  =   0.75    from(0.0:inf);
    parameter   real    ME  =   0.33    from(0.0:1.0);
    parameter   real    AJE =  -0.5;
    parameter   real    CBCO    =   0.0     from[0.0:inf);
    parameter   real    CJC =   0.0     from[0.0:inf);
    parameter   real    QCO =   0.0     from[0.0:inf);
    parameter   real    CJEP    =   0.0     from[0.0:inf);
    parameter   real    PC  =   0.75    from(0.0:inf);
    parameter   real    MC  =   0.33    from(0.0:1.0);
    parameter   real    AJC =  -0.5;
    parameter   real    CJCP    =   0.0     from[0.0:inf);
    parameter   real    PS  =   0.75    from(0.0:inf);
    parameter   real    MS  =   0.33    from(0.0:1.0);
    parameter   real    AJS =  -0.5;
    parameter   real    IBEI    =   1.0e-18 from(0.0:inf);
    parameter   real    WBE =   1.0     from[0.0:1.0];
    parameter   real    NEI =   1.0     from(0.0:inf);
    parameter   real    IBEN    =   0.0     from[0.0:inf);
    parameter   real    NEN =   2.0     from(0.0:inf);
    parameter   real    IBCI    =   1.0e-16 from(0.0:inf);
    parameter   real    NCI =   1.0     from(0.0:inf);
    parameter   real    IBCN    =   0.0     from[0.0:inf);
    parameter   real    NCN =   2.0     from(0.0:inf);
    parameter   real    AVC1    =   0.0     from[0.0:inf);
    parameter   real    AVC2    =   0.0     from[0.0:inf);
    parameter   real    ISP =   0.0     from[0.0:inf);
    parameter   real    WSP =   1.0     from[0.0:1.0];
    parameter   real    NFP =   1.0     from(0.0:inf);
    parameter   real    IBEIP   =   0.0     from[0.0:inf);
    parameter   real    IBENP   =   0.0     from[0.0:inf);
    parameter   real    IBCIP   =   0.0     from[0.0:inf);
    parameter   real    NCIP    =   1.0     from(0.0:inf);
    parameter   real    IBCNP   =   0.0     from[0.0:inf);
    parameter   real    NCNP    =   2.0     from(0.0:inf);
    parameter   real    VEF =   0.0     from[0.0:inf);
    parameter   real    VER =   0.0     from[0.0:inf);
    parameter   real    IKF =   0.0     from[0.0:inf);
    parameter   real    IKR =   0.0     from[0.0:inf);
    parameter   real    IKP =   0.0     from[0.0:inf);
    parameter   real    TF  =   0.0     from[0.0:inf);
    parameter   real    QTF =   0.0     from[0.0:inf);
    parameter   real    XTF =   0.0     from[0.0:inf);
    parameter   real    VTF =   0.0     from[0.0:inf);
    parameter   real    ITF =   0.0     from[0.0:inf);
    parameter   real    TR  =   0.0     from[0.0:inf);
    parameter   real    TD  =   0.0     from[0.0:inf);
    parameter   real    KFN =   0.0     from[0.0:inf);
    parameter   real    AFN =   1.0     from(0.0:inf);
    parameter   real    BFN =   1.0     from(0.0:inf);
    parameter   real    XRE =   0;
    parameter   real    XRBI    =   0;
    parameter   real    XRCI    =   0;
    parameter   real    XRS =   0;
    parameter   real    XVO =   0;
    parameter   real    EA  =   1.12;
    parameter   real    EAIE    =   1.12;
    parameter   real    EAIC    =   1.12;
    parameter   real    EAIS    =   1.12;
    parameter   real    EANE    =   1.12;
    parameter   real    EANC    =   1.12;
    parameter   real    EANS    =   1.12;
    parameter   real    XIS =   3.0;
    parameter   real    XII =   3.0;
    parameter   real    XIN =   3.0;
    parameter   real    TNF =   0.0;
    parameter   real    TAVC    =   0.0;
    parameter   real    RTH =   0.0     from[0.0:inf);
    parameter   real    CTH =   0.0     from[0.0:inf);
    parameter   real    VRT =   0.0     from[0.0:inf);
    parameter   real    ART =   0.1     from(0.0:inf);
    parameter   real    CCSO    =   0.0     from[0.0:inf);
    parameter   real    QBM =   0.0;
    parameter   real    NKF =   0.5     from(0.0:inf);
    parameter   real    XIKF    =   0;
    parameter   real    XRCX    =   0;
    parameter   real    XRBX    =   0;
    parameter   real    XRBP    =   0;
    parameter   real    ISRR    =   1.0     from(0.0:inf);
    parameter   real    XISR    =   0.0;
    parameter   real    DEAR    =   0.0;
    parameter   real    EAP =   1.12;
    parameter   real    VBBE    =   0.0;
    parameter   real    NBBE    =   1.0     from(0.0:inf);
    parameter   real    IBBE    =   1.0e-6;
    parameter   real    TVBBE1  =   0.0;
    parameter   real    TVBBE2  =   0.0;
    parameter   real    TNBBE   =   0.0;
    parameter   real    EBBE    =   0.0;
    parameter   real    DTEMP   =   0.0;
    parameter   real    VERS    =   1.2;
    parameter   real    VREV    =   0.0;

//
    aliasparam  TREF  = TNOM;
    aliasparam  V0    = VO;
    aliasparam  GAMMA = GAMM;
    aliasparam  CBE0  = CBEO;
    aliasparam  CBC0  = CBCO;
    aliasparam  CCS0  = CCSO;
    aliasparam  QC0   = QCO;
    aliasparam  XV0   = XVO;
    aliasparam  DTMP  = DTEMP;
    aliasparam  VERSION = VERS;
//    aliasparam  VREV  = REV REVISION
//

    real    ISatT,ISRRatT,IKFatT,IBEIatT,IBCIatT,ISPatT,IBENatT,IBCNatT;
    real    IBEIPatT,IBENPatT,IBCIPatT,IBCNPatT;
    real    RCXatT,RCIatT,RBXatT,RBIatT,REatT,RSatT,RBPatT;
    real    PEatT,PCatT,PSatT;
    real    CJEatT,CJCatT,CJEPatT,CJCPatT;
    real    NFatT,NRatT,AVC2atT,VBBEatT,NBBEatT,GAMMatT,VOatT,EBBEatT;
    real    Tdev,Tini,rT,dT;
    real    IVEF,IVER,IIKF,IIKR,IIKP,IVO,IHRCF,IVTF,IITF,slTF;

    real    Vtv,Ifi,Iri,Itzf,Itzr,q1z,q1,q2,qb,Ifp,Irp,Iccp,q2p,qbp;
    real    Ibe,Ibex,Ibcj,Ibc,Ibep,Ibcp,Igc,avalf;
    real    Ircx,Irci,Irbx,Irbi,Ire,Irbp,Irs;
    real    Kbci,Kbcx,rKp1,Iohm,derf;
    real    argi,expi,argn,expn,argx,expx;
    real    qdbe,qdbex,qdbc,qdbep,qdbcp;
    real    sgIf,rIf,mIf,tff;
    real    Qbe,Qbex,Qbc,Qbcx,Qbep,Qbcp,Qbeo,Qbco;
    real    Ith,Irth,Qcth;

    real    psiio,psiin,dv0,dvh,pwq,qlo;
    real    qhi,mv0,vl0,q0,dv,mv;
    real    vl,vn0,vnl0,qlo0,vn,vnl;
    real    sel,crt,cmx,cl,ql;

    real    tVCrit, Vbei, Vbex, Vbci, Vbcx, Vbep;

    analog begin
//
//      Temperature mappings
//

        Tini    =  `P_CELSIUS0+TNOM;
        Tdev    =  $temperature+DTEMP+V(rth);
        Vtv =  `P_K*Tdev/`P_Q;
        rT  =  Tdev/Tini;
        dT  =  Tdev-Tini;
        IKFatT  =  IKF*pow(rT,XIKF);
        RCXatT  =  RCX*pow(rT,XRCX);
        RCIatT  =  RCI*pow(rT,XRCI);
        RBXatT  =  RBX*pow(rT,XRBX);
        RBIatT  =  RBI*pow(rT,XRBI);
        REatT   =  RE*pow(rT,XRE);
        RSatT   =  RS*pow(rT,XRS);
        RBPatT  =  RBP*pow(rT,XRBP);
        ISatT   =  IS*pow((pow(rT,XIS)*exp(-EA*(1.0-rT)/Vtv)),(1.0/NF));
        ISRRatT =  ISRR*pow((pow(rT,XISR)*exp(-DEAR*(1.0-rT)/Vtv)),(1.0/NR));
        ISPatT  =  ISP*pow((pow(rT,XIS)*exp(-EAP*(1.0-rT)/Vtv)),(1.0/NFP));
        IBEIatT =  IBEI*pow((pow(rT,XII)*exp(-EAIE*(1.0-rT)/Vtv)),(1.0/NEI));
        IBENatT =  IBEN*pow((pow(rT,XIN)*exp(-EANE*(1.0-rT)/Vtv)),(1.0/NEN));
        IBCIatT =  IBCI*pow((pow(rT,XII)*exp(-EAIC*(1.0-rT)/Vtv)),(1.0/NCI));
        IBCNatT =  IBCN*pow((pow(rT,XIN)*exp(-EANC*(1.0-rT)/Vtv)),(1.0/NCN));
        IBEIPatT=  IBEIP*pow((pow(rT,XII)*exp(-EAIC*(1.0-rT)/Vtv)),(1.0/NCI));
        IBENPatT=  IBENP*pow((pow(rT,XIN)*exp(-EANC*(1.0-rT)/Vtv)),(1.0/NCN));
        IBCIPatT=  IBCIP*pow((pow(rT,XII)*exp(-EAIS*(1.0-rT)/Vtv)),(1.0/NCIP));
        IBCNPatT=  IBCNP*pow((pow(rT,XIN)*exp(-EANS*(1.0-rT)/Vtv)),(1.0/NCNP));
        NFatT   =  NF*(1.0+dT*TNF);
        NRatT   =  NR*(1.0+dT*TNF);
        AVC2atT =  AVC2*(1.0+dT*TAVC);
        VBBEatT =  VBBE*(1.0+dT*(TVBBE1+dT*TVBBE2));
        NBBEatT =  NBBE*(1.0+dT*TNBBE);
        psiio = 2.0*(Vtv/rT)*ln(exp(0.5*PE*rT/Vtv)-exp(-0.5*PE*rT/Vtv));
        psiin = psiio*rT-3.0*Vtv*ln(rT)-EAIE*(rT-1.0);
        PEatT = psiin+2.0*Vtv*ln(0.5*(1.0+sqrt(1.0+4.0*exp(-psiin/Vtv))));
        psiio = 2.0*(Vtv/rT)*ln(exp(0.5*PC*rT/Vtv)-exp(-0.5*PC*rT/Vtv));
        psiin = psiio*rT-3.0*Vtv*ln(rT)-EAIC*(rT-1.0);
        PCatT = psiin+2.0*Vtv*ln(0.5*(1.0+sqrt(1.0+4.0*exp(-psiin/Vtv))));
        psiio = 2.0*(Vtv/rT)*ln(exp(0.5*PS*rT/Vtv)-exp(-0.5*PS*rT/Vtv));
        psiin = psiio*rT-3.0*Vtv*ln(rT)-EAIS*(rT-1.0);
        PSatT = psiin+2.0*Vtv*ln(0.5*(1.0+sqrt(1.0+4.0*exp(-psiin/Vtv))));
        CJEatT  =  CJE*pow(PE/PEatT,ME);
        CJCatT  =  CJC*pow(PC/PCatT,MC);
        CJEPatT =  CJEP*pow(PC/PCatT,MC);
        CJCPatT =  CJCP*pow(PS/PSatT,MS);
        GAMMatT =  GAMM*pow(rT,XIS)*exp(-EA*(1.0-rT)/Vtv);
        VOatT   =  VO*pow(rT,XVO);
        EBBEatT =  exp(-VBBEatT/(NBBEatT*Vtv));

        tVCrit = $vt($temperature)*ln($vt($temperature)/(`CONSTroot2*IS));
//
//      Parameter mappings
//

        IVEF    =  VEF>0.0   ? 1.0/VEF    : 0.0;
        IVER    =  VER>0.0   ? 1.0/VER    : 0.0;
        IIKF    =  IKF>0.0   ? 1.0/IKFatT : 0.0;
        IIKR    =  IKR>0.0   ? 1.0/IKR    : 0.0;
        IIKP    =  IKP>0.0   ? 1.0/IKP    : 0.0;
        IVO =  VO>0.0    ? 1.0/VOatT  : 0.0;
        IHRCF   =  HRCF>0.0  ? 1.0/HRCF   : 0.0;
        IVTF    =  VTF>0.0   ? 1.0/VTF    : 0.0;
        IITF    =  ITF>0.0   ? 1.0/ITF    : 0.0;
        slTF    =  ITF>0.0   ? 0.0        : 1.0;

//
//      Electrical branch constituent relations
//

`ifdef __NGSPICE__
        Vbei     =  $limit(V(bi,ei), "pnjlim", Vtv, tVCrit);
        Vbex     =  $limit(V(bx,ei), "pnjlim", Vtv, tVCrit);
        Vbci     =  $limit(V(bi,ci), "pnjlim", Vtv, tVCrit);
        Vbcx     =  $limit(V(bi,cx), "pnjlim", Vtv, tVCrit);
        Vbep     =  $limit(V(bx,bp), "pnjlim", Vtv, tVCrit);
`else
        Vbei     =  V(bi,ei);
        Vbex     =  V(bx,ei);
        Vbci     =  V(bi,ci);
        Vbcx     =  V(bi,cx);
        Vbep     =  V(bx,bp);
`endif

        dv0 = -PEatT*FC;
        if (AJE<=0.0) begin
            dvh = Vbei+dv0;
            if (dvh>0.0) begin
                pwq = pow((1.0-FC),(-1.0-ME));
                qlo = PEatT*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-ME);
                qhi = dvh*(1.0-FC+0.5*ME*dvh/PEatT)*pwq;
            end else begin
                qlo = PEatT*(1.0-pow((1.0-Vbei/PEatT),(1.0-ME)))/(1.0-ME);
                qhi = 0.0;
            end
            qdbe = qlo+qhi;
        end else begin
            mv0 = sqrt(dv0*dv0+4*AJE*AJE);
            vl0 = -0.5*(dv0+mv0);
            q0 = -PEatT*pow((1.0-vl0/PEatT),(1.0-ME))/(1.0-ME);
            dv = Vbei+dv0;
            mv = sqrt(dv*dv+4*AJE*AJE);
            vl = 0.5*(dv-mv)-dv0;
            qlo = -PEatT*pow((1.0-vl/PEatT),(1.0-ME))/(1.0-ME);
            qdbe = qlo+pow((1.0-FC),(-ME))*(Vbei-vl+vl0)-q0;
        end
        dv0 = -PEatT*FC;
        if (AJE<=0.0) begin
            dvh = Vbex+dv0;
            if (dvh>0.0) begin
                pwq = pow((1.0-FC),(-1.0-ME));
                qlo = PEatT*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-ME);
                qhi = dvh*(1.0-FC+0.5*ME*dvh/PEatT)*pwq;
            end else begin
                qlo = PEatT*(1.0-pow((1.0-Vbex/PEatT),(1.0-ME)))/(1.0-ME);
                qhi = 0.0;
            end
            qdbex = qlo+qhi;
        end else begin
            mv0 = sqrt(dv0*dv0+4*AJE*AJE);
            vl0 = -0.5*(dv0+mv0);
            q0 = -PEatT*pow((1.0-vl0/PEatT),(1.0-ME))/(1.0-ME);
            dv = Vbex+dv0;
            mv = sqrt(dv*dv+4*AJE*AJE);
            vl = 0.5*(dv-mv)-dv0;
            qlo = -PEatT*pow((1.0-vl/PEatT),(1.0-ME))/(1.0-ME);
            qdbex = qlo+pow((1.0-FC),(-ME))*(Vbex-vl+vl0)-q0;
        end
        dv0 = -PCatT*FC;
        if (AJC<=0.0) begin
            dvh = Vbci+dv0;
            if (dvh>0.0) begin
                pwq = pow((1.0-FC),(-1.0-MC));
                qlo = PCatT*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-MC);
                qhi = dvh*(1.0-FC+0.5*MC*dvh/PCatT)*pwq;
            end else begin
                if ((VRT>0.0)&&(Vbci<-VRT)) begin
                    qlo = PCatT*(1.0-pow((1.0+VRT/PCatT),(1.0-MC))*(1.0-((1.0-MC)*(Vbci+VRT))/(PCatT+VRT)))/(1.0-MC);
                end else begin
                    qlo = PCatT*(1.0-pow((1.0-Vbci/PCatT),(1.0-MC)))/(1.0-MC);
                end
                qhi = 0.0;
            end
            qdbc = qlo+qhi;
        end else begin
            if ((VRT>0.0)&&(ART>0.0)) begin
                vn0 = (VRT+dv0)/(VRT-dv0);
                vnl0 = 2.0*vn0/(sqrt((vn0-1.0)*(vn0-1)+4*AJC*AJC)+sqrt((vn0+1.0)*(vn0+1)+4*ART*ART));
                vl0 = 0.5*(vnl0*(VRT-dv0)-VRT-dv0);
                qlo0 = PCatT*(1.0-pow((1.0-vl0/PCatT),(1.0-MC)))/(1.0-MC);
                vn = (2*Vbci+VRT+dv0)/(VRT-dv0);
                vnl = 2.0*vn/(sqrt((vn-1.0)*(vn-1)+4*AJC*AJC)+sqrt((vn+1.0)*(vn+1)+4*ART*ART));
                vl = 0.5*(vnl*(VRT-dv0)-VRT-dv0);
                qlo = PCatT*(1.0-pow((1.0-vl/PCatT),(1.0-MC)))/(1.0-MC);
                sel = 0.5*(vnl+1.0);
                crt = pow((1.0+VRT/PCatT),(-MC));
                cmx = pow((1.0+dv0/PCatT),(-MC));
                cl = (1.0-sel)*crt+sel*cmx;
                ql = (Vbci-vl+vl0)*cl;
                qdbc = ql+qlo-qlo0;
            end else begin
                mv0 = sqrt(dv0*dv0+4*AJC*AJC);
                vl0 = -0.5*(dv0+mv0);
                q0 = -PCatT*pow((1.0-vl0/PCatT),(1.0-MC))/(1.0-MC);
                dv = Vbci+dv0;
                mv = sqrt(dv*dv+4*AJC*AJC);
                vl = 0.5*(dv-mv)-dv0;
                qlo = -PCatT*pow((1.0-vl/PCatT),(1.0-MC))/(1.0-MC);
                qdbc = qlo+pow((1.0-FC),(-MC))*(Vbci-vl+vl0)-q0;
            end
        end
        dv0 = -PCatT*FC;
        if (AJC<=0.0) begin
            dvh = Vbep+dv0;
            if (dvh>0.0) begin
                pwq = pow((1.0-FC),(-1.0-MC));
                qlo = PCatT*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-MC);
                qhi = dvh*(1.0-FC+0.5*MC*dvh/PCatT)*pwq;
            end else begin
                if ((VRT>0.0)&&(Vbep<-VRT)) begin
                    qlo = PCatT*(1.0-pow((1.0+VRT/PCatT),(1.0-MC))*(1.0-((1.0-MC)*(Vbep+VRT))/(PCatT+VRT)))/(1.0-MC);
                end else begin
                    qlo = PCatT*(1.0-pow((1.0-Vbep/PCatT),(1.0-MC)))/(1.0-MC);
                end
                qhi = 0.0;
            end
            qdbep = qlo+qhi;
        end else begin
            if ((VRT>0.0)&&(ART>0.0)) begin
                vn0 = (VRT+dv0)/(VRT-dv0);
                vnl0 = 2.0*vn0/(sqrt((vn0-1.0)*(vn0-1)+4*AJC*AJC)+sqrt((vn0+1.0)*(vn0+1)+4*ART*ART));
                vl0 = 0.5*(vnl0*(VRT-dv0)-VRT-dv0);
                qlo0 = PCatT*(1.0-pow((1.0-vl0/PCatT),(1.0-MC)))/(1.0-MC);
                vn = (2*Vbep+VRT+dv0)/(VRT-dv0);
                vnl = 2.0*vn/(sqrt((vn-1.0)*(vn-1)+4*AJC*AJC)+sqrt((vn+1.0)*(vn+1)+4*ART*ART));
                vl = 0.5*(vnl*(VRT-dv0)-VRT-dv0);
                qlo = PCatT*(1.0-pow((1.0-vl/PCatT),(1.0-MC)))/(1.0-MC);
                sel = 0.5*(vnl+1.0);
                crt = pow((1.0+VRT/PCatT),(-MC));
                cmx = pow((1.0+dv0/PCatT),(-MC));
                cl = (1.0-sel)*crt+sel*cmx;
                ql = (Vbep-vl+vl0)*cl;
                qdbep = ql+qlo-qlo0;
            end else begin
                mv0 = sqrt(dv0*dv0+4*AJC*AJC);
                vl0 = -0.5*(dv0+mv0);
                q0 = -PCatT*pow((1.0-vl0/PCatT),(1.0-MC))/(1.0-MC);
                dv = Vbep+dv0;
                mv = sqrt(dv*dv+4*AJC*AJC);
                vl = 0.5*(dv-mv)-dv0;
                qlo = -PCatT*pow((1.0-vl/PCatT),(1.0-MC))/(1.0-MC);
                qdbep = qlo+pow((1.0-FC),(-MC))*(Vbep-vl+vl0)-q0;
            end
        end
        if (CJCP>0.0) begin
            dv0 = -PSatT*FC;
            if (AJS<=0.0) begin
                dvh = V(bcp)+dv0;
                if (dvh>0.0) begin
                    pwq = pow((1.0-FC),(-1.0-MS));
                    qlo = PSatT*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-MS);
                    qhi = dvh*(1.0-FC+0.5*MS*dvh/PSatT)*pwq;
                end else begin
                    qlo = PSatT*(1.0-pow((1.0-V(bcp)/PSatT),(1.0-MS)))/(1.0-MS);
                    qhi = 0.0;
                end
                qdbcp = qlo+qhi;
            end else begin
                mv0 = sqrt(dv0*dv0+4*AJS*AJS);
                vl0 = -0.5*(dv0+mv0);
                q0 = -PSatT*pow((1.0-vl0/PSatT),(1.0-MS))/(1.0-MS);
                dv = V(bcp)+dv0;
                mv = sqrt(dv*dv+4*AJS*AJS);
                vl = 0.5*(dv-mv)-dv0;
                qlo = -PSatT*pow((1.0-vl/PSatT),(1.0-MS))/(1.0-MS);
                qdbcp = qlo+pow((1.0-FC),(-MS))*(V(bcp)-vl+vl0)-q0;
            end
        end else begin
            qdbcp   =  0;
        end
        argi    =  Vbei/(NFatT*Vtv);
        expi    =  limexp(argi);
        Ifi =  ISatT*(expi-1.0);
        argi    =  Vbci/(NRatT*Vtv);
        expi    =  limexp(argi);
        Iri =  ISatT*ISRRatT*(expi-1.0);
        q1z =  1.0+qdbe*IVER+qdbc*IVEF;
        q1  =  0.5*(sqrt((q1z-1.0e-4)*(q1z-1.0e-4)+1.0e-8)+q1z-1.0e-4)+1.0e-4;
        q2  =  Ifi*IIKF+Iri*IIKR;
        if (QBM<0.5) begin
            qb  =  0.5*(q1+pow((pow(q1,1.0/NKF)+4.0*q2),NKF));
        end else begin
            qb  =  0.5*q1*(1.0+pow((1.0+4.0*q2),NKF));
        end
        Itzr    =  Iri/qb;
        Itzf    =  Ifi/qb;
        if (ISP>0.0) begin
            argi    =  Vbep/(NFP*Vtv);
            expi    =  limexp(argi);
            argx    =  Vbci/(NFP*Vtv);
            expx    =  limexp(argx);
            Ifp =  ISPatT*(WSP*expi+(1.0-WSP)*expx-1.0);
            q2p =  Ifp*IIKP;
            qbp =  0.5*(1.0+sqrt(1.0+4.0*q2p));     // assumes IKP>4*ISP if IKP>0
            argi    =  V(bcp)/(NFP*Vtv);
            expi    =  limexp(argi);
            Irp =  ISPatT*(expi-1.0);
            Iccp    =  (Ifp-Irp)/qbp;
        end else begin
            Ifp =  0.0;
            qbp =  1.0;
            Iccp    =  0.0;
        end

        if (WBE==1.0) begin
            argi    =  Vbei/(NEI*Vtv);
            expi    =  limexp(argi);
            argn    =  Vbei/(NEN*Vtv);
            expn    =  limexp(argn);
            if (VBBE>0.0) begin
                argx    =  (-VBBEatT-Vbei)/(NBBEatT*Vtv);
                expx    =  limexp(argx);
                Ibe =  IBEIatT*(expi-1.0)+IBENatT*(expn-1.0)-IBBE*(expx-EBBEatT);
            end else begin
                Ibe =  IBEIatT*(expi-1.0)+IBENatT*(expn-1.0);
            end
            Ibex    =  0.0;
        end else if (WBE==0.0) begin
            Ibe =  0.0;
            argi    =  Vbex/(NEI*Vtv);
            expi    =  limexp(argi);
            argn    =  Vbex/(NEN*Vtv);
            expn    =  limexp(argn);
            if (VBBE>0.0) begin
                argx    =  (-VBBEatT-Vbex)/(NBBEatT*Vtv);
                expx    =  limexp(argx);
                Ibex    =  IBEIatT*(expi-1.0)+IBENatT*(expn-1.0)-IBBE*(expx-EBBEatT);
            end else begin
                Ibex    =  IBEIatT*(expi-1.0)+IBENatT*(expn-1.0);
            end
        end else begin
            argi    =  Vbei/(NEI*Vtv);
            expi    =  limexp(argi);
            argn    =  Vbei/(NEN*Vtv);
            expn    =  limexp(argn);
            if (VBBE>0.0) begin
                argx    =  (-VBBEatT-Vbei)/(NBBEatT*Vtv);
                expx    =  limexp(argx);
                Ibe =  WBE*(IBEIatT*(expi-1.0)+IBENatT*(expn-1.0)-IBBE*(expx-EBBEatT));
            end else begin
                Ibe =  WBE*(IBEIatT*(expi-1.0)+IBENatT*(expn-1.0));
            end
            argi    =  Vbex/(NEI*Vtv);
            expi    =  limexp(argi);
            argn    =  Vbex/(NEN*Vtv);
            expn    =  limexp(argn);
            if (VBBE>0.0) begin
                argx    =  (-VBBEatT-Vbex)/(NBBEatT*Vtv);
                expx    =  limexp(argx);
                Ibex    =  (1.0-WBE)*(IBEIatT*(expi-1.0)+IBENatT*(expn-1.0)-IBBE*(expx-EBBEatT));
            end else begin
                Ibex    =  (1.0-WBE)*(IBEIatT*(expi-1.0)+IBENatT*(expn-1.0));
            end
        end
        argi    =  Vbci/(NCI*Vtv);
        expi    =  limexp(argi);
        argn    =  Vbci/(NCN*Vtv);
        expn    =  limexp(argn);
        Ibcj    =  IBCIatT*(expi-1.0)+IBCNatT*(expn-1.0);
        if ((IBEIP>0.0)||(IBENP>0.0)) begin
            argi    =  Vbep/(NCI*Vtv);
            expi    =  limexp(argi);
            argn    =  Vbep/(NCN*Vtv);
            expn    =  limexp(argn);
            Ibep    =  IBEIPatT*(expi-1.0)+IBENPatT*(expn-1.0);
        end else begin
            Ibep    =  0.0;
        end
        if (AVC1>0.0) begin
            vl = 0.5*(sqrt((PCatT-Vbci)*(PCatT-Vbci)+0.01)+(PCatT-Vbci));
            avalf = AVC1*vl*limexp(-AVC2atT*pow(vl,(MC-1.0)));
            Igc =  (Itzf-Itzr-Ibcj)*avalf;
        end else begin
            Igc =  0.0;
        end
        Ibc =  Ibcj-Igc;

        if (RCX>0.0) begin
            Ircx    =  V(rcx)/RCXatT;
        end else begin
            Ircx    =  0.0;
        end
        argi    =  Vbci/Vtv;
        expi    =  limexp(argi);
        argx    =  Vbcx/Vtv;
        expx    =  limexp(argx);
        Kbci    =  sqrt(1.0+GAMMatT*expi);
        Kbcx    =  sqrt(1.0+GAMMatT*expx);
        if (RCI>0.0) begin
            rKp1    =  (Kbci+1.0)/(Kbcx+1.0);
            Iohm    =  (V(rci)+Vtv*(Kbci-Kbcx-ln(rKp1)))/RCIatT;
            derf    =  IVO*RCIatT*Iohm/(1.0+0.5*IVO*IHRCF*sqrt(V(rci)*V(rci)+0.01));
            Irci    =  Iohm/sqrt(1+derf*derf);
        end else begin
            Irci    =  0.0;
        end
        if (RBX>0.0) begin
            Irbx    =  V(rbx)/RBXatT;
        end else begin
            Irbx    =  0.0;
        end
        if (RBI>0.0) begin
            Irbi    =  V(rbi)*qb/RBIatT;
        end else begin
            Irbi    =  0.0;
        end
        if (RE>0.0) begin
            Ire =  V(re)/REatT;
        end else begin
            Ire =  0.0;
        end
        if (RBP>0.0) begin
            Irbp    =  V(rbp)*qbp/RBPatT;
        end else begin
            Irbp    =  0.0;
        end
        if ((IBCIP>0.0)||(IBCNP>0.0)) begin
            argi    =  V(bcp)/(NCIP*Vtv);
            expi    =  limexp(argi);
            argn    =  V(bcp)/(NCNP*Vtv);
            expn    =  limexp(argn);
            Ibcp    =  IBCIPatT*(expi-1.0)+IBCNPatT*(expn-1.0);
        end else begin
            Ibcp    =  0.0;
        end
        if (RS>0.0) begin
            Irs =  V(rs)/RSatT;
        end else begin
            Irs =  0.0;
        end

        sgIf    =  Ifi>0.0?1.0:0.0;
        rIf =  Ifi*sgIf*IITF;
        mIf =  rIf/(rIf+1.0);
        tff =  TF*(1.0+QTF*q1)*(1.0+XTF*limexp(Vbci*IVTF/1.44)*(slTF+mIf*mIf)*sgIf);
        Qbe =  CJEatT*qdbe*WBE+tff*Ifi/qb;
        Qbex    =  CJEatT*qdbex*(1.0-WBE);
        Qbc =  CJCatT*qdbc+TR*Iri+QCO*Kbci;
        Qbcx    =  QCO*Kbcx;
        Qbep    =  CJEPatT*qdbep+TR*Ifp;
        Qbcp    =  CJCPatT*qdbcp+CCSO*V(bcp);
        Qbeo    =  V(be)*CBEO;
        Qbco    =  V(bc)*CBCO;

        Ith = -(Ibe*Vbei+Ibc*Vbci+(Itzf-Itzr)*V(cei)+Ibex*Vbex+Ibep*Vbep+Irs*V(rs)+Ibcp*V(bcp)+Iccp*V(cep)+Ircx*V(rcx)+Irci*V(rci)+Irbx*V(rbx)+Irbi*V(rbi)+Ire*V(re)+Irbp*V(rbp));
        if (RTH>0.0) begin
            Irth    =  V(rth)/RTH;
        end else begin
            Irth    =  0.0;
        end
        Qcth    =  V(rth)*CTH;

//
//      Branch contributions to VBIC model
//

        I(bei)  <+  Ibe;
        I(bex)  <+  Ibex;
        I(cei)  <+  Itzf;
        I(eci)  <+  Itzr;
        I(bci)  <+  Ibc;
        I(bep)  <+  Ibep;
        I(rcx)  <+  Ircx;
        I(rci)  <+  Irci;
        I(rbx)  <+  Irbx;
        I(rbi)  <+  Irbi;
        I(re)   <+  Ire;
        I(rbp)  <+  Irbp;
        I(bei)  <+  ddt(Qbe);
        I(bex)  <+  ddt(Qbex);
        I(bci)  <+  ddt(Qbc);
        I(bcx)  <+  ddt(Qbcx);
        I(bep)  <+  ddt(Qbep);
        I(be)   <+  ddt(Qbeo);
        I(bc)   <+  ddt(Qbco);
        I(bcp)  <+  Ibcp;
        I(cep)  <+  Iccp;
        I(rs)   <+  Irs;
        I(bcp)  <+  ddt(Qbcp);
        I(rth)  <+  Irth;
        I(ith)  <+  Ith;
        I(rth)  <+  ddt(Qcth);
    end
endmodule
