Work with subcircuits

../_images/colorCode.svg

Although SLiCAP is intended to be used for relatively small circuits, it supports unlimited netsing of subcircuits. The function makeCircuit() recursively expands subcircuits until the final circuit comprises devices with stamp models only (see Work with models). Working with subcircuits, usually simplifies the design and is strongly recommended in the following cases:

  1. The circuit consists of a number of topologically identical building blocks comprising multiple devices

    • Examples are the built-in subcircuits for small-signal models of active devices and operational amplifiers.

      Below the built-in definition (in SLiCAPmodels.lib) of the small-signal model of a MOS transistor

      88* MOSFET
      89.subckt M d g s b gm=1m gb=0 go=0 cgs=0 cdg=0 cgb=0 cdb=0 csb=0 ; default values
      90Gm d s g s g value={gm}
      91Gb d s b s g value={gb}
      92Go d s d s g value={go}
      93Cgs g s {cgs}
      94Cdg d g {cdg}
      95Cgb g b {cgb}
      96Cdb d b {cdb}
      97Csb s b {csb}
      98.ends
      
  2. The circuit consists of a number of building blocks that comprise multiple parameters with complex expressions

    • Examples are the built-in subcircuits for MOS devices with EKV model equations that relate their small-signal parameters to geometry parameters (e.g. W, L) and operating point parameters (e.g ID).

      Below the built-in definition (in SLiCAP.lib) of the small-signal model of an CMOS18 NMOS transistor with its small-signal circuit parameters related to its geometry and operating conditions.

      134.subckt CMOS18N drain gate source bulk W={W} L={L} ID={ID}
      135* EKV model of transistor without bulk resistances
      136* Voltage dependency of bulk capacitances not modeled
      137* Operating in forward saturation region
      138* 
      139M1 drain gate source bulk CMOS18N
      140
      141.model CMOS18N M 
      142+ gm      = {g_m} 
      143+ go      = {g_o} 
      144+ gb      = {g_b}
      145+ cgs     = {c_gs}
      146+ cdg     = {c_dg}
      147+ cgb     = {c_gb}
      148+ cdb     = {c_db}
      149+ csb     = {c_sb}
      150.param
      151* device equations EKV model
      152* See Binkley: "Tradeoffs and Optimization in Analog CMOS Design"
      153+ IC_CRIT = {1/(4*(N_s_N18*U_T)*(Theta_N18+1/L/E_CRIT_N18))^2}
      154+ g_m     = {ID/(N_s_N18*U_T*sqrt(IC*(1+IC/IC_CRIT)+0.5*sqrt(IC*(1+IC/IC_CRIT))+1))}
      155+ g_o     = {g_CLM + g_DIBL}
      156+ g_CLM   = {ID/(VAL_N18*L*sqrt(L/L_min_N18))} ; 
      157+ g_DIBL  = {-g_m*DVTDIBL_N18*(L_min_N18/L)^DVTIDBLEXP_N18}
      158+ g_b     = {(N_s_N18-1)*g_m}
      159+ c_gs    = {(2-x)/3*W*L*C_OX_N18 + CGSO_N18*W} 
      160+ c_dg    = {CGSO_N18*W}
      161+ c_gb    = {W*L*C_OX_N18*(1+x)/3*(N_s_N18-1)/N_s_N18+CGBO_N18*2*L}
      162+ c_db    = {CJB0_N18*W*LDS_N18}
      163+ c_sb    = {CJB0_N18*W*LDS_N18}
      164+ IC_i    = {ID*L/W/I_0_N18}                ; Initial estimate of inversion coefficient
      165+ IC      = {IC_i*(1+3*(IC_i/IC_CRIT))**(1/3)} ; Correction for short-channel effects
      166+ V_GS    = {2*N_s_N18*U_T*ln(exp(sqrt(IC_i*(1+IC_i/IC_CRIT)))-1) + Vth_N18}
      167+ f_T     = {g_m/2/pi/c_iss}
      168+ c_iss   = {c_gs+c_dg+c_gb}
      169+ x       = {(sqrt(IC + 0.25) + 1.5)/(sqrt(IC + 0.25) + 0.5)^2}
      170.ends
      
  3. The circuit consists of an anti-series connection of two identical circuits.

    • These circuits belong to the class of ‘balanced circuits’. Nodal voltages and branch currents in these circuits can be resolved in differential-mode and common-mode quantities. SLiCAP can decompose a balanced circuit into common-mode and differential-mode equivalent circuits. To this end, it needs pairing information for nodes and branches, which is easy to provide if the balanced circuit consists of the anti-series connection of two identical sub circuits. For more information see: Work with balanced circuits

