// SPICE Gummel-Poon bipolar transistor model: A Verilog-A Description of SPICE3f5
// 3-node version, substrate capacitance connected to the external emitter node.
// simulator specific physical constants selectable by compiler flag
// Zero resistance protection and node collapse are performed by specifying MIN_R=1e-3
// ptf=0 implies no NQS, otherwise 2nd order Bessel in TR and AC since ADMS does not recognize absdelay()
// ADMS does not recognize "parameter string tye..." thus bjtn, (bjtp) is used by the "type" variable
// no limitation is adopted for Vj<-5*Vt as opposed to some SPICE versions
// fc=0 assumed for Qjs in SPICE is not adopted.
// modify `QJ(Qjs,cjs_t,Vcie,vjs_t,mjs,fc); => `QJ(Qjs,cjs_t,Vcie,vjs_t,mjs,0); if to adopt SPICE fc=0
// retain or comment (//) model parameter temp in compliance to the simulator used

/* ****** 24-06-2021, update to SGP-CEDIC v1.0 ********************************
(XJ)
Add node s:
            br_sc: ccsp: perimeter collector-substrate junction capacitance;
            br_sci: cjs intenal collector-substrate junction capacitance;
                    Isc: collector-substrate diode current
 */
/* ****** 20-06-2021, update to SGP-CEDIC v1.0 ********************************
 Below are the correction by XJ (xiaodi.jin@tu-dresden.com)
 Add constant.h and disciplines for spectre;
 Module of TEMPCJ changed to TEMPCJ_spectre, because the calculation of Vj need eg_ref and eg_t;
 Equations of eg_ref and eg_t are added;
 QJ module ad for qhi:  qhi = dvh*(1.0-FC+0.5*mj*dvh/vj)*pwq; => qhi = dvh*(1.0-FC*(1+mj)+0.5*mj*dvh/vj)*pwq; The VBIC code has the same issue;
 Qdc is modified: Qdc = tr*Itr; => Qdc = tr*Ibwd; where Itr=Ibwd*iKqb;
 Add T dependence for resistance re, rb, rbm, rc with 2nd-order polynomial equation, as well as each two T coefficients, al1 and al2;
 Replace Rb by rb in the if case, because only parameter rather than variables can be used in the if case;
 Add variable defination of macro;
 Uniform the naming of variables;
 */

`ifdef insideADMS
 `define MODEL @(initial_model)
 `define NOISE
 `define ATTR(txt) (*txt*)
`else
 `define MODEL
 `define NOISE
 `define ATTR(txt)
`endif

//select simulator specific physical constants
//`define PHYSC_VBIC    //VBIC
`define PHYSC_SPECTRE //SPICE3F5, SPICE2G6, ELDO, SPECTRE
//`define PHYSC_AMS_231   //NIST1998, Verilog-A, QUCS, QucsStudio
`ifdef PHYSC_VBIC
  `define	KB  1.380662e-23  // Boltzmann constant (J/K)
  `define	QQ  1.602189E-19  // mag. of electronic charge (C)
`else
`ifdef PHYSC_SPECTRE
  `define	KB  1.3806226e-23 // Boltzmann constant (J/K)
  `define	QQ  1.6021918e-19 // mag. of electronic charge (C)
`else
`ifdef PHYSC_AMS_231  //NIST1998
  `define	KB  1.3806503e-23 // Boltzmann constant (J/K)
  `define	QQ  1.6021765e-19 // mag. of electronic charge (C)
`endif
`endif
`endif

//comment this line if not to specify "type" as model parameter and set npn/pnp by assigning Type internally
`define TYPE_MP
`ifdef TYPE_MP
  `define Type  type
`else
  `define Type  1
`endif
//alternatively check if compiler supports this command
//`define Type  $simparam("type",1)

//comment this line if not to specify "temp" as model parameter
//`define TEMP_MP

//comment this line for a bias dependent excess phase using "tff" instead of "tf"
`define NQS_TF

`define Dexp_lim  80.0
`define TMAX      326.85
`define TMIN      -100.0
`define MIN_R     0.001
`define egta      7.0200e-04
`define egtb      1.1080e+03
`define Gmin      $simparam("gmin",1e-12)  //suggested by L.L

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

