Interface with NGspice

../_images/colorCode.svg

SLiCAP offers a simple interface for running basic NGspice simulations and plot graphs from within your SLiCAP application. It requires installation of:

  1. NGspice for circuit simulation

  2. KiCAD for creating circuit diagrams with symbols from the KiCAD SPICE symbol library

Supported analysis

The function ngspice2traces() creates SLiCAPplots.trace objects that can be plotted with the SLiCAPplots.plot() function.

ngspice2traces() supports:

  1. OP: operating point analysis

  2. DC: DC sweep

  3. AC: small-signal frequency-domain analysis

  4. TRAN: Time-domain analysis

  5. DC TEMP: Temperature sweep

  6. NOISE: small-signal frequency-domain noise analysis

Parameter stepping (including temperature: TEMP) is supported on all above analysis types.

KiCAD SPICE symbol library

The KiCAD SPICE symbol library provided with SLiCAP supports all NGspice devices with associated parameters. The SPICE symbol library location is set in the SLiCAP.ini file in the user home directory. Below the location with SLiCAP installed for user USR in Python environment ENV:

>>> import SLiCAP as sl
>>> sl.ini.ngspice_syms
/home/USR/ENV/lib/python3.12/site-packages/SLiCAP/files/kicad/SLiCAP

Important

NGspice netlist creation and simulation from within SLiCAP only works with SPICE symbols from the library mentioned above!

Don’t mix-up SLiCAP symbols and SPICE symbols in one schematic!

Example

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

1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4"""
5ngspice.py: SLiCAP scripts for the HTML help file
6"""
7import SLiCAP as sl
../_images/colorCode.svg

Schematic capture and netlist generation

makeCircuit() with keyword argument language=SPICE creates and returns a NGspice compatible netlist of a KiCAD schematic file:

 9# Create SPICE netlist
10fileName = "VampQspice"
11netlist  = sl.makeCircuit("kicad/" + fileName + "/" + fileName + ".kicad_sch", 
12                         language="SPICE")
KiCAD NGspice schematic

Fig. 1 KiCAD NGspice schematic with SLiCAP SPICE symbols and automatically updated operating point information.

Please notice:

  1. The value field of independent sources carries the SPICE specification of simulation signals (see: V1 and V2)

  2. A standard library (no binned IC models) is included with an .INC directive

  3. A binned IC device model library is included with a .LIB directive

  4. The library path is relative to the project directory

  5. All circuit parameters (here: C_c) must be assigned a value with a .param directive

  6. The netlist created from the KiCAD schematics is stored in the cir/ folder in the project directory

Netlist

"BJT voltage amplifier"
.inc lib/BC847.lib
.param C_c=18p
C1 c2 out 1u
C2 out 0 100p
C3 e2 0 200u
C4 in b1 1u
C5 c2 e1 {C_c}
Q1 c1 b1 e1 BC847
Q2 c2 c1 e2 BC847
R1 e2 0 1k noisy=1
R2 cc c2 2.7k noisy=1
R3 cc c1 82k noisy=1
R4 b1 e2 100k noisy=1
R5 out 0 10k noisy=1
R6 e1 0 1k noisy=1
R7 c2 e1 3k noisy=1
R8 in 1 2k noisy=1
V1 1 0 DC 0 AC 1 0 SIN 0 {V_p} 100k
.param V_p=1
V2 cc 0 DC 12
.end

Library

1.model BC847 NPN (Is=7.049f Xti=3 Eg=1.11 Vaf=62.79 Bf=374.6 Ise=68f Ne=1.576
2+               Ikf=81.57m Nk=.4767 Xtb=1.5 Br=1 Isc=12.4f Nc=1.835 Ikr=3.924
3+               Rc=.9747 Cjc=5.25p Mjc=.3147 Vjc=.5697 Fc=.5 Cje=11.5p
4+               Mje=.6715 Vje=.5 Tr=10n Tf=410.2p Itf=1.491 Xtf=40.06 Vtf=10)

Create traces

The function ngspice2traces returns a dictionarys with traces, the swept variable name, and the swept variable units.

In case of an AC analysis the function returns two dictionaries with traces instead of one.

DC sweep

Simulation command:

14# DC sweep
15simCmd  = "DC V2 6 12 1"

The dictionary with names is a mapping of NGspice variable names on plot legend variable names.

16names   = {"V_c2": "V(c2)", "V_e2":"V(e2)"}

The function ngspice2traces performs the simulation and returns the data:

17DC, x_name, x_units = sl.ngspice2traces("cir/" + fileName, simCmd, names)

In case of a DC sweep, the x-units are empty. They can be defined with the plot:

19# DC plot 
20sl.plot("VampQspiceDC", "DC voltages $V_{c2}$, $V_{e2}$ versus power supply", 
21        "lin", DC, xName=x_name, xUnits="V", yUnits="V")
../_images/VampQspiceDC.svg

AC analysis

23# AC simulation, dBmag and phase, stepped
24simCmd  = "AC DEC 50 5 10MEG" 
25stepCmd = "C_c LIN 2p 20p 10"
26names   = {"V_out": "V(out)"}
27mag, phase, x_name, x_units  = sl.ngspice2traces("cir/" + fileName, simCmd, 
28                                                 names, stepCmd=stepCmd, 
29                                                 traceType='dBmagPhase')
../_images/VampQspiceM.svg ../_images/VampQspiceP.svg

Transient analysis