../_images/colorCode.svg

SLiCAP output displayed on this manual page, is generated with the script: subcircuits.py, imported by Manual.py.

 1#!/usr/bin/env python3
 2# -*- coding: utf-8 -*-
 3
 4"""
 5subcircuits.py: SLiCAP scripts for the HTML help file
 6"""
 7import SLiCAP as sl
 8
 9###############################################################################
10# work with subcircuits
11###############################################################################

Subcircuit expansion

Below a schematic diagram of a circuit with nested subcircuits. The main circuit comprises one subcircuit “XA: bigAmp”. This subcircuit comprises two identical “smallAmp” subcircuits “X1” and “X2”.

../_images/hierarchy.svg

Subcircuit “XA” has two parameters that can be set by the parent circuit: “A_i”, the voltage gain of “X1” and “R_o” the output resistance of both “X1” and “X2”. The resistance of “R1” of “XA” is defined symbolically as \(R_i\) to which no numeric value has been assigned.

Below the manually created netlist of the circuit.

 1hierarchy
 2
 3V1 1 0     V      value={V_s}
 4R1 1 2     R      value={R_s}
 5R2 4 0     R      value={R_L}
 6XA 2 0 4 0 bigAmp A_i={A_i} R_o={R}
 7
 8.param V_s=1 R_s=50  R=50
 9
10.subckt bigAmp inP inN ouP outN A_i=30 R_o=30
11R1 inP inN           R        value={R_i}
12X1 inP inN 3    0    smallAmp A_v={A_i} R_o=40
13X2 3   0   outP outN smallAmp A_v=10 R_o={R_o}
14
15.subckt smallAmp inP inN outP outN A_v={A} R_o=10
16E1 1 outN inP inN E value={A_v}
17R1 1 outP         R value={R_o}
18.ends ; smallAmp
19
20.ends ; bigAmp
21
22.end

At the creation of a circuit object, SLiCAP expands or “flattens” this circuit. It converts the hierarchically structured netlist into a circuit that comprises devices with stamp models only (see Work with models). The MNA matrix equation will be constructed from this “flattened” circuit.

Reference designators of expanded circuit elements

The table below shows the element data of the expanded circuit.

The first column of this table shows the reference designators of the expanded circuit elements.

important

The reference designator of a subcircuit element in its expanded parent is that of the subcircuit element appended with _<refX>, where refX is the reference designator of the parent subcircuit.

Hence, the reference designator of “R1” in “XA” becomes “R1_XA” in its expanded parent.

This naming process is recursive, so “R1” in “X1” of “XA” becomes “R1_X1_XA” in the expanded parent of “XA”.

Table 7 Expanded netlist data of hierarchy.cir

ID

Nodes

Refs

Model

Param

Symbolic

Numeric

V1

1 0

V

value

\(V_{s}\)

\(1\)

dc

\(0\)

\(0\)

dcvar

\(0\)

\(0\)

noise

\(0\)

\(0\)

R1

1 2

R

value

\(R_{s}\)

\(50\)

dcvar

\(0\)

\(0\)

noisetemp

\(0\)

\(0\)

noiseflow

\(0\)

\(0\)

dcvarlot

\(0\)

\(0\)

R2

4 0

R

value

\(R_{L}\)

\(R_{L}\)

dcvar

\(0\)

\(0\)

noisetemp

\(0\)

\(0\)

noiseflow

\(0\)

\(0\)

dcvarlot

\(0\)

\(0\)

R1_XA

2 0

R

value

\(R_{i XA}\)

\(R_{i XA}\)

dcvar

\(0\)

\(0\)

noisetemp

\(0\)

\(0\)

noiseflow

\(0\)

\(0\)

dcvarlot

\(0\)

\(0\)

E1_X1_XA

1_X1_XA 0 2 0

E

value

\(A_{i}\)

\(A_{i}\)

R1_X1_XA

1_X1_XA 3_XA

R

value

\(40\)

\(40\)

dcvar

\(0\)

\(0\)

noisetemp

\(0\)

\(0\)

noiseflow

\(0\)

\(0\)

dcvarlot

\(0\)

\(0\)

E1_X2_XA

1_X2_XA 0 3_XA 0

E

value

\(10\)

\(10\)

R1_X2_XA

1_X2_XA outP_XA

R

value

\(R\)

\(50\)

dcvar

\(0\)

\(0\)

noisetemp

\(0\)

\(0\)

noiseflow

\(0\)

\(0\)

dcvarlot

\(0\)

\(0\)

Expanded circuit node names

