home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p064 / 3.ddi / DIODE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  9.0 KB  |  341 lines

  1. /****************************************************************************/
  2. /*        Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991                  */
  3. /*          By MicroSim Corporation, All Rights Reserved                    */
  4. /****************************************************************************/
  5. /* diode.c
  6.  *   $Revision:   1.19  $
  7.  *   $Author:   pwt  $
  8.  *   $Date:   13 Jun 1991 11:23:54  $ */
  9.  
  10. /******************* USERS OF DEVICE EQUATIONS OPTION ***********************/
  11. /******** The procedure for changing the diode model parameters    **********/
  12. /******** and device equations is the same as for the MOSFET.  See **********/
  13. /******** the comments in the files mos.c and m.h for details.     **********/
  14.  
  15. #define D_DEVICE
  16.  
  17. #include "option1.h"
  18.  
  19. #ifdef USE_DECL_ARGS
  20. int Diode(struct d_ *,int ,int ,int );
  21. #else
  22. int Diode();
  23. #endif
  24.  
  25. int Diode(    /* Process diode for DC and TRANSIENT analyses */
  26.   Instance,    /* a device to evaluate */
  27.   ModeFl,    /* mode control flag:   see "tran.h" */
  28.   InitFl,    /* initialization flag: see "tran.h" */
  29.   LoadFl    /* NO: bypass MatPrm load if solution unchanged */
  30.   )        /* return: did not converge (YES/NO) */
  31.   struct d_ *Instance;
  32.   int ModeFl, InitFl, LoadFl;
  33.  
  34. /*
  35. pwt    12 Aug 86    creation
  36. pwt    16 Mar 88    add shared data area to D.H, change source to match
  37. pwt    ?? Jul 88    add high-injection effects
  38. pwt    17 Aug 88    add generation-recombination current effects
  39. whjb    06 Apr 89    LoadFl==YES now forces full recalculation
  40. pwt    15 Apr 89    set T=0 cap. current
  41. pwt    11 Sep 89    add enhanced breakdown model
  42. sv    12 Feb 90    add local temperatures to models
  43. pwt    04 May 90    minor housekeeping
  44. */
  45. { struct D_ *model;    /* device model */
  46.   double
  47.     vj,            /* voltage across diode junction */
  48.     ij,            /* current thru diode */
  49.     ij_hat,        /* predicted current */
  50.     gj,            /* conductance of diode junction */
  51.     cap_d;        /* junction capacitance */
  52.  
  53.   int
  54.     jlim_fl = YES,    /* junction limiting flag: YES, NO */
  55.     pred_fl = NO,    /* pred. calculated  flag: YES, NO */
  56.     nonconv = NO;    /* non-convergence   flag: YES, NO */
  57.  
  58. #define vt    VT
  59.  
  60. /* defines & declarations for state-vector access */
  61.  
  62.   struct dsv_def *sv[MSTVCT];
  63.  
  64.   EVAL_SV(sv,Instance,d_sda.d_sv);
  65.  
  66. /* defines for model parameter access: simplify code appearance */
  67.  
  68. #define PARAM(a) ((double)model->a)
  69. #define AF    PARAM(D_af)
  70. #define BV    PARAM(D_bv)
  71. #define CJO    PARAM(D_cjo)
  72. #define EG    PARAM(D_eg)
  73. #define FC    PARAM(D_fc)
  74. #define F1    PARAM(D_f1)
  75. #define F2    PARAM(D_f2)
  76. #define F3    PARAM(D_f3)
  77. #define IBV    PARAM(D_ibv)
  78. #define IBVL    PARAM(D_ibvl)
  79. #define IKF    PARAM(D_ikf)
  80. #define IS    PARAM(D_is)
  81. #define ISR    PARAM(D_isr)
  82. #define KF    PARAM(D_kf)
  83. #define M    PARAM(D_m)
  84. #define N    PARAM(D_n)
  85. #define NBV    PARAM(D_nbv)
  86. #define NBVL    PARAM(D_nbvl)
  87. #define NR    PARAM(D_nr)
  88. #define RS    PARAM(D_rs)
  89. #define TT    PARAM(D_tt)
  90. #define VCRIT    PARAM(D_vcrit)
  91. #define VJ    PARAM(D_vj)
  92. #define XTI    PARAM(D_xti)
  93.  
  94. #define FCVJ    FC    /* = fc*vj */
  95.  
  96. #define IJ0    (Instance->dcv_ij)
  97. #define GJ0    (Instance->dcv_gj)
  98.  
  99. #define CJ0    (Instance->d_sda.d_ac.dac_cj)
  100.  
  101. #define DevOff  (Instance->d_off)
  102. #define AREA    (Instance->d_area)
  103.  
  104. /* find the model */
  105.  
  106.   model = Instance->d_model;
  107.  
  108. /* initialization */
  109.  
  110.   if      ( InitFl==INSTV0 )            /* use prev. iteration */
  111.     vj = VOLTAGE(d_p) - VOLTAGE(d_N);
  112.  
  113.   else if ( InitFl==INTRAN )            /* use prev. time-step */
  114.     vj = D_VJ(1);
  115.  
  116.   else if ( InitFl==INOFF && DevOff==YES )    /* set "off" devices */
  117.     vj = 0.;
  118.  
  119.   else if ( InitFl==ININIT ) {            /* use IC= values */
  120.     if ( ModeFl==MDBPTR && NOSOLV==YES )
  121.       vj = Instance->d_vj;
  122.     else
  123.       vj = ( DevOff ? 0.: VCRIT);
  124.     }
  125.   else {
  126.     double del_vj, del_ij;
  127.  
  128.     if ( InitFl==INPRDCT ) {            /* extrapolate value */
  129.       vj = ( D_VJ(1) - D_VJ(2) )*DELTA/DELOLD[1] + D_VJ(1);
  130.       *sv[0] = *sv[1];
  131.       }
  132.     else {                    /* use prev. iteration */
  133.       vj = VOLTAGE(d_p) - VOLTAGE(d_N);
  134.       }
  135.  
  136. /* compute new non-linear branch voltage */
  137.  
  138.     del_vj = vj - D_VJ(0);
  139.     del_ij = del_vj*GJ0;
  140.     ij_hat = del_ij + IJ0;
  141.  
  142. /* bypass if solution not changed */
  143.  
  144.     if ( LoadFl ) ;
  145.     else if ( InitFl==INPRDCT && DELTA!=DELOLD[1] ) ;
  146.     else if ( fabs(del_ij) >= TOL(ij_hat,    IJ0,RELTOL,ABSTOL) ) ;
  147.     else if ( fabs(del_vj) >= TOL(    vj,D_VJ(0),RELTOL, VNTOL) ) ;
  148.     else {
  149.       goto done;
  150.       }
  151.     pred_fl = YES;
  152.  
  153. /* solution changed: limit new junction voltage */
  154.  
  155.     if ( BV==0.|| vj >= 10*vt*MAX(NBV,NBVL)-BV ) {
  156.       double vte = N*vt;
  157.  
  158.       jlim_fl = PNJLIM(vj,D_VJ(0),vte,VCRIT);
  159.       }
  160.     else {
  161.       double
  162.         vj_now = -(BV+vj),
  163.         vj_old = -(BV+D_VJ(0)),
  164.         vtbv   = NBV*vt,
  165.         tmp    = vtbv * log( vtbv / (ROOT2 * IBV) ),
  166.         vcrit  = MAX(tmp,0.);
  167.  
  168.       jlim_fl = PNJLIM(vj_now,vj_old,vtbv,vcrit);
  169.  
  170.       if ( IBVL > 0.) {
  171.         double
  172.           v2_now = -(BV+vj),
  173.           vtbvl  = NBVL*vt,
  174.           tmp    = vtbvl * log( vtbvl / (ROOT2 * IBVL) ),
  175.           vcrit  = MAX(tmp,0.);
  176.  
  177.         jlim_fl |= PNJLIM(v2_now,vj_old,vtbvl,vcrit);
  178.  
  179.         if ( fabs(vj_old-v2_now) < fabs(vj_old-vj_now) ) vj_now = v2_now;
  180.         }
  181.  
  182.       vj = -(vj_now+BV);
  183.       }
  184.  
  185.     } /* end of initialization */
  186.  
  187. /* compute DC current & conductances */
  188.  
  189.   { double itmp, vtmp;
  190.  
  191.     if ( vj >= -10*(vtmp = N*vt) ) {    /* Shockley equation */
  192.       itmp = EXP(vj/vtmp)*IS*AREA;
  193.       ij   = itmp;
  194.       gj   = itmp/vtmp;
  195.       }
  196.     else {
  197.       ij = -IS*AREA;
  198.       gj = 0.;
  199.       }
  200.  
  201.     if ( BV!=0.&&
  202.          vj<=-MINREAL) {
  203.       double ijr, gjr, k,
  204.         bvj = -(vj+BV);
  205.  
  206.       if ( bvj >= -35*(vtmp = NBV*vt) ) {    /* UCB SPICE breakdown */
  207.         itmp = EXP(bvj/vtmp)*IBV*AREA;
  208.         ijr  = itmp;
  209.         gjr  = itmp/vtmp;
  210.         }
  211.       else
  212.         ijr =
  213.         gjr = 0.;
  214.  
  215.       if ( IBVL!=0.&&
  216.            bvj >= -35*(vtmp = NBVL*vt) ) {    /* low-level breakdown */
  217.         itmp = EXP(bvj/vtmp)*IBVL*AREA;
  218.         ijr += itmp;
  219.         gjr += itmp/vtmp;
  220.         }
  221.  
  222.       if ( (k = vj/(10*vt)) > -1.) {    /* smooth-fit breakdown current */
  223.         double            /* over -1 < k < 0, note: 0 test implicit */
  224.           fact = (2*k+3)*k*k;    /* use cubic: 2x^3 + 3x^2 */
  225.                 /* derivative: 6x^2 + 6x */
  226.         gjr  = gjr*fact - ijr*6*(k+1)*k*k/vj;    /* do gjr first as ijr used */
  227.         ijr *= fact;        /* note: f*g (d/dx) = f (dg/dx) + g (df/dx) */
  228.         }
  229.  
  230.       ij -= ijr;
  231.       gj += gjr;
  232.     } }
  233.  
  234.   if ( ISR==0.) {            /* GMIN "leakage" */
  235.     gj += GMIN;
  236.     ij += GMIN*vj;
  237.     }
  238.   else {                /* gen.-rec. current effects */
  239.     if (vj >= -10.0 * NR * vt) {      
  240.       double
  241.         vtr  = NR*vt,
  242.         evjr = EXP(vj/vtr),
  243.         kv   = 1-vj/VJ,
  244.         fact = kv*kv +.005,
  245.         kw   = pow(fact,M/2),        /* depletion region width factor */
  246.         ki   = kw*AREA*ISR;
  247.  
  248.       gj += ki*(evjr/vtr - (evjr-1)*M*kv/fact);
  249.       ij += ki*(evjr-1);
  250.       }
  251.     else {
  252.       double
  253.         kv   = 1-vj/VJ,
  254.         fact = kv*kv +.005,
  255.         kw   = pow(fact,M/2),        /* depletion region width factor */
  256.         ki   = kw*AREA*ISR;
  257.  
  258.       gj += ki*M*kv/fact;
  259.       ij += -ki;
  260.       }
  261.     }
  262.  
  263.   if ( IKF!=0. && ij > 0.) {        /* high-injection correction */
  264.     double
  265.       ikf    = IKF*AREA,
  266.       factor = ikf/(ikf + ij),
  267.       sqfctr = sqrt(factor);
  268.  
  269.     ij *= sqfctr;
  270.     gj *= sqfctr*(factor+1)/2;
  271.     }
  272.  
  273. /* charge calculations */
  274.  
  275.   if ( ModeFl==MDTRAN ||
  276.        InitFl==INSTV0 ||
  277.        ModeFl==MDBPTR && NOSOLV==YES ) {
  278.     double cjo = CJO*AREA;        /* scale 0-bias cap. */
  279.  
  280.     PNJCHG(D_QCJ(0),cap_d,cjo,vj,VJ,FCVJ,M,F1,F2,F3);
  281.     D_QCJ(0) += TT*ij;
  282.     cap_d    += TT*gj;
  283.  
  284.     D_ICJ(0) = 0.;    /* reset, so T=0 results (e.g. Probe) are correct */
  285.  
  286.     if ( InitFl==INSTV0 ) {    /* store small-signal parameters */
  287.       CJ0     = cap_d;        /* and update state vector values */
  288.  
  289.       goto load;
  290.       }
  291.  
  292.     if ( !(ModeFl==MDBPTR && NOSOLV==NO) ) {    /* transient analysis */
  293.       double g_eq, i_eq;
  294.  
  295.       if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  296.         D_QCJ(2) = D_QCJ(1) = D_QCJ(0);        /* set "old" charges so */
  297.         }                    /* integration works */
  298.  
  299.       INTEGR8(g_eq,i_eq,cap_d,D_QIJ(0),D_QIJ(1),D_QIJ(2));
  300.       gj += g_eq;
  301.       ij += D_ICJ(0);
  302.  
  303.       if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  304.         D_ICJ(1) = D_ICJ(0);            /* set "old" currents so */
  305.         }                    /* time-step calc. works */
  306.     } } /* end of charge calculations */
  307.  
  308. /* check convergence */
  309.  
  310.   if ( pred_fl && (
  311.          jlim_fl ||
  312.          fabs(ij_hat-ij) > TOL(ij_hat,ij,RELTOL,ABSTOL)
  313.          )
  314.        ) nonconv = YES;
  315.  
  316. load:
  317.   { double gspr;
  318.  
  319.     /* load current vector */
  320.  
  321.     Y_MATRIX(d_ip) = -( Y_MATRIX(d_iN) =  ij - gj*vj );
  322.  
  323.     /* load conductance matrix */
  324.  
  325.     Y_MATRIX(d_Np) = Y_MATRIX(d_pN) = -( Y_MATRIX(d_NN) = gj );
  326.  
  327.     Y_MATRIX(d_pp) = gj + ( gspr = AREA*RS );
  328.  
  329.     if ( LoadFl ) {
  330.       Y_MATRIX(d_Pp) = Y_MATRIX(d_pP) = -( Y_MATRIX(d_PP) = gspr );
  331.     } }
  332.  
  333.   D_VJ(0) = vj;
  334.  
  335.   IJ0     = ij;
  336.   GJ0     = gj;
  337.  
  338. done:
  339.   return nonconv;
  340.   }
  341.