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

  1. /****************************************************************************/
  2. /*        Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991                  */
  3. /*          By MicroSim Corporation, All Rights Reserved                    */
  4. /****************************************************************************/
  5. /* jfet.c
  6.  *   $Revision:   1.15  $
  7.  *   $Author:   pwt  $
  8.  *   $Date:   11 Aug 1990 13:30:52  $ */
  9.  
  10. /******************* USERS OF DEVICE EQUATIONS OPTION ***********************/
  11. /******** The procedure for changing the JFET 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 J_DEVICE
  16.  
  17. #include "option1.h"
  18.  
  19. #ifdef USE_DECL_ARGS
  20. int Jfet(struct j_ *,int ,int ,int );
  21. #else
  22. int Jfet();
  23. #endif
  24.  
  25. int Jfet(    /* Process JFET 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 j_ *Instance;
  32.   int ModeFl, InitFl, LoadFl;
  33.  
  34. /*
  35. pwt    15 Aug 86    creation
  36. pwt    16 Mar 88    add shared data area to J.H, change source to match
  37. pwt    17 Aug 88    add generation-recombination current effects
  38. pwt    15 Sep 88    add active gate current, due to impact ionization in channel
  39. whjb    06 Apr 89    LoadFl==YES forces full recalculation
  40. pwt    15 Apr 89    set T=0 cap. currents
  41. sv    12 Feb 90    add local temperatures to models
  42. pwt    04 May 90    minor speed-up in some calculations
  43. pwt    08 Aug 90    correct IC= for device type
  44. */
  45. { struct J_ *model;    /* device model */
  46.   double
  47.     beta,        /* device transconductance */
  48.     isat,        /* junction saturation current */
  49.     vds, vgs, vgd,    /* terminal voltages */
  50.     vte,        /* emission coef. * thermal voltage */
  51.     gm,            /* forward transconductance */
  52.     gds, ggs, ggd,    /* conductances */
  53.     ggds, gggs,
  54.     ig, id, igd,    /* currents */
  55.     idrain,        /* drain current */
  56.     ig_hat, id_hat,    /* predicted currents */
  57.     cap_gs, cap_gd,    /* junction capacitances */
  58.     type;        /* NJF=+1, PJF=-1 */
  59.  
  60. #define vt    VT
  61.  
  62.   int
  63.     jlim_fl = YES,    /* junction limiting flag: YES, NO */
  64.     pred_fl = NO,    /* pred. calculated  flag: YES, NO */
  65.     nonconv = NO;    /* non-convergence   flag: YES, NO */
  66.  
  67. /* defines & declarations for state-vector access */
  68.  
  69.   struct jsv_def *sv[MSTVCT];
  70.  
  71.   EVAL_SV(sv,Instance,j_sda.j_sv);
  72.  
  73. /* defines for model parameter access: simplify code appearance */
  74.  
  75. #define PARAM(a) ((double)model->a)
  76. #define AF    PARAM(J_af)
  77. #define ALPHA    PARAM(J_alpha)
  78. #define BETA    PARAM(J_beta)
  79. #define CGD    PARAM(J_cgd)
  80. #define CGS    PARAM(J_cgs)
  81. #define FC    PARAM(J_fc)
  82. #define FCPB    FC        /* = fc*pb */
  83. #define F1    PARAM(J_f1)
  84. #define F2    PARAM(J_f2)
  85. #define F3    PARAM(J_f3)
  86. #define IS    PARAM(J_is)
  87. #define ISR    PARAM(J_isr)
  88. #define KF    PARAM(J_kf)
  89. #define LAMBDA    PARAM(J_lambda)
  90. #define M    PARAM(J_m)
  91. #define N    PARAM(J_n)
  92. #define NR    PARAM(J_nr)
  93. #define PB    PARAM(J_pb)
  94. #define RD    PARAM(J_rd)
  95. #define RS    PARAM(J_rs)
  96. #define VCRIT    PARAM(J_vcrit)
  97. #define VK    PARAM(J_vk)
  98. #define VTO    PARAM(J_vto)
  99.  
  100. #define IG0    (Instance->jcv_ig)
  101. #define ID0    (Instance->jcv_id)
  102.  
  103. #define GM0    (Instance->jcv_gm)
  104. #define GDS0    (Instance->jcv_gds)
  105. #define GGS0    (Instance->jcv_ggs)
  106. #define GGD0    (Instance->jcv_ggd)
  107. #define GGDS0    (Instance->jcv_ggds)
  108. #define GGGS0    (Instance->jcv_gggs)
  109.  
  110. #define CGS0    (Instance->j_sda.j_ac.jac_cgs)
  111. #define CGD0    (Instance->j_sda.j_ac.jac_cgd)
  112.  
  113. #define DevOff    (Instance->j_off)
  114. #define AREA    (Instance->j_area)
  115.  
  116. /* find the model */
  117.  
  118.   model = Instance->j_model;
  119.  
  120.   type  = model->J_type > 0 ? 1.: -1.;
  121.  
  122. /* some DC model parameters */
  123.  
  124.   vte = N*vt;
  125.  
  126. /* initialization */
  127.  
  128.   if      ( InitFl==INSTV0 ) {        /* use prev. iteration */
  129.     vgs = ( VOLTAGE(j_G) - VOLTAGE(j_s) )*type;
  130.     vgd = ( VOLTAGE(j_G) - VOLTAGE(j_d) )*type;
  131.     }
  132.   else if ( InitFl==INTRAN ) {        /* use prev. time-step */
  133.     vgs = J_VGS(1);
  134.     vgd = J_VGD(1);
  135.     }
  136.   else if ( InitFl==INOFF &&        /* set "off" devices */
  137.             DevOff==YES)
  138.     vgs = vgd = 0.;
  139.  
  140.   else if ( InitFl==ININIT ) {        /* use IC= values */
  141.  
  142.     if ( ModeFl==MDBPTR && NOSOLV==YES ) {
  143.       vgs = (    Instance->j_vgs)*type;
  144.       vgd = (vgs-Instance->j_vds)*type;
  145.       }
  146.     else
  147.       vgd = vgs = ( DevOff ? 0.: -1.)*type;
  148.     }
  149.   else {
  150.     double del_vgs, del_vgd, del_vds, del_id, del_ig;
  151.  
  152.     if ( InitFl==INPRDCT ) {        /* extrapolate value */
  153.       double arg = DELTA/DELOLD[1];
  154.  
  155.       vgs = arg*( J_VGS(1) - J_VGS(2) ) + J_VGS(1);
  156.       vgd = arg*( J_VGD(1) - J_VGD(2) ) + J_VGD(1);
  157.  
  158.       *sv[0] = *sv[1];
  159.       }
  160.     else {                /* use current value */
  161.       vgs = ( VOLTAGE(j_G) - VOLTAGE(j_s) )*type;
  162.       vgd = ( VOLTAGE(j_G) - VOLTAGE(j_d) )*type;
  163.       }
  164.  
  165. /* compute new non-linear branch voltage */
  166.  
  167.     del_vgd = vgd - J_VGD(0);
  168.     del_vgs = vgs - J_VGS(0);
  169.     del_vds = del_vgs - del_vgd;
  170.  
  171.     del_id = del_vds*GDS0 - del_vgd*GGD0 +
  172.              ( J_VGS(0) > J_VGD(0) ? del_vgs : del_vgd )*GM0;
  173.     id_hat = del_id + ID0;
  174.  
  175.     del_ig = del_vgs*GGS0 + del_vgd*GGD0;
  176.     ig_hat = del_ig + IG0;
  177.  
  178. /* bypass if solution not changed */
  179.  
  180.     if ( InitFl==INPRDCT && DELTA!=DELOLD[1] || LoadFl==YES) ;
  181.     else if ( fabs(del_id)  >= TOL(id_hat,     ID0,RELTOL,ABSTOL) ) ;
  182.     else if ( fabs(del_vgd) >= TOL(   vgd,J_VGD(0),RELTOL, VNTOL) ) ;
  183.     else if ( fabs(del_vgs) >= TOL(   vgs,J_VGS(0),RELTOL, VNTOL) ) ;
  184.     else if ( fabs(del_ig)  >= TOL(ig_hat,     IG0,RELTOL,ABSTOL) ) ;
  185.     else {
  186.       goto done;
  187.       }
  188.     pred_fl = YES;
  189.  
  190. /* solution changed: limit non-linear branch voltages */
  191.  
  192.     jlim_fl  = PNJLIM(vgs,J_VGS(0),vte,VCRIT);
  193.     jlim_fl |= PNJLIM(vgd,J_VGD(0),vte,VCRIT);
  194.  
  195.     FETlim(&vgs,J_VGS(0),VTO);
  196.     FETlim(&vgd,J_VGD(0),VTO);
  197.  
  198.     } /* end of initialization */
  199.  
  200. /* compute DC current & conductances */
  201.  
  202.   beta = AREA*BETA;
  203.   isat = AREA*IS;
  204.   vds  = vgs-vgd;
  205.  
  206. /* compute gate junction current & derivatives */
  207.  
  208.   if ( vgs > -10*vte ) {        /* currents re. vgs */
  209.     double evgs = EXP(vgs/vte);
  210.  
  211.     ggs = (evgs/vte)*isat;
  212.     ig  = (evgs-1)*isat;
  213.     }
  214.   else {
  215.     ggs = 0.;
  216.     ig  = -isat;
  217.     }
  218.  
  219.   if ( vgd > -10*vte ) {        /* currents re. vgd */
  220.     double evgd = EXP(vgd/vte);
  221.  
  222.     ggd = (evgd/vte)*isat;
  223.     igd = (evgd-1)*isat;
  224.     }
  225.   else {
  226.     ggd = 0.;
  227.     igd = -isat;
  228.     }
  229.  
  230.   if ( ISR==0.) {            /* traditional SPICE leakage */
  231.     ggs += GMIN;
  232.     ggd += GMIN;
  233.     ig  += GMIN*vgs;
  234.     igd += GMIN*vgd;
  235.     }
  236.   else {                /* gen.-rec. current effects */
  237.     double
  238.       vtr  = NR*vt,
  239.       evjr = EXP(vgs/vtr),
  240.       kv   = 1-vgs/PB,
  241.       fact = kv*kv +.005,
  242.       kw   = pow(fact,M/2),    /* depletion region width factor */
  243.       ki   = kw*AREA*ISR;
  244.  
  245.     ggs += ki*(evjr/vtr - (evjr-1)*M*kv/fact);        /* gate-source */
  246.     ig  += ki*(evjr-1);
  247.  
  248.     evjr = EXP(vgd/vtr);
  249.     kv   = 1-vgd/PB;
  250.     fact = kv*kv +.005;
  251.     kw   = pow(fact,M/2);
  252.     ki   = kw*AREA*ISR;
  253.  
  254.     ggd += ki*(evjr/vtr - (evjr-1)*M*kv/fact);        /* gate-drain */
  255.     igd += ki*(evjr-1);
  256.     }
  257.  
  258. /* compute drain current & derivatives */
  259.  
  260.   if ( vds >= 0. ) {            /* forward mode */
  261.     double vgst = vgs-VTO;
  262.  
  263.     if ( vgst <= 0. )            /* cut-off */
  264.       idrain = gm = gds = ggds = gggs = 0.;
  265.     else {
  266.       double
  267.         beta1 = beta*(1+vds*LAMBDA),
  268.         beta2 = beta1+beta1;
  269.  
  270.       if ( vds > vgst ) {        /* saturated */
  271.         idrain = beta1*vgst*vgst;
  272.         gm     = beta2*vgst;
  273.         gds    = beta*vgst*vgst*LAMBDA;
  274.  
  275.         if ( ALPHA==0.) {
  276.           ggds = gggs = 0.;
  277.           }
  278.         else {            /* gate current from impact ionization */
  279.           double
  280.             vdif = vds - vgst,    /* don't let vdif==0 (careful test for saturation) */
  281.             vrat = VK/vdif,
  282.             temp = ALPHA*EXP(-vrat);
  283.  
  284.           igd   -= temp*vdif*idrain;
  285.           ggds   = temp*( vdif*gds + (1+vrat)*idrain );
  286.           gggs   = temp*( vdif*gm  - (1+vrat)*idrain );
  287.         } }
  288.       else {                /* linear */
  289.         idrain = beta1*vds*(vgst+vgst-vds);
  290.         gm     = beta2*vds;
  291.         gds    = beta2*(vgst-vds) + beta*vds*(vgst+vgst-vds)*LAMBDA;
  292.         ggds   =
  293.         gggs   = 0.;
  294.     } } }
  295.   else {                /* reverse mode */
  296.     double vgdt = vgd-VTO;
  297.  
  298.     if ( vgdt <= 0. )            /* cut-off */
  299.       idrain = gm = gds = ggds = gggs = 0.;
  300.     else {
  301.       double
  302.         beta1  =  beta*(1-vds*LAMBDA),
  303.         beta2  =  beta1+beta1;
  304.  
  305.       if ( vgdt < -vds ) {        /* saturated */
  306.         idrain = -beta1*vgdt*vgdt;
  307.         gm     =  beta2*vgdt;
  308.         gds    =  beta*vgdt*vgdt*LAMBDA;
  309.  
  310.         if ( ALPHA==0.) {
  311.           ggds = gggs = 0.;
  312.           }
  313.         else {            /* gate current from impact ionization */
  314.           double
  315.             vdif = -vds - vgdt,    /* don't let vdif==0 (careful test for saturation) */
  316.             vrat = VK/vdif,
  317.             temp = ALPHA*EXP(-vrat);
  318.  
  319.           ig    += temp*vdif*idrain;
  320.           ggds   = temp*( vdif*gds - (1+vrat)*idrain );
  321.           gggs   = temp*( vdif*gm  + (1+vrat)*idrain );
  322.         } }
  323.       else {                /* linear */
  324.         idrain =  beta1*vds*(vgdt+vgdt+vds);
  325.         gm     = -beta2*vds;
  326.         gds    =  beta2*(vgdt+vds) - beta*vds*(vgdt+vgdt+vds)*LAMBDA;
  327.         ggds   =
  328.         gggs   = 0.;
  329.     } } }
  330.  
  331.   ig += igd;        /* total gate current */
  332.   id  = idrain-igd;    /* total drain current */
  333.  
  334. /* charge calculations */
  335.  
  336.   if ( ModeFl==MDTRAN ||
  337.        InitFl==INSTV0 ||
  338.      ( ModeFl==MDBPTR && NOSOLV==YES ) ) {
  339.     double
  340.       cgso = CGS*AREA,        /* scale 0-bias cap. */
  341.       cgdo = CGD*AREA;
  342.  
  343.     PNJCHG(J_QCGS(0),cap_gs,cgso,vgs,PB,FCPB,M,F1,F2,F3);
  344.     PNJCHG(J_QCGD(0),cap_gd,cgdo,vgd,PB,FCPB,M,F1,F2,F3);
  345.  
  346.     J_ICGS(0) =        /* reset, so T=0 results (e.g. Probe) are correct */
  347.     J_ICGD(0) = 0.;
  348.  
  349.     if ( InitFl==INSTV0) {        /* store small-signal parameters */
  350.       CGS0 = cap_gs;            /* and update the state vector */
  351.       CGD0 = cap_gd;
  352.  
  353.       goto load;
  354.       }
  355.  
  356.     if ( !(ModeFl==MDBPTR && NOSOLV==NO) ) {    /* transient analysis */
  357.       double g_eq, i_eq;
  358.  
  359.       if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  360.         J_QCGS(2) = J_QCGS(1) = J_QCGS(0);    /* set "old" charges so */
  361.         J_QCGD(2) = J_QCGD(1) = J_QCGD(0);    /* integration works */
  362.         }
  363.  
  364.       INTEGR8(g_eq,i_eq,cap_gs,J_QIGS(0),J_QIGS(1),J_QIGS(2));
  365.       ggs += g_eq;
  366.  
  367.       INTEGR8(g_eq,i_eq,cap_gd,J_QIGD(0),J_QIGD(1),J_QIGD(2));
  368.       ggd += g_eq;
  369.  
  370.       ig  += J_ICGD(0) + J_ICGS(0);
  371.       igd += J_ICGD(0);
  372.       id  -= J_ICGD(0);
  373.  
  374.       if ( InitFl==INTRAN ) {            /* for 1st transient step: */
  375.         J_ICGS(1) = J_ICGS(0);            /* set "old" currents so */
  376.         J_ICGD(1) = J_ICGD(0);            /* time-step calc. works */
  377.         }
  378.     } } /* end of charge calculations */
  379.  
  380. /* check convergence */
  381.  
  382.   if ( pred_fl && (
  383.          jlim_fl ||
  384.          fabs(id_hat-id) > TOL(id_hat,id,RELTOL,ABSTOL) ||
  385.          fabs(ig_hat-ig) > TOL(ig_hat,ig,RELTOL,ABSTOL)
  386.          )
  387.        ) nonconv = YES;
  388.  
  389. load:
  390.   { int fwd = ( vds > 0. ? YES : NO );
  391.     double
  392.       gdpr, gspr,
  393.       ieq_gd =      igd - ggd*vgd + ( fwd ?     gggs*vgs + ggds*vds : 0.),
  394.       ieq_gs = ig - igd - ggs*vgs + ( fwd ? 0.: gggs*vgd - ggds*vds ),
  395.       ieq_dr = id + igd - gds*vds - gm*( fwd ? vgs : -vgd );
  396.  
  397.     /* load current vector */
  398.  
  399.     Y_MATRIX(j_iG) = -type*(ieq_gs + ieq_gd);
  400.     Y_MATRIX(j_id) =  type*(ieq_gd - ieq_dr);
  401.     Y_MATRIX(j_is) =  type*(ieq_gs + ieq_dr);
  402.  
  403.     /* load conductance matrix */
  404.  
  405.     Y_MATRIX(j_ds) = ( fwd ? -gm - gggs - ggds :  0. ) - gds;
  406.     Y_MATRIX(j_dG) = ( fwd ?  gm + gggs        : -gm ) - ggd;
  407.     Y_MATRIX(j_dd) = ( fwd ?              ggds :  gm ) + gds + ggd
  408.                    + ( gdpr = AREA*RD );
  409.  
  410.     Y_MATRIX(j_sd) = ( fwd ?  0. : -gm - gggs - ggds ) - gds;
  411.     Y_MATRIX(j_sG) = ( fwd ? -gm :  gm + gggs        ) - ggs;
  412.     Y_MATRIX(j_ss) = ( fwd ?  gm :              ggds ) + gds + ggs
  413.                    + ( gspr = AREA*RS );
  414.  
  415.     Y_MATRIX(j_Gd) = ( fwd ? -ggds        : gggs + ggds ) - ggd;
  416.     Y_MATRIX(j_Gs) = ( fwd ?  ggds + gggs :      - ggds ) - ggs;
  417.     Y_MATRIX(j_GG) = ggd + ggs - gggs;
  418.  
  419.     if ( LoadFl ) {
  420.       Y_MATRIX(j_dD) = Y_MATRIX(j_Dd) = -( Y_MATRIX(j_DD) = gdpr );
  421.       Y_MATRIX(j_sS) = Y_MATRIX(j_Ss) = -( Y_MATRIX(j_SS) = gspr );
  422.     } }
  423.  
  424.   J_VGS(0) = vgs;
  425.   J_VGD(0) = vgd;
  426.  
  427.   IG0  = ig ;
  428.   ID0  = id ;
  429.  
  430.   GM0   = gm ;
  431.   GDS0  = gds;
  432.   GGS0  = ggs;
  433.   GGD0  = ggd;
  434.   GGDS0 = ggds;
  435.   GGGS0 = gggs;
  436.  
  437. done:
  438.   return nonconv;
  439.   }
  440.