The name of a connecting node of a subcircuit, will be that of the connecting parent node. Unconnected nodes remain local. Their node names will be modified in a similar way as the element reference designator.

The name of a local node becomes <nodeID>_<refX>, where nodeID is the node name in the subcircuit, and refX is the reference designator of the subcircuit in the parent circuit.

Expanded circuit parameter names

Parents can pass parameter values or expression to child subcircuits. If so, all instances of this parameter in element expression in the subcircuit, in parameter definitions in the subcircuit, and in model definitions in the subcircuit, are substituted with the value or expression passed by the parent.

Parents can only pass parameters that are declared a value or expression in the subcircuit definition. See line 10 from the netlist above:

10.subckt bigAmp inP inN ouP outN A_i=30 R_o=30

Hence, the parent can pass a value or expression to \(A_i\) and to \(R_o\) to an instance of the subcircuit “bigAmp”.

All other parameters will remain local and all instances of local parameters in subcircuit element expressions, in subcircuit parameter definitions, and in subcircuit model definitions, will be substituted with a new variable:

new_param = sympy.Symbol(str(old_param) + "_" + refX)

# new_param is the new parameter name
# old_param is the old parameter name (type = sympy.Symbol)
# refX is the reference designator of the subcircuit in the parent circuit

The tables below show how this applies to the circuit from above.

Table 8 Expanded circuit parameter definitions

Name

Symbolic

Numeric

\(V_{s}\)

\(1\)

\(1\)

\(R_{s}\)

\(50\)

\(50\)

\(R\)

\(50\)

\(50\)

Table 9 Expanded circuit undefined parameters

Name

\(A_{i}\)

\(R_{L}\)

\(R_{i XA}\)

Subcircuit creation

Aside from using built-in subcircuits, the user can create subcircuits. There are two ways to create subcircuits:

  1. Include a subcircuit definition in a circuit file

  2. Create a subcircuit definition in a library file and store it in the lib/ folder of the project directory

Both methods can be done by manually editing circuit .cir files, the latter one can also be performed with a schematic capture program.

The manual approach is elucidated above.

Create subcircuits with KiCAD

