@@ -41,6 +41,8 @@ class MosfetElm extends CircuitElm implements MouseWheelHandler {
4141 double vt ;
4242 // beta = 1/(RdsON*(Vgs-Vt))
4343 double beta ;
44+ // channel-length modulation parameter (1/V), 0 = ideal
45+ double lambda ;
4446 static int globalFlags ;
4547 Diode diodeB1 , diodeB2 ;
4648 double diodeCurrent1 , diodeCurrent2 , bodyCurrent ;
@@ -69,6 +71,7 @@ public MosfetElm(int xa, int ya, int xb, int yb, int f,
6971 try {
7072 vt = new Double (st .nextToken ()).doubleValue ();
7173 beta = new Double (st .nextToken ()).doubleValue ();
74+ lambda = new Double (st .nextToken ()).doubleValue ();
7275 } catch (Exception e ) {}
7376 globalFlags = flags & (FLAGS_GLOBAL );
7477 allocNodes (); // make sure volts[] has the right number of elements when hasBodyTerminal() is true
@@ -120,15 +123,18 @@ void dumpXml(Document doc, Element elem) {
120123 super .dumpXml (doc , elem );
121124 XMLSerializer .dumpAttr (elem , "vt" , vt );
122125 XMLSerializer .dumpAttr (elem , "be" , beta );
126+ if (lambda != 0 )
127+ XMLSerializer .dumpAttr (elem , "lambda" , lambda );
123128 }
124129
125130 void undumpXml (XMLDeserializer xml ) {
126131 flags = 0 ;
127132 super .undumpXml (xml );
128133 vt = xml .parseDoubleAttr ("vt" , vt );
129134 beta = xml .parseDoubleAttr ("be" , beta );
135+ lambda = xml .parseDoubleAttr ("lambda" , 0 );
130136 globalFlags = flags & (FLAGS_GLOBAL );
131- allocNodes (); // make sure volts[] has the right number of elements when hasBodyTerminal() is true
137+ allocNodes (); // make sure volts[] has the right number of elements when hasBodyTerminal() is true
132138 }
133139
134140 int getDumpType () { return 'f' ; }
@@ -423,11 +429,14 @@ void calculate(boolean finished) {
423429 Gds = beta *(vgs -vds -vt );
424430 mode = 1 ;
425431 } else {
426- // saturation; Gds = 0
427- gm = beta *(vgs -vt );
432+ // saturation; Gds from channel-length modulation
433+ double vgs_vt = vgs -vt ;
434+ gm = beta *vgs_vt *(1 +lambda *vds );
435+ ids = .5 *beta *vgs_vt *vgs_vt *(1 +lambda *vds );
436+ Gds = .5 *beta *vgs_vt *vgs_vt *lambda ;
428437 // use very small Gds to avoid nonconvergence
429- Gds = 1e-8 ;
430- ids = .5 * beta *( vgs - vt )*( vgs - vt ) + ( vds -( vgs - vt ))* Gds ;
438+ if ( Gds < 1e-8 )
439+ Gds = 1e-8 ;
431440 mode = 2 ;
432441 }
433442
@@ -465,7 +474,9 @@ void calculate(boolean finished) {
465474 void getFetInfo (String arr [], String n ) {
466475 arr [0 ] = Locale .LS (((pnp == -1 ) ? "p-" : "n-" ) + n );
467476 arr [0 ] += " (Vt=" + getVoltageText (pnp *vt );
468- arr [0 ] += ", \u03b2 =" + beta + ")" ;
477+ arr [0 ] += ", \u03b2 =" + beta ;
478+ if (lambda > 0 ) arr [0 ] += ", \u03bb =" + lambda ;
479+ arr [0 ] += ")" ;
469480 arr [1 ] = ((pnp == 1 ) ? "Ids = " : "Isd = " ) + getCurrentText (ids );
470481 arr [2 ] = "Vgs = " + getVoltageText (volts [0 ]-volts [pnp == -1 ? 2 : 1 ]);
471482 arr [3 ] = ((pnp == 1 ) ? "Vds = " : "Vsd = " ) + getVoltageText (volts [2 ]-volts [1 ]);
@@ -493,27 +504,29 @@ public EditInfo getEditInfo(int n) {
493504 return new EditInfo ("Threshold Voltage" , pnp *vt , .01 , 5 );
494505 if (n == 1 )
495506 return new EditInfo (EditInfo .makeLink ("mosfet-beta.html" , "Beta" ), beta , .01 , 5 );
496- if (n == 2 ) {
507+ if (n == 2 )
508+ return new EditInfo ("Channel-Length Modulation (1/V)" , lambda , 0 , 0 ).setDimensionless ();
509+ if (n == 3 ) {
497510 EditInfo ei = new EditInfo ("" , 0 , -1 , -1 );
498511 ei .checkbox = new Checkbox ("Show Bulk" , showBulk ());
499512 return ei ;
500513 }
501- if (n == 3 ) {
514+ if (n == 4 ) {
502515 EditInfo ei = new EditInfo ("" , 0 , -1 , -1 );
503516 ei .checkbox = new Checkbox ("Swap D/S" , (flags & FLAG_FLIP ) != 0 );
504517 return ei ;
505518 }
506- if (n == 4 && !showBulk ()) {
519+ if (n == 5 && !showBulk ()) {
507520 EditInfo ei = new EditInfo ("" , 0 , -1 , -1 );
508521 ei .checkbox = new Checkbox ("Digital Symbol" , drawDigital ());
509522 return ei ;
510523 }
511- if (n == 4 && showBulk ()) {
524+ if (n == 5 && showBulk ()) {
512525 EditInfo ei = new EditInfo ("" , 0 , -1 , -1 );
513526 ei .checkbox = new Checkbox ("Simulate Body Diode" , (flags & FLAG_BODY_DIODE ) != 0 );
514527 return ei ;
515528 }
516- if (n == 5 && doBodyDiode ()) {
529+ if (n == 6 && doBodyDiode ()) {
517530 EditInfo ei = new EditInfo ("" , 0 , -1 , -1 );
518531 ei .checkbox = new Checkbox ("Body Terminal" , (flags & FLAG_BODY_TERMINAL ) != 0 );
519532 return ei ;
@@ -525,28 +538,30 @@ public void setEditValue(int n, EditInfo ei) {
525538 if (n == 0 )
526539 vt = pnp *ei .value ;
527540 if (n == 1 && ei .value > 0 )
528- beta = lastBeta = ei .value ;
529- if (n == 2 ) {
541+ beta = lastBeta = ei .value ;
542+ if (n == 2 && ei .value >= 0 )
543+ lambda = ei .value ;
544+ if (n == 3 ) {
530545 globalFlags = (!ei .checkbox .getState ()) ? (globalFlags |FLAG_HIDE_BULK ) :
531546 (globalFlags & ~(FLAG_HIDE_BULK |FLAG_DIGITAL ));
532547// setPoints();
533548 ei .newDialog = true ;
534549 }
535- if (n == 3 ) {
550+ if (n == 4 ) {
536551 flags = (ei .checkbox .getState ()) ? (flags | FLAG_FLIP ) :
537552 (flags & ~FLAG_FLIP );
538553// setPoints();
539554 }
540- if (n == 4 && !showBulk ()) {
555+ if (n == 5 && !showBulk ()) {
541556 globalFlags = (ei .checkbox .getState ()) ? (globalFlags |FLAG_DIGITAL ) :
542557 (globalFlags & ~FLAG_DIGITAL );
543558// setPoints();
544559 }
545- if (n == 4 && showBulk ()) {
560+ if (n == 5 && showBulk ()) {
546561 flags = ei .changeFlag (flags , FLAG_BODY_DIODE );
547562 ei .newDialog = true ;
548563 }
549- if (n == 5 ) {
564+ if (n == 6 ) {
550565 flags = ei .changeFlag (flags , FLAG_BODY_TERMINAL );
551566 }
552567
0 commit comments