// -->2021.06.20(XJ) Add
//spectre
`include "constants.h"
`include "discipline.h"
//================ begin macros ====================

// -->2021.06.20(XJ) Mod: for qhi:FC->FC*(1-mj)
// Junction charge calculation (simplified VBIC)
// Piecewise function by the threshold voltage FC*vj. For V<FC*vj, cj inscreases with V, and charge consists of qlo; For V>FC*vj, cj is constant, and charge consists of qlo and qhi.
// Important for BE and BC junction
// INPUT:
//  cj0		: zero-bias capacitance
//  vj	  : built-in voltage
//  mj 		: exponent coefficient
//  FC		: coefficient for forward-bias depletion capacitance formula, and FC*vj is defined as the threshold voltage, larger which is cap is relative constant.
//  V	    : voltage across junction
// IMPLICIT INPUT:
//  no
// OUTPUT:
//  qjj	: depletion charge
//`define QJ(qjj,cj0,V,vj,mj,FC) \
  //dv0   = -vj*FC; \
	//dvh =  V+dv0; \
	//if (dvh>0.0) begin \
	  //pwq = pow((1.0-FC),(-1.0-mj)); \
	  //qlo = vj*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-mj); \
	  //qhi = dvh*(1.0-FC*(1+mj)+0.5*mj*dvh/vj)*pwq; \
	//end else begin \
	  //qlo = vj*(1.0-pow((1.0-V/vj),(1.0-mj)))/(1.0-mj); \
	  //qhi = 0.0; \
	//end \
	//qjj = cj0*(qlo+qhi);
`define QJ(qjj,cj0,V,P,M,FC) \
    dv0   = -P*FC; \
	dvh =  V+dv0; \
	if (dvh>0.0) begin \
	  pwq = pow((1.0-FC),(-1.0-M)); \
	  qlo = P*(1.0-pwq*(1.0-FC)*(1.0-FC))/(1.0-M); \
	  qhi = dvh*(1.0-FC+0.5*M*dvh/P)*pwq; \
	end else begin \
	  qlo = P*(1.0-pow((1.0-V/P),(1.0-M)))/(1.0-M); \
	  qhi = 0.0; \
	end \
	qjj = cj0*(qlo+qhi);

// diode current with limitation (simplified Hicum)
// INPUT:
//  isat    : saturation currents (model parameter related)
//  nn      : ideality factor
//  V       : branch voltage
// IMPLICIT INPUT:
//  Vt          : thermal voltage
// OUTPUT:
//  id          : diode current
`define IDIO(isat,nn,V,id)\
  arg     = V/(nn*Vt);\
  if (isat > 0.0) begin\
    if (arg > `Dexp_lim) begin\
      le    = (1.0 + (arg - `Dexp_lim));\
      arg   = `Dexp_lim;\
    end else begin\
      le    = 1.0;\
    end\
    le      = le*exp(arg);\
    id      = isat*(le-1.0);\
  end else begin\
    id      = 0.0;\
  end

// -->2021.06.20(XJ) Add
// Temperature update of junction capacitance parameters
// INPUT:
//  cj0		: zero-bias capacitance at Tnorm
//  vj  	: built-in voltage at Tnom
//  mj 		: junction exponential factor
//  eg_ref: bandgap voltage at Tnom
//  eg_t  : bandgap voltage at Tdev
// IMPLICIT INPUT:
//  no
// OUTPUT:
//  cj0_t		: zero-bias capacitance at Tdev
//  vj  	  : built-in voltage at Tdev
`define TEMPCJ_spectre(cj0,vj,mj,eg_ref, eg_t,cj0_t,vj_t)\
  vj_t  = vj*rT-3.0*Vt*lnrT-rT*eg_ref+eg_t;\
  cj0_t  = cj0*(1+mj*(4.0e-4*dT+1-vj_t/vj));
    //vj_t  = vj*rT-3.0*Vt*lnrT+rT*eg_ref-eg_t;\
  //MM: change signs last term

