//VerilogA for laser,vcsel,veriloga
// DOI: 10.1109/JLT.2021.3064465

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

module vcsel(Vin,Vlam,Gnd,Opow,Ophase,Olam,Tout);
    parameter real Egart = 1.53 from (0:inf);
    parameter real dEga = -1.63e-3 from (-inf:inf);
    parameter real meA = 0.0622 from (0:inf);
    parameter real mhhA = 0.346 from (0:inf);
    parameter real tcap = 7.0e-12 from (0:inf);
    parameter real etaA = 1.6 from [0:inf);
    parameter real etaesc = 2.0 from [0:inf);
    parameter real A0A = 7.4e5 from (0:inf);
    parameter real Art = 0.45e9 from (-inf:inf);
    parameter real dA = 0 from (-inf:inf);
    parameter real d2A = 0 from (-inf:inf);
    parameter real Brt = 3.0e-16 from (-inf:inf);
    parameter real dB = -1.19e-18 from (-inf:inf);
    parameter real d2B = 5.74e-21 from (-inf:inf);
    parameter real Crt = -7.9e-42 from (-inf:inf);
    parameter real dC = 8.2e-44 from (-inf:inf);
    parameter real d2C = -5.4e-46 from (-inf:inf);

    parameter real Egbrt = 1.89 from (0:inf);
    parameter real dEgb = -4.5e-4 from (-inf:inf);
    parameter real meB = 0.0977 from (0:inf);
    parameter real mhhB = 0.596 from (0:inf);
    parameter real etainj = 0.8 from [0:1];
    parameter real tspb = 5.0e-9 from (0:inf);
    parameter real etaB = 1.0 from [0:inf);
    parameter real etaleak = 2.0 from [0:inf];
    parameter real A0B = 7.4e5 from (0:inf);
    parameter real Egcrt = 2.31 from (0:inf);
    parameter real dEgc = 4.94e-4 from (-inf:inf);

    parameter real a0rt = 7.54e5 from (0:inf);
    parameter real da0 = 8.22e2 from (-inf:inf);
    parameter real d2a0 = 2.66 from (-inf:inf);
    parameter real a1d = -1.4e13 from (-inf:inf);
    parameter real a1u = -1.34e13 from (-inf:inf);
    parameter real a2d = 1.57e20 from (-inf:inf);
    parameter real a2u = 2.03e21 from (-inf:inf);
    parameter real N0rt = 2.76e24 from (0:inf);
    parameter real dN0 = 9.22e21 from (-inf:inf);
    parameter real Ns = -1.5e21 from (-inf:inf);
    parameter real eps = 5.0e-24 from (0:1];
    parameter real lamgrt = 857.0e-9 from (0:inf);
    parameter real dlamg = 0.314e-9 from (-inf:inf);
    parameter real dlamgdna = -3.26e-33 from (-inf:inf);
    parameter real d2lamgdna = -5.44e-60 from (-inf:inf);

    // parameter real lamrt = 847.3e-9;
    parameter real dlam = 0.064e-9 from (-inf:inf);
    parameter real vg = 1e8 from (0:inf);
    parameter real gam = 3.28e-2 from (0:1];
    parameter real beta = 4.68e-2 from (0:1];
    parameter real alabsrt = 6.19e10 from (0:inf);
    parameter real dalabs = 0 from (-inf:inf);
    parameter real d2alabs = 7e6 from (-inf:inf);
    parameter real albmrt = 1.35e10 from (0:inf);
    parameter real dalbm = -1.5e8 from (-inf:inf);
    parameter real altmrt = 1.91e11 from (0:inf);
    parameter real daltm = -7e8 from (-inf:inf);

    parameter real tth = 1e-7 from (0:inf);
    parameter real rthrt = 2.8e3 from (0:inf);
    parameter real drth = 2.5 from (-inf:inf);

    parameter real nqw = 5 from (0:inf);
    parameter real dqw = 4e-9 from (0:inf);
    parameter real dsch = 74e-9 from (0:inf);
    parameter real Aape = 38.5e-12 from (0:inf);

    parameter real Lb = 0 from [0:inf);
    parameter real Rb = 0 from [0:inf);
    parameter real Lp1 = 76.0e-12 from [0:inf);
    parameter real Rp1 = 0 from [0:inf);
    parameter real Lp2 = 0 from [0:inf);
    parameter real Rp2 = 0 from [0:inf);
    parameter real Cp = 50.0e-15 from [0:inf);
    parameter real Rp3 = 150.0e-3 from [0:inf);
    parameter real rmrt = 170 from [0:inf);
    parameter real drm = -0.96 from (-inf:inf);
    parameter real d2rm = 1.38e-2 from (-inf:inf);
    parameter real d3rm = -1.11e-4 from (-inf:inf);
    parameter real etaRm1 = 0.285 from [0:1];
    parameter real etaRm2 = 0.125 from [0:1];
    parameter real etaRm3 = 0.590 from [0:1];
    parameter real Cm1 = 2.02e-15 from [0:inf);
    parameter real Cm2 = 19.5e-15 from [0:inf);
    parameter real Cm3 = 88.6e-15 from [0:inf);
    parameter real Cdep = 50.0e-15 from [0:inf);

    input Vin,Vlam;
    output Opow,Ophase,Olam,Tout;
    inout Gnd;
    thermal Tout;
    electrical Vin,Vlam,Gnd,Opow,Ophase,Olam;
    electrical Nscha,Nschb,Nph,NTem,NTru;
    electrical NLb,NLbp,NLp1,NLp,NLp2,NLp3,NLpm,NLm12,NLm23,NLsch;

    //cir1
    branch(Vin,NLb)     LLb;
    branch(NLb,NLbp)    RRb;
    branch(NLbp,NLp1)   LLp1;
    branch(NLp1,NLp)    RRp1;
    branch(NLp,NLp3)    CCp;
    branch(NLp3,Gnd)    RRp3;
    branch(NLp,NLp2)    LLp2;
    branch(NLp2,NLpm)   RRp2;
    branch(NLpm,NLm12)  CCm1,RRm1;
    branch(NLm12,NLm23) CCm2,RRm2;
    branch(NLm23,NLsch) CCm3,RRm3;
    branch(NLsch,Gnd)   CCdep,BUsch;

    //cir2
    branch(Gnd,Nschb)   BIinj,BIescb;
    branch(Nschb,Gnd)   BIspb,BIcapb,BIleak,CCb;

    //cir3
    branch(Gnd,Nscha)   BIcapa;
    branch(Nscha,Gnd)   BIspa1,BIspa2,BIspa3,BIesca,BIsta,CCa;

    //cir4
    branch(Gnd,Nph)     BIsts,BIsp;
    branch(Nph,Gnd)     BIabs,BIbm,BItm,CCs;

    //cir5
    branch(Gnd,NTem)    BIgen,CCt;
    branch(NTem,NTru)   RRth;
    branch(NTru,Gnd)    BUamb;

    real fa = 1;
    real fb = 1;
    real fs = 1;
    real ft = 1;

    real cop = 1;
    real midn;

    real k  = `P_K;
    real kev = 8.6173357e-5;
    real q  = `P_Q;
    real h  = `P_H;
    real hev = 4.135667e-15;
    real pi = `M_PI;
    real m0 = 9.109e-31;

    real Tamb = $temperature;
    real Trt = 273.15+25;
    real na,nb,S,Tem;
    real rm,Ega,Egb,Egc,A,B,C,a0,N0,lam,lamg,alabs,albm,altm,rth,a1,a2;
    real Va,Vb;
    real Nc,Nv,Efa,Efb;
    real Usch,g,ggen,Rm1,Rm2,Rm3;
    real Isch,Iinj,Iesc,Ileak,Ist,Isp;
    real Cb,Ca,Cs,Ct,RthR;
    real Popt;
    real Rspb,Rcap,Rabs,Rbm,Rtm,Rspa1,Ispa2,Ispa3;

    real Zdqw = dqw * cop;//1
    real Zdsch = dsch * cop;//1
    real ZA0B = A0B * pow(cop,-2);//-2
    real ZA0A = A0A * pow(cop,-2);//-2
    real ZBrt = Brt * pow(cop,3);//3
    real ZdB = dB * pow(cop,3);//3
    real Zd2B = d2B * pow(cop,3);//3
    real ZCrt = Crt * pow(cop,6);//6
    real ZdC = dC * pow(cop,6);//6
    real Zd2C = d2C * pow(cop,6);//6
    real Za0rt = a0rt * pow(cop,-1);//-1
    real Zda0 = da0 * pow(cop,-1);//-1
    real Zd2a0 = d2a0 * pow(cop,-1);//-1
    real Za1,Za2;//-2,-3
    real ZN0rt = N0rt * pow(cop,-3);//-3
    real ZdN0 = dN0 * pow(cop,-3);//-3
    real ZNs = Ns * pow(cop,-3);//-3
    real Zeps = eps * pow(cop,3);//3
    real Zlamgrt = lamgrt * cop;//1
    real Zdlamg = dlamg * cop;//1
    real Zdlamgdna = dlamgdna * pow(cop,4);//4
    real Zd2lamgdna = d2lamgdna * pow(cop,7);//7
    real Zlamrt;// = lamrt * cop;//1
    real Zdlam = dlam * cop;//1
    real Zvg = vg * cop;//1
    real Zm0 = m0 * pow(cop,-2);//-2
    real ZVa,ZVb;//3
    real ZPc = `P_C * cop;//1

    real Mefa11,Mefa12,Mefa13,Mefa21,Mefa22,Mefa23;
    real Mefb11,Mefb12,Mefb13,Mefb14,Mefb15,Mefb16,Mefb17,Mefb18,Mefb1,Mefb21,Mefb22,Mefb23,Mefb24,Mefb25,Mefb26,Mefb27,Mefb28,Mefb2;
    real Mg1,Mg2,Mg3,Mg4,Mg5,Mg6;
    real Mesc1,Mesc2,Mesc3;
    real Mleak1,Mleak2,Mleak3;

    analog initial begin
        Va = dqw * nqw * Aape; //(6)
        Vb = dsch * Aape; //(7)

        ZVa = Va * pow(cop,3);//3
        ZVb = Vb * pow(cop,3);//3

        Rspb = fb / q * tspb; //(11)
        Rcap = fb / q * tcap; //(12)
        Ca = q / fa; //(25)
        Cb = q / fb; //(26)

        midn = 2 * pi * Zm0 * k / pow(h,2);
        Tem=Tamb;
    end

    analog begin
        Zlamrt = V(Vlam) * cop;//1

        na  = abs(V(Nscha)) / fa;
        nb  = abs(V(Nschb)) / fb;
        S   = abs(V(Nph)) / fs;
        Tem = abs(V(NTem)) / ft;

        rm = rmrt + drm * (Tem - Trt) + 0.5 * d2rm * pow((Tem - Trt),2) + 1.0 / 6.0 * d3rm * pow((Tem - Trt),3); //(47)
        Ega = (Egart + dEga * (Tem - Trt)); //(48)
        Egb = (Egbrt + dEgb * (Tem - Trt)); //(49)
        Egc = (Egcrt + dEgc * (Tem - Trt)); //(50)
        A = Art + dA * (Tem - Trt); //(51)
        B = ZBrt + ZdB * (Tem - Trt) + 0.5 * Zd2B * pow((Tem - Trt),2); //(52)
        C = ZCrt + ZdC * (Tem - Trt) + 0.5 * Zd2C * pow((Tem - Trt),2); //(53)
        a0 = Za0rt + Zda0 * (Tem - Trt) + 0.5 * Zd2a0 * pow((Tem - Trt),2); //(54)
        N0 = ZN0rt + ZdN0 * (Tem - Trt); //(55)
        lam = Zlamrt + Zdlam * (Tem - Trt); //(56)
        lamg = Zlamgrt + Zdlamg * (Tem - Trt) + Zdlamgdna * (na / ZVa) + 0.5 * Zd2lamgdna * pow((na / ZVa),2); //(57)
        alabs = alabsrt + dalabs * (Tem - Trt) + 0.5 * d2alabs * pow((Tem - Trt),2); //(58)
        albm = albmrt + dalbm * (Tem - Trt); //(59)
        altm = altmrt + daltm * (Tem - Trt); //(60)
        rth = rthrt + drth * (Tem - Trt); //(61)
        if (lam > lamg) begin
            a1 = a1u;
            a2 = a2u;
        end
        else begin
            a1 = a1d;
            a2 = a2d;
        end

        Za1 = a1 * pow(cop,-2);//-2
        Za2 = a2 * pow(cop,-3);//-3

        Nc = 2.0 * abs(midn * meB * Tem)**(3.0/2.0); //(4)
        Nv = 2.0 * abs(midn * mhhB * Tem )**(3.0/2.0); //(5)

        Mefa11 = Zdqw * na / ZVa;
        Mefa12 = 2.0 * midn * Tem * meA;
        Mefa13 = kev * Tem * ln(limexp(Mefa11 / Mefa12) - 1.0);
        Mefa21 = Zdqw * na / ZVa;
        Mefa22 = 2.0 * midn * Tem * mhhA;
        Mefa23 = kev * Tem * ln(limexp(Mefa21 / Mefa22) - 1.0);
        Efa = Ega + etaA * (Mefa13 + Mefa23); //(2)

        Mefb11 = nb / ZVb / Nc;
        Mefb12 = 1.0 - pow(Mefb11,2);
        Mefb13 = ln(Mefb11) / Mefb12;
        Mefb14 = 3.0 * sqrt(pi) * nb / ZVb / 4.0 / Nc;
        Mefb15 = Mefb14**(2.0/3.0);
        Mefb16 = 0.24 + 1.08 * Mefb15;
        Mefb17 = 1.0 + pow(Mefb16,-2);
        Mefb18 = Mefb15 / Mefb17;
        Mefb1 = Mefb13 + Mefb18;
        Mefb21 = nb / ZVb / Nv;
        Mefb22 = 1.0 - pow(Mefb21,2);
        Mefb23 = ln(Mefb21) / Mefb22;
        Mefb24 = 3.0 * sqrt(pi) * nb / ZVb / 4.0 / Nv;
        Mefb25 = Mefb24**(2.0/3.0);
        Mefb26 = 0.24 + 1.08 * Mefb25;
        Mefb27 = 1.0 + pow(Mefb26,-2);
        Mefb28 = Mefb25 / Mefb27;
        Mefb2 = Mefb23 + Mefb28;
        Efb = Egb + etaB * kev * Tem * (Mefb1 + Mefb2); //(3)

        Mg1 = (na / ZVa + ZNs)/(N0 + ZNs);
        Mg2 = a0 * ln(Mg1);
        Mg3 = Za1 * (lam - lamg);
        Mg4 = Za2 * pow((lam - lamg),2);
        Mg5 = 1.0 + Zeps * S * gam / ZVa;
        Mg6 = Mg2 - Mg3 - Mg4;
        g = Mg6 / Mg5; //(17)
        if (g < 0) begin
            g = 0;
        end
        // etas = hev * ZPc / lam; //(39)
        Popt = hev * ZPc / lam * I(BItm); //(32)
        ggen = V(Vin,Gnd) * I(LLb) - Popt; //(41)
        Rm1 = rm * etaRm1;
        Rm2 = rm * etaRm2;
        Rm3 = rm * etaRm3;
        RthR = rth * ft; //(45)
        Cs = q / fs; //(38)
        Ct = tth / rth / ft; //(44)
        Iinj = etainj * Isch; //(10)

        Mesc1 = ZA0A * ZVa * pow(Tem,2) / (Zdqw * nqw);
        Mesc2 = limexp(-Egb / (etaesc * kev * Tem));
        Mesc3 = limexp(Efa / (etaesc * kev * Tem));
        Iesc = Mesc1 * Mesc2 * (Mesc3 - 1); //(13)
        Mleak1 = ZA0B * ZVb * pow(Tem,2) / Zdsch;
        Mleak2 = limexp(-Egc / (etaleak * kev * Tem));
        Mleak3 = limexp(Efb / (etaleak * kev * Tem));
        Ileak = Mleak1 * Mleak2 * (Mleak3 - 1); //(14)
        Rspa1 = fa / (q * A); //(15)
        Ispa2 = B * pow(na,2) / ZVa * q; //(15)
        Ispa3 = C * pow(na,3) / pow(ZVa,2) * q; //(15)
        Ist = gam * Zvg * g * S * q; //(16)

        Isp = q * beta * B * pow(na,2) / ZVa; //(28)
        Rabs = fs / (q * alabs); //(29)
        Rbm = fs / (q * albm); //(30)
        Rtm = fs / (q * altm); //(31)

        Isch = I(BUsch);
        Usch = (na * Efa + nb * Efb)/((na + nb)); //(1)

        //cir1
        V(LLb)    <+ Lb   * ddt(I(LLb));
        V(RRb)    <+ Rb   * I(RRb);
        V(LLp1)   <+ Lp1  * ddt(I(LLp1));
        V(RRp1)   <+ Rp1  * I(RRp1);
        I(CCp)    <+ Cp   * ddt(V(CCp));
        V(RRp3)   <+ Rp3  * I(RRp3);
        V(LLp2)   <+ Lp2  * ddt(I(LLp2));
        V(RRp2)   <+ Rp2  * I(RRp2);
        I(CCm1)   <+ Cm1  * ddt(V(CCm1));
        V(RRm1)   <+ Rm1  * I(RRm1);
        I(CCm2)   <+ Cm2  * ddt(V(CCm2));
        V(RRm2)   <+ Rm2  * I(RRm2);
        I(CCm3)   <+ Cm3  * ddt(V(CCm3));
        V(RRm3)   <+ Rm3  * I(RRm3);
        I(CCdep)  <+ Cdep * ddt(V(CCdep));
        V(BUsch)  <+ Usch;

        //cir2
        I(BIinj)  <+ Iinj; //(18)
        I(BIescb) <+ Iesc; //(21)
        V(BIspb)  <+ Rspb * I(BIspb); //(19)
        V(BIcapb) <+ Rcap * I(BIcapb); //(20)
        I(BIleak) <+ Ileak; //(22)
        I(CCb)    <+ Cb * ddt(V(CCb));

        //cir3
        I(BIcapa) <+ I(BIcapb); //(20)
        I(CCa)    <+ Ca * ddt(V(CCa));
        V(BIspa1) <+ Rspa1 * I(BIspa1); //(23)
        I(BIspa2) <+ Ispa2; //(23)
        I(BIspa3) <+ Ispa3; //(23)
        I(BIesca) <+ Iesc; //(21)
        I(BIsta)  <+ Ist; //(24)

        //cir4
        I(BIsts)  <+ Ist; //(33)
        I(BIsp)   <+ Isp; //(34)
        I(CCs)    <+ Cs   * ddt(V(CCs));
        V(BIabs)  <+ Rabs * I(BIabs); //(35)
        V(BIbm)   <+ Rbm  * I(BIbm);//(36)
        V(BItm)   <+ Rtm  * I(BItm); //(37)

        //cir5
        I(BIgen)  <+ ggen; //(43)
        I(CCt)    <+ Ct * ddt(V(CCt));
        V(RRth)   <+ RthR * I(RRth);
        V(BUamb)  <+ Tamb * ft; //(46)

        //Light output
        V(Opow)   <+ Popt;
        V(Ophase) <+ 0;
        V(Olam)   <+ lam / cop;

        //Temperature output
        Temp(Tout)   <+ Tem - 273.15;
    end

endmodule