ahkab.ekv

Partial implementation of the EKV 3.0 MOS transistor model

The EKV model was developed by Matthias Bucher, Christophe Lallement, Christian Enz, Fabien Théodoloz, François Krummenacher at the Electronics Laboratories, Swiss Federal Institute of Technology (EPFL), Lausanne, Switzerland.

The Tecnical Report upon which this implementation is based is available here:

EKV Technical Report.

This module defines two classes:

Features:

  • EKV model implementation, computation of charges, potentials, reverse and forward currents, slope factor and normalization factors.
  • Calculation of trans-conductances based on the charge-driven approach.
  • N/P MOS symmetry
  • Rudimentary temperature effects.

The Missing Features:

  • Channel length modulation,
  • Reverse Short Channel Effect (RSCE),
  • Complex mobility degradation,
  • Transcapacitances,
  • Quasi-static implementation,

Patches to implement the above are welcome!

Note

The default values in the model are suitable for a generic 500nm feature-size CMOS process.

class ekv_device(part_id, nd, ng, ns, nb, W, L, model, M=1, N=1)[source]

EKV device

Parameters:

part_id : string
The element identifier, eg ‘M1’
nd : int
drain node
ng : int
gate node
ns : int
source node
nb : int
bulk node
L : float
element width [m]
W : float
element length [m]
M : int
multiplier (n. of shunt devices)
N : int
series mult. (n. of series devices)
model : ekv_model instance
The corresponding instance of ekv_mos_model

Selected methods: - get_output_ports() -> (nd, ns) - get_drive_ports() -> (nd, nb), (ng, nb), (ns, nb)

INIT_IFRN_GUESS = 1
g(op_index, ports_v, port_index, time=0)[source]

Returns the differential (trans)conductance rs the port specified by port_index when the element has the voltages specified in ports_v across its ports, at (simulation) time.

ports_v: a list in the form: [voltage_across_port0, voltage_across_port1, ...] port_index: an integer, 0 <= port_index < len(self.get_ports()) time: the simulation time at which the evaluation is performed. Set it to None during DC analysis.

get_drive_ports(op)[source]

Returns a tuple of tuples of ports nodes, as: (port0, port1, port2...) Where each port is in the form: port0 = (nplus, nminus)

get_netlist_elem_line(nodes_dict)[source]
get_op_info(ports_v)[source]

Information regarding the Operating Point (OP)

Parameters:

ports_v : list of lists
The voltages applied to all the driving ports, grouped by output port.

i.e.

[<list of voltages for the drive ports of output port 0>,
 <list of voltages for the drive ports of output port 1>,
 ...,
 <list of voltages for the drive ports of output port N>]

Usually, this method returns op_keys and the corresponding op_info, two lists, one holding the labels, the other the corresponding values.

In the case of MOSFETs, the values are way too many to be shown in a linear table. For this reason, we return None as op_keys, and we return for op_info a list which holds both labels and values in a table-like manner, spanning the vertical and horizontal dimension.

For this reason, each MOSFET has to have its OP info printed alone, not grouped as it happens with most other elements.

Returns:

op_keys : None
See above for why this value is always None.
op_info : list of floats
The OP information ready to be passed to printing.table() for arranging it in a pretty table to display.
get_output_ports()[source]
get_value_function(identifier)[source]
i(op_index, ports_v, time=0)[source]

Returns the current flowing in the element with the voltages applied as specified in the ports_v vector.

ports_v: [voltage_across_port0, voltage_across_port1, ...] time: the simulation time at which the evaluation is performed.

It has no effect here. Set it to None during DC analysis.
update_status_dictionary(ports_v)[source]
class ekv_mos_model(name=None, TYPE=u'n', TNOM=None, COX=None, GAMMA=None, NSUB=None, PHI=None, VTO=None, KP=None, XJ=None, LAMBDA=None, TOX=None, VFB=None, U0=None, TCV=None, BEX=None)[source]
get_device_temperature()[source]

Returns the temperature of the device - in K.

get_dvsmall_dismall(ismall, verbose=3)[source]

The Newton algorithm in get_ismall(...) requires the evaluation of the first derivative of the fixed point function:

dv/di = 1.0/(sqrt(.25+i)-.5) * .5/sqrt(.25 + i) + 1/sqrt(.25 + i)

This is provided by this module.

get_gmd(device, xxx_todo_changeme3, opdict=None, debug=False)[source]

Returns the drain-bulk transconductance or d(IDS)/d(VD-VB).

get_gmg(device, xxx_todo_changeme4, opdict=None, debug=False)[source]

Returns the gate-bulk transconductance or d(IDS)/d(VG-VB).

get_gms(device, xxx_todo_changeme2, opdict=None, debug=False)[source]

Returns the source-bulk transconductance or d(IDS)/d(VS-VB).

get_ids(device, xxx_todo_changeme, opdict=None, debug=False)[source]

Returns: IDS, the drain-to-source current (de-normalized), qs, the (scaled) charge at the source, qr, the (scaled) charge at the drain.

get_ip_abs_err(device)[source]

Absolute error to be enforced in the calculation of the normalized currents.

get_ismall(vsmall, ip_abs_err, iguess=None, debug=False)[source]

Solves the problem: given v, find i such that:

\[v = ln(q) + 2q\]
..math::
q = sqrt(.25 + i) - .5

The Newton Method is used inside.

get_leq_virp(device, xxx_todo_changeme1, Vp, Leff, ifn)[source]
get_voltages(vd, vg, vs)[source]

Performs the VD <-> VS swap if needed. Returns: (VD, VG, VS) after the swap CS, an integer which equals to:

+1 if no swap was necessary, -1 if VD and VS have been swapped.
get_vp_nv_nq(VG)[source]

Calculates and returns: VP, the pinch-off voltage, nv, the slope factor, nq, the charge linearization factor.

get_vsmall(ismall, verbose=3)[source]

Returns v according to the equations: q = sqrt(.25 + i) - .5 v = ln(q) + 2q

ismall2qsmall(ismall, verbose=0)[source]

i(f,r) -> q(f,r) Convert a source/drain scaled current to the corresponding normalized charge.

print_model()[source]

All the internal parameters of the model get printed out, for visual inspection. Notice some can be set to None (ie not available) if they were not provided in the netlist or some not provided are calculated from the others.

qsmall2ismall(qsmall)[source]

q(f,r) -> i(f,r) Convert a source/drain scaled charge to the corresponding normalized current.

set_device_temperature(T)[source]

Change the temperature of the device.

Correspondingly, VTO, KP and PHI get updated.

setup_scaling(nq, device)[source]

Calculates and stores in self.scaling the following factors: Ut, the thermal voltage, Is, the specific current, Gs, the specific transconductance, Qs, the specific charge.

class scaling_holder[source]