// Temperature update of junction capacitance parameters
`define TEMPCJ(cj0,vj,mj,egnom,cj0_t,vj_t)\
  egj   = 1.16-`egta*Tdev*Tdev/(`egtb+Tdev);\
  tvj   = -3.0*Vt*lnrT-rT*egnom+egj;\
  vj_t  = vj*rT+tvj;\
  cj0_t  = cj0*(1+mj*(4.0e-4*dT+1-vj_t/vj));


//================ end macros ====================

module bjtn(c,b,e,s);

//Node definitions

inout       c,b,e,s;
electrical  c,b,e,s,ci,bi,ei;
electrical  xf1,xf2;  //Bessel type output NQS

//Branch definitions
branch    (b,bi)    br_bbi;
branch    (e,ei)    br_eei;
branch    (c,ci)    br_cci;
branch    (ci,e)    br_cie;
branch    (ci,ei)   br_ciei;
branch    (bi,ei)   br_biei;
branch    (bi,ci)   br_bici;
branch    (b,ci)    br_bci;
branch    (b,e)     br_be;

branch    (s,c)      br_sc;
branch    (s,ci)     br_sci;
//Bessel type output NQS network
branch		(xf1 )		br_xf1;
branch		(xf2 )		br_xf2;

//  Model Parameters
parameter real    is   = 1.0000e-16 from [0.0:1.0]  `ATTR(info="transport saturation current" unit="A");
parameter real    bf   = 1.0000e+02 from [0.0:inf)  `ATTR(info="ideal maximum forward beta");
parameter real    nf   = 1.0000e+00 from (0.0:10.0] `ATTR(info="forward current emission coefficient");
parameter real    vaf  = 0.0000e+00 from [0.0:inf)  `ATTR(info="forward Early voltage" unit="V"); //`0' signifies infinity
parameter real    ikf  = 0.0000e+00 from [0.0:1.0]  `ATTR(info="corner for forward beta high current roll-off" unit="A"); //`0' signifies infinity
parameter real    ise  = 0.0000e+00 from [0.0:1.0]  `ATTR(info="B-E leakage saturation current" unit="A");
parameter real    ne   = 1.5000e+00 from (0.0:10.0] `ATTR(info="B-E leakage emission coefficient");
parameter real    br   = 1.0000e+00 from [0.0:inf)  `ATTR(info="ideal maximum reverse beta");
parameter real    nr   = 1.0000e+00 from (0.0:10.0] `ATTR(info="reverse current emission coefficient");
parameter real    var  = 0.0000e+00 from (0.0:inf)  `ATTR(info="reverse Early voltage" unit="V"); //`0' signifies infinity
parameter real    ikr  = 0.0000e+00 from [0.0:1.0]  `ATTR(info="corner for reverse beta high current roll-off" unit="A"); //`0' signifies infinity
parameter real    isc  = 0.0000e+00 from [0.0:1.0]  `ATTR(info="B-C leakage saturation current" unit="A");
parameter real    nc   = 2.0000e+00 from (0.0:10.0] `ATTR(info="B-C leakage emission coefficient");
parameter real    rb   = 0.0000e+00 from [0:inf]    `ATTR(info="zero-bias base resistance" unit="Ohm");
parameter real    irb  = 0          from [0.0:1.0]  `ATTR(info="current where base resistance falls halfway to its min value" unit="A");
parameter real    rbm  = 0.0000e+00 from [0:inf]    `ATTR(info="minimum base resistance at high currents" unit="Ohm");
parameter real    re   = 0.0000e+00 from [0:inf]    `ATTR(info="emitter resistance" unit="Ohm");
parameter real    rc   = 0.0000e+00 from [0:inf]    `ATTR(info="collector resistance" unit="Ohm");
parameter real    cje  = 0.0000e+00 from [0.0:inf)  `ATTR(info="B-E zero-bias depletion capacitance" unit="F");
parameter real    vje  = 7.5000e-01 from [0.0:inf)  `ATTR(info="B-E built-in potential" unit="V");
parameter real    mje  = 3.3000e-01 from (0.0:1.0]  `ATTR(info="B-E junction exponential factor");
parameter real    tf   = 0.0000e+00 from [0.0:inf)  `ATTR(info="ideal forward transit time" unit="s");
parameter real    xtf  = 0.0000e+00 from [0.0:inf)  `ATTR(info="coefficient for bias dependence of tf");
parameter real    vtf  = 0.0000e+00 from [0.0:inf)  `ATTR(info="voltage describing VBC dependence of tf" unit="V");
parameter real    itf  = 0.0000e+00 from [0.0:inf)  `ATTR(info="high-current parameter for effect on tf" unit="A");
parameter real    ptf  = 0.0000e+00 from [0.0:inf)  `ATTR(info="excess phase at freq=1.0/(tf*2pi) Hz" unit="deg");
parameter real    cjc  = 0.0000e+00 from [0.0:inf)  `ATTR(info="B-C zero-bias depletion capacitance" unit="F");
parameter real    vjc  = 7.5000e-01 from [0.0:inf)  `ATTR(info="B-C built-in potential" unit="V");
parameter real    mjc  = 3.3000e-01 from (0.0:1.0]  `ATTR(info="B-C junction exponential factor");
parameter real    xcjc = 1.0000e+00 from [0.0:1.0]  `ATTR(info="fraction of B-C depletion capacitance connected to internal base node");
parameter real    tr   = 0.0000e+00 from [0.0:inf)  `ATTR(info="ideal reverse transit time" unit="s");
parameter real    cjs  = 0.0000e+00 from [0.0:inf)  `ATTR(info="zero-bias collector-substrate capacitance" unit="F");
parameter real    vjs  = 7.5000e-01 from [0.0:inf)  `ATTR(info="substrate junction built-in potential" unit="V");
parameter real    mjs  = 0.0000e+00 from (0.0:10.0]  `ATTR(info="substrate junction exponential factor");
parameter real    xtb  = 0.0000e+00 from [0.0:10.0) `ATTR(info="forward and reverse beta temperature exponent");
parameter real    eg   = 1.1100e+00 from [0.0:10.0] `ATTR(info="energy gap for temperature effect on is" unit="eV");
parameter real    xti  = 3.0000e+00 from [0.0:10.0) `ATTR(info="temperature exponent for effect on is");
parameter real    kf   = 0.0000e+00 from [0.0:inf]  `ATTR(info="flicker-noise coefficient");
parameter real    af   = 1.0000e+00 from [0.0:10.0] `ATTR(info="flicker-noise exponent");
parameter real    fc   = 5.0000e-01 from [0.0:1.0)  `ATTR(info="coefficient for forward-bias depletion capacitance formula");
parameter real    tnom = 2.7000e+01                 `ATTR(info="temperature at which parameters were extracted" unit="C");
// -->2021.06.20(XJ) Add
//Temperature dependence of resistance
//MM: naming was wrong, added tikf, tbf, tf
parameter real    ttf1 = 0                 `ATTR(info="Linear temperature coefficient for the emitter resistor" unit="1/C");
parameter real    ttf2 = 0                 `ATTR(info="Quadratic temperature coefficient for the emitter resistor" unit="1/C");
parameter real    tbf1 = 0                 `ATTR(info="Linear temperature coefficient for the emitter resistor" unit="1/C");
parameter real    tbf2 = 0                 `ATTR(info="Quadratic temperature coefficient for the emitter resistor" unit="1/C");
parameter real    tikf1 = 0                 `ATTR(info="Linear temperature coefficient for the emitter resistor" unit="1/C");
parameter real    tikf2 = 0                 `ATTR(info="Quadratic temperature coefficient for the emitter resistor" unit="1/C");
parameter real    tre1 = 0                 `ATTR(info="Linear temperature coefficient for the emitter resistor" unit="1/C");
parameter real    tre2 = 0                 `ATTR(info="Quadratic temperature coefficient for the emitter resistor" unit="1/C");
parameter real    trc1 = 0                 `ATTR(info="Linear temperature coefficient for the collector resistor" unit="1/C");
parameter real    trc2 = 0                 `ATTR(info="Quadratic temperature coefficient for the collector resistor" unit="1/C");
parameter real    trb1 = 0                 `ATTR(info="Linear temperature coefficient for the base resistor" unit="1/C");
parameter real    trb2 = 0                 `ATTR(info="Quadratic temperature coefficient for the base resistor" unit="1/C");
parameter real    trm1 = 0                 `ATTR(info="Linear temperature coefficient for the minimum base resistor" unit="1/C");
parameter real    trm2 = 0                 `ATTR(info="Quadratic temperature coefficient for the minimum base resistor" unit="1/C");
parameter real    trs1 = 0                 `ATTR(info="Linear temperature coefficient for the substrate resistor" unit="1/C");
parameter real    trs2 = 0                 `ATTR(info="Quadratic temperature coefficient for the substrate resistor" unit="1/C");
parameter real    ccsp    = 0.0           from [0:inf)    `ATTR(info="Perimeter C-S zero-bias depletion capacitance" unit="F");
parameter real    ns   = 1.5000e+00       from (0.0:10.0] `ATTR(info="Substrate leakage emission coefficient");
parameter real    iss  = 0.0000e+00 from [0.0:1.0]  `ATTR(info="Substrate leakage saturation current" unit="A");
// -->2021.06.20(MM) Add
//Parasitic caps
parameter real    cbcp  = 0.0000e+00 from [0.0:inf)  `ATTR(info="B-E isolation cap" unit="F");
parameter real    cbep  = 0.0000e+00 from [0.0:inf)  `ATTR(info="B-C isolation cap" unit="F");
`ifdef TYPE_MP
  parameter integer type = 1        from [-1:1] exclude 0  `ATTR(info="For transistor type NPN(+1) or PNP (-1)");
`endif
`ifdef TEMP_MP
  parameter real  temp = 2.7000e+01                 `ATTR(info="ambient temperature in C" unit="C");
`endif

//Macros
//IDIO
real arg,le;
//TEMPCJ
real tvj,egj;
//QJ
real dv0,dvh,pwq,qlo,qhi;
//Model
real ttype,Tdev,Tnom,tj,dT,lnrT,Vt;
real bf_t,br_t,tbeta;
real is_t,ise_t,isc_t;
real cje_t;
real cjs_t;
real ikf_t;
real tf_t;
real ccsp_t;
real vje_t,vjc_t,vjs_t;
real ifwd,ibe2,ibwd,ibc2,Ib,iKq1,Kq2,iKqb,Itzf,Itr;
real itdep,Qde,Qdc,Qjs,Qje,qjcx,Qjcx,qjci,Qjci;
real opipi,hib,z1,zed,tanz,ftan;
real TD,Qxf1,Qxf2,Itxf1,Itxf2,t0;
real ovaf,ovar,oikf,oikr,argt,fourkt,twoq,flicker_Pwr;
real Vbbi,Veei,Vcci,Vcie,Vciei,Vbiei,Vbici,Vbci;
// -->2021.06.20(XJ) Add
// T depdence of resistance
real rb_t,rbm_t;
real Qcsp;
real Vsc, Vsci;
real iss_t, Isc, isfwd;
real qbe, qbc;
// T dependence of bandgap voltage
real eg_t, eg_ref;

// for output of ft
real GMi, gPIi, gPIx;
real BETAAC;
real CdEi_ddx, CdCi_ddx, CjEi_ddx, CjCi_ddx, CdS_ddx;
real CMUi, CMUx, CPIi, CPIx;
real ft;

(*retrieve*) real re_t;
(*retrieve*) real cjc_t;
(*retrieve*) real rT;
(*retrieve*) real rc_t;
(*retrieve=ifwd*) real Rb;
(*retrieve*) real Ibe;
(*retrieve*) real Ibc;
(*retrieve*) real tff;
(*retrieve*) real Qje_Vbe;
(*retrieve*) real Qjci_Vbc;
(*retrieve*) real Qjcx_Vbc;
(*retrieve*) real Itxf;

analog begin

`MODEL begin : Model_initialization

//	Temperature mappings (code independent of bias)

  Tdev  = $temperature;
  Tnom	= tnom+`P_CELSIUS0;
  Vt    = `KB*Tdev/`QQ;
  rT    = Tdev/Tnom;
  lnrT  = ln(rT);
  dT    = Tdev-Tnom;

  tbeta = exp(xtb*lnrT);
  if (tbf1 ==  0) begin
    bf_t  = bf*tbeta;
  end else begin
    bf_t  = bf*(1+tbf1*dT+tbf2*dT*dT);
  end

  br_t  = br*tbeta;
  // -->2021.06.20(XJ) Add
  eg_t     = eg -`egta*Tdev*Tdev/(`egtb+Tdev);
  eg_ref   = eg -`egta*Tnom*Tnom/(`egtb+Tnom);

  if (vaf ==  0) begin
    ovaf  = 0;
  end else begin
    ovaf  = 1/vaf;
  end
  if (var ==  0) begin
    ovar  = 0;
  end else begin
    ovar  = 1/var;
  end


  tf_t = tf*(1+ttf1*dT+ttf2*dT*dT);

  ikf_t = ikf*(1+tikf1*dT+tikf2*dT*dT);
  if (ikf ==  0) begin
    oikf  = 0;
  end else begin
    oikf  = 1/ikf_t;
  end
  if (ikr ==  0) begin
    oikr  = 0;
  end else begin
    oikr  = 1/ikr;
  end

  argt  = xti*lnrT+eg*(rT-1)/Vt;
  is_t	= is*exp(argt);
  ise_t	= ise*exp(argt/ne)/tbeta;
  isc_t	= isc*exp(argt/nc)/tbeta;
  // -->2021.06.20(XJ) Add
  iss_t	= iss*exp(argt/ns)/tbeta;
  // -->2021.06.20(XJ) Add
  `TEMPCJ_spectre(cje,vje,mje,eg_ref,eg_t,cje_t,vje_t)
  `TEMPCJ_spectre(cjc,vjc,mjc,eg_ref,eg_t,cjc_t,vjc_t)
  `TEMPCJ_spectre(cjs,vjs,mjs,eg_ref,eg_t,cjs_t,vjs_t)
  `TEMPCJ_spectre(ccsp,vjs,mjs,eg_ref,eg_t,ccsp_t,vjs_t)
  // -->2021.06.20(XJ) Comment, below is the original
  //`TEMPCJ(cje,vje,mje,eg,cje_t,vje_t);
  //`TEMPCJ(cjc,vjc,mjc,eg,cjc_t,vjc_t);
  //`TEMPCJ(cjs,vjs,mjs,eg,cjs_t,vjs_t);

  // -->2021.06.20(XJ) Add
  // T dependence of resistance
  re_t = re*(1+tre1*dT+tre2*dT*dT);
  rb_t = rb*(1+trb1*dT+trb2*dT*dT);
  rc_t = rc*(1+trc1*dT+trc2*dT*dT);
  rbm_t = rbm*(1+trm1*dT+trm2*dT*dT);

end //of Model_initialization

ttype=`Type;
Vbbi  = ttype*V(br_bbi);
Veei  = ttype*V(br_eei);
Vcci  = ttype*V(br_cci);
Vcie  = ttype*V(br_cie);
Vciei = ttype*V(br_ciei);
Vbiei = ttype*V(br_biei);
Vbici = ttype*V(br_bici);
Vbci  = ttype*V(br_bci);
// -->2021.06.24(XJ) Add
Vsci  = ttype*V(br_sci);
Vsc   = ttype*V(br_sc);

begin : Model_evaluation

  //currents
  `IDIO(is_t,  nf, Vbiei, ifwd)
  `IDIO(ise_t, ne, Vbiei, ibe2)
  `IDIO(is_t,  nr, Vbici, ibwd)
  `IDIO(isc_t, nc, Vbici, ibc2)
  // -->2021.06.24(XJ) Add
  `IDIO(iss_t, ns, Vsci, isfwd)
  Isc   = isfwd;

  Ibe   = ifwd/bf_t+ibe2;
  Ibc   = ibwd/br_t+ibc2;
  Ib    = Ibe+Ibc;
  Kq2   = ifwd*oikf+ibwd*oikr;

  iKq1  = 1.0-Vbiei*ovar-Vbici*ovaf;
  iKqb  = 2*iKq1/(1.0+sqrt(1.0+4.0*Kq2));

  Itzf  = ifwd*iKqb;

  Itr   = ibwd*iKqb;
  Itxf  = Itzf;

  //bias dependent base resistance
  if (irb == 0) begin
    Rb = rbm_t+(rb_t-rbm_t)*iKqb;
  end else begin
    opipi = 1/(`M_PI*`M_PI);
    hib   = Ib/irb;
    z1    = sqrt(1+144*hib*opipi)-1;
    zed   = z1/(24*sqrt(hib)*opipi);
    tanz  = tan(zed);
    ftan  = 3*(tanz-zed)/(zed*tanz*tanz);
    Rb    = rbm_t+(rb_t-rbm_t)*ftan;
  end

  //effective transit time
  itdep = ifwd/(ifwd+itf);
  if (vtf  > 0) begin
    tff = tf_t*(1+xtf*exp(Vbici/(1.44*vtf))*itdep*itdep);
  end else begin
    tff = tf_t*(1+xtf*itdep*itdep);
  end
  t0  =  1e-12;
  `ifdef NQS_TF
    TD  = tf*ptf*`M_PI/180;
  `else
    TD  = tff*ptf*`M_PI/180;
  `endif

  //diffusion charges
  Qde = tff*Itzf;
  // -->2021.06.20(XJ) Add
  // modified by XJ
  Qdc = tr*ibwd;
  // -->2021.06.20(XJ) Comment, below is the original
  // Qdc = tr*Itr;

  //junction charges
  // -->2021.06.24(XJ) Add
  `QJ(Qjs,cjs_t,Vsci,vjs_t,mjs,fc)  //though fc=0 is assumed in SPICE
  `QJ(Qcsp,ccsp_t,Vsc,vjs_t,mjs,fc)  //though fc=0 is assumed in SPICE
  // -->2021.06.24(XJ) Comment
  // `QJ(Qjs,cjs_t,Vcie,vjs_t,mjs,fc)  //though fc=0 is assumed in SPICE
  `QJ(Qje,cje_t,Vbiei,vje_t,mje,fc)
  `QJ(qjcx,cjc_t,Vbci,vjc_t,mjc,fc)
  Qjcx  = (1-xcjc)*qjcx;
  `QJ(qjci,cjc_t,Vbici,vjc_t,mjc,fc)
  Qjci  = xcjc*qjci;

  Qje_Vbe = ddx(Qje, V(bi));
  Qjci_Vbc = ddx(Qjci, V(bi));
  Qjcx_Vbc = ddx(Qjcx, V(b));

  qbe  = Qje + Qde;
  qbc  = Qjci + Qjcx + Qdc;

  GMi = ttype*ddx(Itxf,V(bi))+`Gmin;
  gPIi = ttype*ddx(Ibe,V(bi))+`Gmin;
  gPIx = `Gmin;

  if (gPIi+gPIx > 0.0) begin
      BETAAC = GMi/(gPIi+gPIx);
  end else begin
      BETAAC = 0.0;
  end

  CdS_ddx = 0;

  CdEi_ddx = -ttype*ddx(Qde,V(ei));
  CdCi_ddx = -ttype*ddx(Qdc,V(ci));

  CjEi_ddx = -ttype*ddx(Qje,V(ei));
  CjCi_ddx = -ttype*ddx(Qjci,V(ci));

  CMUi = CjCi_ddx+CdCi_ddx;
  CMUx = CdS_ddx;

  CPIi = CjEi_ddx+CdEi_ddx;
  CPIx = 0;

  // ft = GMi/(2*`M_PI*(CPIi+CPIx+CMUi+CMUx+(rc_t+re_t+(re_t+Rb)/BETAAC)*GMi*(CMUi+CMUx)));

end //of Model_evaluation

begin : Load_sources
  I(br_biei)     <+ `Gmin*V(br_biei);
  I(br_bici)     <+ `Gmin*V(br_bici);
  I(br_ciei)	   <+ `Gmin*V(br_ciei);

  //excess phase network, 2nd Bessel approach (Hicum)
    if ((ptf != 0.0) && (tf != 0.0)) begin
      Itxf1     =  (V(br_xf2)-Itzf)/TD*t0;
      Itxf2     =  (V(br_xf2)-V(br_xf1))/TD*t0;
      Qxf1      =  t0*V(br_xf1);
      Qxf2      =  t0*V(br_xf2)/3;
      Itxf      =  V(br_xf2);
      I(br_xf1) <+ Itxf1;
      I(br_xf1) <+ ddt(Qxf1);
      I(br_xf2) <+ Itxf2;
      I(br_xf2) <+ ddt(Qxf2);
    end else begin
      I(br_xf1) <+ V(br_xf1);
      I(br_xf2) <+ V(br_xf2);
      Qxf1      =  0;
      Qxf2      =  0;
    end
  // -->2021.06.20(XJ) Mod Rb=>rb
  if (rb >= `MIN_R) begin
    I(br_bbi)   <+ V(br_bbi)/Rb;
  end else begin
    V(br_bbi)   <+ 0;
  end
  if (re >= `MIN_R) begin
    I(br_eei)   <+ V(br_eei)/re_t;
  end else begin
    V(br_eei)   <+ 0;
  end
  if (rc >= `MIN_R) begin
    I(br_cci)   <+ V(br_cci)/rc_t;
  end else begin
    V(br_cci)   <+ 0;
  end
  I(br_biei)  <+ ttype*Ibe;
  I(br_biei)  <+ ddt(ttype*Qje);
  I(br_biei)  <+ ddt(ttype*Qde);

  //MM: Isolation caps
  I(br_be)       <+ ddt(cbep*V(br_be));
  I(br_bci)       <+ ddt(cbcp*V(br_bci));

  I(br_bici)  <+ ttype*Ibc;
  I(br_bici)  <+ ddt(ttype*Qjci);
  I(br_bici)  <+ ddt(ttype*Qdc);
  I(br_bci)   <+ ddt(ttype*Qjcx);

  I(br_ciei)  <+ ttype*(-Itr);
  I(br_ciei)  <+ ttype*Itxf;
  // -->2021.06.28(XJ) Add
  I(br_ciei)  <+ ttype*(-Ibc);
  // -->2021.06.24(XJ) Add
  I(br_sci)   <+ ttype*Isc;
  I(br_sci)   <+ ddt(ttype*Qjs);
  I(br_sc)    <+ ddt(ttype*Qcsp);
  // -->2021.06.24(XJ) Comment
  // I(br_cie)   <+ ddt(ttype*Qjs);
end //of Load_sources

`NOISE begin : Noise_sources

  //Thermal noise
  fourkt  = 4.0 * `P_K * Tdev;
  if(rb >= `MIN_R) begin
    I(br_bbi) <+  white_noise(fourkt/Rb, "Rb");
  end
  if(re >= `MIN_R) begin
    I(br_eei) <+  white_noise(fourkt/re_t, "re");
  end
  if(rc >= `MIN_R) begin
    I(br_cci) <+ white_noise(fourkt/rc_t, "rc");
  end

  //Flicker noise
  if (af > 0 && kf > 0) begin
    flicker_Pwr = kf*pow(abs(Ibe),af);
    I(br_biei)  <+  flicker_noise(flicker_Pwr,1.0, "flicker_Ibe");
  end

  //shot noise
  twoq  = 2.0 * `P_Q;
  I(br_biei)  <+  white_noise(twoq*abs(Ibe),"Ibe");
  I(br_ciei)  <+  white_noise(twoq*abs(Itzf-Itr),"It");

end //Noise sources

end //analog
endmodule