39# TRAN simumlation, stepped
40simCmd  = "TRAN 1n 1u"
41stepCmd = "C_c LIN 2p 20p 10"
42names   = {"V_out": "V(out)"}
43tran, x_name, x_units  = sl.ngspice2traces("cir/" + fileName, simCmd, names, 
44                                           stepCmd=stepCmd)
45# Time plot
46sl.plot("VampQspiceT1", "Pulse $V_{out}$, stepped $C_c$", "lin", 
47        tran, xName=x_name, xUnits=x_units, xScale="u", yUnits="V")
../_images/VampQspiceT1.svg
49# TRAN simumlation, multiple traces
50simCmd  = "TRAN 1n 1u"
51names   = {"V_out": "V(out)", "V_in": "V(in)", "V_c2": "V(c2)"}
52tran, x_name, x_units  = sl.ngspice2traces("cir/" + fileName, simCmd, names)
53
54# Time plot
55sl.plot("VampQspiceT2", "Pulse $V_{out}$, $C_c$=18pF", "lin", tran, 
56        xName=x_name, xUnits=x_units, xScale="u", yUnits="V")
../_images/VampQspiceT2.svg

Change the netlist

50# Change the netlist: change pulse to sinewave with parameter V_p amplitude
51netlist = netlist.replace("PULSE 0 0.3 0 1n 1n 499n 1u", 
52                          "SIN 0 {V_p} 100k\n" +
53                          ".param V_p=1")
54f = open("cir/VampQspice.cir", "w")
55f.write(netlist)
56f.close()
57
58# TRAN simumlation, multiple traces and parameter stepping
59simCmd  = "TRAN 10n 20u"
60stepCmd = "V_p LIN 0.5 1 2"
61names   = {"V_out": "V(out)", "V_in": "V(in)", "V_c2": "V(c2)"}
62sine, x_name, x_units  = sl.ngspice2traces("cir/" + fileName, simCmd, 
63                                           names, stepCmd=stepCmd)
64
65# Time plot
66sl.plot("VampQspiceS", "Sine overdrive $V_{out}$, $C_c$=18pF", "lin", sine, 
67        xName=x_name, xUnits=x_units, xScale="u", yUnits="V")
../_images/VampQspiceS.svg

DC TEMP sweep

77# DC TEMP sweep
78simCmd  = "DC TEMP -55 125 5"
79names   = {"V_c2": "V(c2)", "V_e2":"V(e2)"}
80TMP, x_name, x_units = sl.ngspice2traces("cir/" + fileName, simCmd, names)
81
82# TEMP plot 
83sl.plot("VampQspiceTMP", "DC voltages $V_{c2}$, $V_{e2}$ versus temperature", 
84        "lin", TMP, xName=x_name, xUnits="Celsius", yUnits="V")
../_images/VampQspiceTMP.svg

NOISE analysis

86# NOISE analysis
87simCmd  = "NOISE V(out) V1 dec 50 5 10MEG"
88names   = {"S_vo": "onoise_spectrum", "S_vi": "inoise_spectrum"}
89NOISE, x_name, x_units = sl.ngspice2traces("cir/" + fileName, simCmd, names, 
90                                           squaredNoise=False)
91
92# NOISE plot 
93sl.plot("VampQspiceNOISE", "Noise input and output spectrum", 
94        "log", NOISE, xName=x_name, xUnits="Hz", yUnits="$V/\\sqrt{Hz}$")
../_images/VampQspiceNOISE.svg
 96# Total noise versus temperature
 97simCmd  = "NOISE V(out) V1 dec 50 5 10MEG"
 98stepCmd = "TEMP LIN -55 125 50"
 99names   = {"v_no": "onoise_total"}
100NOISETOT, x_name, x_units = sl.ngspice2traces("cir/" + fileName, simCmd, names, 
101                                              stepCmd=stepCmd, 
102                                              squaredNoise=False)
103# TOTAL NOISE plot 
104sl.plot("VampQspiceNOISETOT", "Total output noise versus temperature", "lin", 
105        NOISETOT, xName=x_name, xUnits="Celsius", yUnits="V", yScale="u")
../_images/VampQspiceNOISETOT.svg

Operating point information

Without parameter stepping an OP instruction returns a dictionary with name-value pairs. With parameter stepping, it returns a dictionary with traces that can be plotted with SLiCAPplots.plot().

107# Operating point analysis
108simCmd  = "OP"
109names   = {"V_c1": "V(c1)",
110           "V_b1": "V(b1)",
111           "V_e1": "V(e1)",
112           "V_c2": "V(c2)",
113           "V_e2": "V(e2)", 
114           "I_V2": "I(V2)"}
115
116OPinfo  = sl.ngspice2traces("cir/" + fileName, simCmd, names, stepCmd=None)
117
118for name in OPinfo.keys():
119    print(name, ":", OPinfo[name])

This yields:

V_c1 : 2.49185497
V_b1 : 1.76367933
V_e1 : 1.15679378
V_c2 : 4.29572571
V_e2 : 1.81259412
I_V2 : -0.00296938791

Typesetted:

121rst = sl.RSTformatter()
122head = ["Name", "Value"]
123rst.dictTable(OPinfo, head=head ,caption="Bias voltages").save("table-VampQ-opinfo")
Table 21 Bias voltages

Name

Value

V_c1

\(2.492\)

V_b1

\(1.764\)

V_e1

\(1.157\)

V_c2

\(4.296\)

V_e2

\(1.813\)

I_V2

\(-0.002969\)

Display operating point information in KiCAD schematic

The SLiCAP function backAnnotateSchematic() can be used to display parameter values and operating point information in a KiCAD schematic file and its svg and pdf image files. To this end, text fields with the keys from the OPinfo dictionary must be placed on the schematic. backAnnotateSchematic replaces these text fields with <name>:<OPinfo[name]>. The result is shown in Fig. 1. Please notice that the keys of the OPinfo dictionary equal those of the names dictionary.

125sl.backAnnotateSchematic("kicad/" + fileName + "/" + fileName + ".kicad_sch", 
126                         OPinfo)