KiCAD supports hierarchical design, but the approach differs from the subcircuit approach outlined above. SLiCAP subcircuits must be created as follows:

  1. Create a KiCAD schematic for the subcircuit and put a command with the subcircuit decraration on the schematic. The subcircuit definition for “smallAmp” looks as depicted below.

    ../_images/smallAmp.svg
  2. With the .subckt directive on the schematic, makeNetlist() creates a library file in the lib/ folder in the project directory. The name of this file defaults to the subcircuit name with extension .lib.

    15# Create a subcircuit library file: <sl.ini.user_lib_path>smallAmp.lib
    16smallAmp = sl.makeCircuit("kicad/smallAmp/smallAmp.kicad_sch")
    

    The contents of lib/smallAmp.lib is:

    1smallAmp
    2.subckt smallAmp inP inN outP outN A_v={A} r_o={R}
    3E1 1 outN inP inN E value={A_v}
    4R1 1 outP R value={r_o} noisetemp=0 noiseflow=0 dcvar=0 dcvarlot=0
    5.ends
    6.end
    

    Important

    SLiCAP library files are like circuit netlists. The first line is taken as title and the last line must be .end.

  3. Now create the subcircuit bigAmp. Use a 4-pin subcircuit symbol for smallAmp, or create a symbol yourself. Don’t forget to include the library with smallAmp.lib.

    ../_images/bigAmp.svg
    1. The subcircuit symbol must have four pins and the pin sequence must be according to the subcircuit definition: “inP”, “inN”, “outP”, “outN”. The SLiCAP KiCAD symbol Xamp4 can be used for this purpose, it has the correct pin sequence.

    2. Parameters to be passed to the subcircuit must added as symbol properties. The property name is the parameter name and the value can be any because it will be overruled by the definition in the .subckt directive.

    The following instruction creates the bigAmp library file.

    18# Create a subcircuit library file: <sl.ini.user_lib_path>bigAmp.lib
    19bigAmp = sl.makeCircuit("kicad/bigAmp/bigAmp.kicad_sch")
    

    The contents of lib/bigAmp.lib is:

    1bigAmp
    2.subckt bigAmp inP inN outP outN A_i=30 R_o=30
    3.lib smallAmp.lib
    4R1 inP inN R value={R_i} noisetemp=0 noiseflow=0 dcvar=0 dcvarlot=0
    5X1 inP inN 1 0 smallAmp A_v={A_i} r_o=40
    6X2 1 0 outP outN smallAmp A_v=10 r_o={R_o}
    7.ends
    8.end
    
  4. Now create the main circuit and again use the Xamp4 symbol for bigAmp.

    ../_images/mainAmp.svg

    The following instruction creates the main circuit object .

    17# Create the main circuit
    18mainAmp = sl.makeCircuit("kicad/mainAmp/mainAmp.kicad_sch")
    

    The netlist of cir/mainAmp.cir is:

    1mainAmp
    2.lib bigAmp.lib
    3.param V_s=1 R_s=50 R=50
    4R1 1 2 R value={R_s} noisetemp=0 noiseflow=0 dcvar=0 dcvarlot=0
    5R2 3 0 R value={R_L} noisetemp=0 noiseflow=0 dcvar=0 dcvarlot=0
    6V1 1 0 V value={V_s} noise=0 dc=0 dcvar=0
    7XA 2 0 3 0 bigAmp A_i={A_i} R_o={R}
    8.end
    

    The expanded circuit data and the parameter definitions are as above:

    Table 10 Expanded netlist data of mainAmp.cir

    ID

    Nodes

    Refs

    Model

    Param

    Symbolic

    Numeric

    R1

    1 2

    R

    value

    \(R_{s}\)

    \(50\)

    noisetemp

    \(0\)

    \(0\)

    noiseflow

    \(0\)

    \(0\)

    dcvar

    \(0\)

    \(0\)

    dcvarlot

    \(0\)

    \(0\)

    R2

    3 0

    R

    value

    \(R_{L}\)

    \(R_{L}\)

    noisetemp

    \(0\)

    \(0\)

    noiseflow

    \(0\)

    \(0\)

    dcvar

    \(0\)

    \(0\)

    dcvarlot

    \(0\)

    \(0\)

    V1

    1 0

    V

    value

    \(V_{s}\)

    \(1\)

    noise

    \(0\)

    \(0\)

    dc

    \(0\)

    \(0\)

    dcvar

    \(0\)

    \(0\)

    R1_XA

    2 0

    R

    value

    \(R_{i XA}\)

    \(R_{i XA}\)

    noisetemp

    \(0\)

    \(0\)

    noiseflow

    \(0\)

    \(0\)

    dcvar

    \(0\)

    \(0\)

    dcvarlot

    \(0\)

    \(0\)

    E1_X1_XA

    1_X1_XA 0 2 0

    E

    value

    \(A_{i}\)

    \(A_{i}\)

    R1_X1_XA

    1_X1_XA 1_XA

    R

    value

    \(40\)

    \(40\)

    noisetemp

    \(0\)

    \(0\)

    noiseflow

    \(0\)

    \(0\)

    dcvar

    \(0\)

    \(0\)

    dcvarlot

    \(0\)

    \(0\)

    E1_X2_XA

    1_X2_XA 0 1_XA 0

    E

    value

    \(10\)

    \(10\)

    R1_X2_XA

    1_X2_XA 3

    R

    value

    \(R\)

    \(50\)

    noisetemp

    \(0\)

    \(0\)

    noiseflow

    \(0\)

    \(0\)

    dcvar

    \(0\)

    \(0\)

    dcvarlot

    \(0\)

    \(0\)

    Table 11 Expanded circuit parameter definitions

    Name

    Symbolic

    Numeric

    \(V_{s}\)

    \(1\)

    \(1\)

    \(R_{s}\)

    \(50\)

    \(50\)

    \(R\)

    \(50\)

    \(50\)

    Table 12 Expanded circuit undefined parameters

    Name

    \(A_{i}\)

    \(R_{L}\)

    \(R_{i XA}\)

Display circuit data on HTML pages and in LaTeX documents

The report module Create reports, discusses how HTML snippets and LaTeX snippets can be created for variables, expressions, equations and tables.

As a matter of fact, tables and figures on this page are created with this module:

24# Generate RST snippets for the Help file
25rst = sl.RSTformatter()
26
27rst.elementData(cir, caption="Expanded netlist data of hierarchy.cir").save(
28    "table-hierarchy-expanded")
29rst.parDefs(cir, caption="Expanded circuit parameter definitions").save(
30    "table-hierarchy-pardefs")
31rst.params(cir, caption="Expanded circuit undefined parameters").save(
32    "table-hierarchy-params")
33rst.elementData(mainAmp, caption="Expanded netlist data of mainAmp.cir").save(
34    "table-mainamp-expanded")
35rst.parDefs(mainAmp, caption="Expanded circuit parameter definitions").save(
36    "table-mainamp-pardefs")
37rst.params(mainAmp, caption="Expanded circuit undefined parameters").save(
38    "table-mainamp-params")
../_images/colorCode.svg