Southampton VHDL-AMS Validation Suite

School of Electronics and Computer Science, University of Southampton

 

  Home Example Models Web Parser Acknowledgement ESD Group ECS University of Southampton
 

Van der Pol Oscillator

Lorenz Chaos

Bouncing Ball

Level3 MOS Transistor

Bipolar Transistor with Thermal Effects

AnalogueSchmitt Trigger

VoltageControlled Oscillator with Integration of Phase

Phase-Locked-LoopFrequency Multiplier

Switch-modePower Regulator

Ferromagnetic Hysteresis

Sigma-Delta Modulator

MEMS accelerometer with SD control loop

 

 

Level 3 MOS Transistor

 

<<Previous<<        >>Next>>

 

-- VHDL-AMS model of SPICE Level 3 MOS Transistor
-- (c) University of Southampton 1997
-- Southampton VHDL-AMS Validation Suite - example 3
-- author:  Mark Zwolinski
-- Department of Electronics and Computer Science, University of Southampton
-- Highfield, Southampton SO17 1BJ, United Kingdom
-- Tel. +44 2380 593528  Fax +44 2380 592901
-- e-mail: mz@ecs.soton.ac.uk
-- Created:      18 Oct 1994
-- Last revised:  20 Jun 2005 (by Shaolin Wang)
--
------------------------------------------------------------------------------
-- Description:
-- VHDL-A model of intrinsic part of SPICE level 3 MOS model (source, drain
-- resistances, overlap capacitances as well as drain-bulk, source-bulk diodes are all omitted.)
-- There are some differences with the SPICE model.
-- Based on SPICE 2G6/3E2 source and Southampton University MOS model
-- and converted from Pascal.

--

------------------------------------------------------------------------------

 

--1. VHDL-AMS Model of Level 3 MOS Transistor 

 

library IEEE;

use IEEE.math_real.all;

use IEEE.electrical_systems.all;

 

entity mos is

      generic(

    -- instance parameters

    width  : real:=1.0E-4;  -- should be global constant DEFW!

    length : real:=1.0E-4;  -- DEFL

    channel: real :=1.0;     -- +1 for NMOS, -1  for PMOS

    -- model parameters

    vt0    : real:= real'low;

    kp     : real:= 2.0E-5;

    gamma  : real:= 0.0;

    phi    : real:= 0.6;

    tox    : real:= 1.0E-7;

    nsub   : real:= 0.0;

    nss    : real:= 0.0;

    nfs    : real:= 0.0;

    tpg    : real:= 1.0;

    xj     : real:= 0.0;

    ld     : real:= 0.0;

    u0     : real:= 600.0;

    vmax   : real:= 0.0;

    xqc    : real:= 1.0;

    kf     : real:= 0.0;

    af     : real:= 1.0;

    fc     : real:= 0.5;

    delta  : real:= 0.0;

    theta  : real:= 0.0;

    eta    : real:= 0.0;

    kappa  : real:= 0.2;

    ngate  : real:= 1.5e19;

    -- environment parameters

    Temperature : real :=300.0  -- Should be global

    );

    port(terminal drain,gate,source,bulk: electrical);

  

end entity ;

 

