Interface with NGspice
SLiCAP offers a simple interface for running basic NGspice simulations and plot graphs from within your SLiCAP application. It requires installation of:
NGspice for circuit simulation
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:
OP: operating point analysis
DC: DC sweep
AC: small-signal frequency-domain analysis
TRAN: Time-domain analysis
DC TEMP: Temperature sweep
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
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")
Fig. 1 KiCAD NGspice schematic with SLiCAP SPICE symbols and automatically updated operating point information.
Please notice:
The value field of independent sources carries the SPICE specification of simulation signals (see:
V1
andV2
)A standard library (no binned IC models) is included with an
.INC
directiveA binned IC device model library is included with a
.LIB
directiveThe library path is relative to the project directory
All circuit parameters (here:
C_c
) must be assigned a value with a.param
directiveThe 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")
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')
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")
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")
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")
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")
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}$")
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")
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")
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)