architecture mos3 of mos is

 

  quantity MOSquantities: real_vector(0 to 3);

  quantity Vdsq across drain to source;

  quantity Vgsq across gate to source;

  quantity Vbsq across bulk to source;

  quantity Idq through drain;

  quantity Igq through gate;

  quantity Isq through source;

  quantity Ibq through bulk;

 

  constant eps0 : real :=8.85418e-12;

  constant Ni : real :=1.45e16;

  constant Boltzmann : real :=1.380662e-23;

  constant echarge: real :=1.6021892e-19;

  constant epsSiO2 : real :=3.9*eps0;

  constant epsSi : real :=11.7*eps0;

  constant pi: real := 3.14159;

 

  Function Max(x,y: real) return real is

              variable z: real;

       begin

              if x>=y then

                     z:=x;

              else

                     z:=y;

              end if;

              return z;

  end function Max;

 

  Function Min(x,y: real) return real is

              variable z: real;

       begin

              if x<=y then

                     z:=x;

              else

                     z:=y;

              end if;

              return z;

  end function Min;

     

  Function MOSequations(vdsq,vgsq,vbsq,width,length,channel,vt0,kp,gamma,

                    phi,tox,nsub,nss,nfs,tpg,xj,ld,u0,vmax,xqc,kf,af,fc,delta,theta,

                    eta,kappa,ngate,temperature: real) return real_vector is

           

     variable Qc,Qb,Qg: real;

     variable cox,beta,vt,sigma,nsub_in,Phi_in,Gamma_in,nss_in,ngate_in,A,B,C,D,Vfb,fshort,

              wp,wc,sqwpxj,vbulk,delv,vth,Vgstos, Vgst, eff, Tau, Vsat,Vpp,fdrain,egfet,

              fermig,mobdeg,stfct,leff,xd,qnfscox,fn,dcrit,deltal,It,Ids,R,Vds,Vgs,Vbs,    

              forward,kTQ : real;

     variable results: real_vector(0 to 3);

       begin 

              kTQ :=Boltzmann*temperature/echarge;

    

      if tox<=0.0 then

        cox:=epsSiO2/(1.0e-7);

      else

        cox:=epsSiO2/tox;

      end if;

 

      if kp = 0.0 then

        beta:=cox*u0;

      else

        beta:=kp;

      end if;

 

          nsub_in:= nsub * 1.0e6;  -- scale nsub to SI units

 

 

     -- All "undefined" GENERICs must be assigned legal values by the

     -- configuration.  SPICE, however, allows parameters to be

     -- undefined, and calculates appropriate values.

 

      if (phi = real'low) then

        if (nsub_in > 0.0) then

          Phi_in:=max(0.1,2.0*kTQ*log(nsub_in/Ni));

        else

          Phi_in:=0.6;

        end if;

      else

        Phi_in:=phi;

      end if; -- model.phi = undefined

 

 

      if (gamma = real'low) then

        if (nsub_in > 0.0) then

          Gamma_in:=sqrt(2.0*epsSi*echarge*nsub_in)/cox;

        else

          Gamma_in:=0.0;

        end if;

      else

        Gamma_in:=gamma;

      end if; -- gamma = undefined

 

      nss_in:=nss*1.0e4;              -- Scale to SI

      ngate_in:=ngate*1.0e4;           -- Scale to SI

 

      if (vt0 = real'low) then

        egfet:=1.16-(7.02e-4*Temperature*Temperature)/(Temperature+1108.0);

        if tpg=0.0 then

          fermig:=0.05+egfet/2.0;

        else

          if ngate_in>0.0 then

            fermig:=tpg*channel*kTQ*log(ngate_in/Ni);

          else

            fermig:=tpg*channel*egfet/2.0;

          end if;

          vt:=-fermig+channel*(Phi_in*0.5+Gamma_in*sqrt(Phi_in))-nss_in*echarge/cox;

        end if;

      else

        vt:=vt0;

      end if; -- vt0 = undefined

 

      leff:=length-2.0*ld;

      if leff>0.0 then

        Sigma:=eta*8.15e-22/(cox*leff*leff*leff);

      else

        Sigma:=0.0;

      end if; -- leff>0

 

      if nsub_in>0.0 then -- N.B. nsub was scaled, above.

        xd:=sqrt(2.0*epsSi/(echarge*nsub_in));

      else

        xd:=0.0;

      end if; -- nsub >0

 

      if (nfs>0.0) and(cox>0.0) then

        qnfscox:=echarge*nfs/cox;

      else

        qnfscox:=0.0;

      end if; --nfs > 0

 

      if cox>0.0 then

        fn:=delta*pi*epsSi*0.5/(cox*width);

      else

        fn:=delta*pi*epsSi*0.5*tox/epsSiO2;

      end if;  -- cox > 0

 

      --Scale beta and convert cox from Fm^-2 to F

      beta:=beta*width/leff;

      cox:=cox*width*leff;  

 

    Vds:=channel*Vdsq;

    if Vds>=0.0 then

        Vgs:=channel* Vgsq;

        Vbs:=channel* Vbsq;

        forward:=1.0;

    else

        Vds:=-Vds;

        Vgs:=channel* Vgsq;

        Vbs:=channel* Vbsq;

        forward:=-1.0;

    end if; -- Vds >=0

 

    if Vbs<=0.0 then

        A:=Phi_in-Vbs;

        D:=sqrt(A);

    else

        D:=2.0*sqrt(Phi_in)*Phi_in/(2.0*Phi_in+Vbs);

        A:=D*D;

    end if; -- Vbs <= 0

 

    Vfb:=Vt-Gamma_in*sqrt(Phi_in)-Sigma*Vds;

    if (xd=0.0) OR (xj=0.0) then

        fshort:=1.0;

    else

        wp:=xd*D;

        wc:=0.0631353*xj+0.8013292*wp-0.01110777*wp*wp/xj;

        sqwpxj:=sqrt(1.0-(wp*wp/((wp+xj)*(wp+xj))));

        fshort:=1.0-((ld+wc)*sqwpxj-ld)/leff;

    end if; -- xd or xj = 0

 

    vbulk:=Gamma_in*fshort*D+fn*A;

    if nfs=0.0 then

        delv:=0.0;

    else

        delv:=kTQ*(1.0+qnfscox+vbulk*0.5/A);

    end if; -- nfs = 0

 

    vth:=Vfb+vbulk;

    Vgstos:=Vgs-Vfb;

    Vgst:=max(Vgs-vth,delv);

    if (vgs>=vth) or (delv/=0.0) then

 

      if (Vbs<=0.0) or (Phi_in /= 0.0) then

          B:=0.5*Gamma/D+fn;

      else

          B:=fn;

      end if;

 

      mobdeg:=1.0/(1.0+theta*Vgst);

      if (vmax /=0.0) then

         Ueff:=u0*mobdeg;

          Tau:=Ueff/Leff*vmax;

      else

          Tau:=0.0;

      end if;

 

      Vsat:=Vgst/(1.0+B);

      Vsat:=Vsat*(1.0-0.5*Tau*Vsat); -- not quite the same as SPICE

      Vpp:=min(Vds,Vsat);

      fdrain:=1.0/(1.0+Tau*Vpp);

      if (Vgs<vth+delv) and (nfs>0.0) then

        stfct:=exp((Vgs-vth-delv)/delv);

      else

          stfct:=1.0;

      end if;

 

      if Vds>=Vsat then

        if (kappa>0.0) and (xd>0.0) then

 

          if vmax=0.0 then

              deltal:=sqrt(kappa*xd*xd*(Vds-Vsat));

          else

              dcrit:=(xd*xd*vmax*0.5)/(Ueff*(1.0-fdrain));

              deltal:=sqrt(kappa*xd*xd*(Vds-Vsat)+dcrit*dcrit)-dcrit;

          end if;

 

          if deltal<=0.5*Leff then

              C:=Leff/(Leff-deltal);

          else

              C:=4.0*deltal/Leff;

          end if;

 

        else --kappa=0.0 or xd=0.0

            C:=1.0;

        end if;

 

      else

          C:=1.0;

      end if;

 

      It:=Vgst-Vpp*(1.0+B)*0.5;

        Beta:=Beta*mobdeg;

        Ids:=Beta*Vpp*It*C*fdrain*stfct;

    else

        -- Cutoff

        Ids:=0.0;

    end if; -- vgs >= vth

 

    if Cox /= 0.0 then

        --Charges

      if Vgs<=vth then

        if Gamma_in /= 0.0 then

          if Vgstos < -A then

                Qg:=Cox*(Vgstos+A); -- Accumulation

          else

                Qg:=0.5*Gamma_in*Cox*(sqrt(4.0*(Vgstos+A)+sqrt(Gamma_in))-Gamma_in);

          end if ; -- vgstos <-A

        else-- Gamma = 0.0

            Qg:=0.0;

        end if; -- gamma /= 0

          Qb:=-Qg;

          Qc:=0.0;

      else

          -- depletion mode:

          R:=(1.0+B)*Vpp*Vpp/(12.0*It);

          Qg:=Cox*(Vgstos-Vpp*0.5+R);

          Qc:=-Cox*(Vgst+(1.0+B)*(R-Vpp*0.5));

          Qb:=-(Qc+Qg);

      end if; -- vgs<=vth

 

    else

        Qg:=0.0;

        Qc:=0.0;

        Qb:=0.0;

    end if; -- cox /= 0

   

    results(0):=channel*forward*Ids;

    results(1):=channel*xqc*Qc;

    results(2):=channel*Qg;

    results(3):=channel*Qb;

    return results;

    end function MOSequations;

 

begin  

    -- equations for currents:

      MOSquantities == MOSequations(vdsq,vgsq,vbsq,width,length,channel,vt0,kp,gamma,

                    phi,tox,nsub,nss,nfs,tpg,xj,ld,u0,vmax,xqc,kf,af,fc,delta,theta,

                    eta,kappa,ngate,temperature);

      Idq == MOSquantities(0)+MOSquantities(1)'dot;

      Igq == MOSquantities(2)'dot;

      Ibq == MOSquantities(3)'dot;

      Isq == -Idq - Igq - Ibq;

 

 

end architecture mos3;

 

--------------------------------------------------------------------------------

 

--2. Testbench

 

library IEEE;

use IEEE.math_real.all;

use IEEE.electrical_systems.all;

 

entity test_mos is

end entity test_mos;

 

architecture test of test_mos is

       terminal d,g: electrical;

       alias ground is ELECTRICAL_REF;

begin

       vgs: entity v_constant generic map (level=>2.0)
                                port map (pos=>g,neg=>ground);
       vds: entity v_pulse generic map (pulse=>5.0,tchange=>10sec)
                                port map(pos=>d,neg=>ground);

       nmos: entity mos port map (drain=>d,gate=>g,source=>ground,bulk=>ground);

end architecture;

 

--------------------------------------------------------------------------------

 

--3. Constant Voltage Source

 

library IEEE;

use IEEE.math_real.all;

use IEEE.electrical_systems.all;

 

entity v_constant is

       generic(level: voltage);

       port(terminal pos,neg:electrical);

end entity v_constant;

 

architecture ideal of v_constant is

       quantity v across i through pos to neg;

begin

       v == level;

end architecture;

 

--------------------------------------------------------------------------------

 

--4. Pulse Voltage Source

 

library IEEE;
use IEEE.math_real.all;
use IEEE.electrical_systems.all;

entity v_pulse is
    generic(
            initial: real:= 0.0;
            pulse : real:= 5.0;
            tchange : time:= 10sec); -- initial to pulse [Sec]
    port(terminal pos,neg: electrical);
end entity v_pulse;

architecture behaviour of v_pulse is
    function time2real(tt : time) return real is
    begin
    return time'pos(tt) * 1.0e-15;
    end time2real;

    constant slope:real:=pulse/time2real(tchange);

    quantity v across i through pos to neg;
    -- Signal used in CreateEvent process below
    signal pulse_signal : real := initial;
begin

    v==pulse_signal'slew(slope);

    CreateEvent : process
    begin
    wait until domain = time_domain; -- Run process in Time Domain only
    pulse_signal <=pulse;
    end process CreateEvent;

end architecture behaviour;

 

--------------------------------------------------------------------------------

 

--5. Simulation Results

 

 

 

<<Previous<<        >>Next>>         Top^

 

School of Electronics and Computer Science, University of Southampton, Highfield, Southampton S017 1BJ, United Kingdom