# 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:

1. NGspice for circuit simulation

   - NGspice

   - NGspice manual

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, with FFT or FOURIER post processing

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

## 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:

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)

## Run NGspice from SLiCAP

The function ngspice2traces returns

1. A dictionary with traces, the swept variable name, and the swept variable units.

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

2. A dictionary with operating point information

## 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')
    30
    31# dB magnitude plot
    32sl.plot("VampQspiceM", "dBmag($V_{out}$)", "semilogx", mag , xName=x_name,
    33        xUnits=x_units, yUnits="dB")
    34
    35# Phase plot
    36sl.plot("VampQspiceP", "arg($V_{out}$)", "semilogx",
    37        phase, xName=x_name, xUnits=x_units, yUnits="deg")

## 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")

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)

## Fourier and FFT post processing functions

### Transient analysis with parameter substitution

    128# TRAN with parameter substitution
    129simCmd   = "TRAN 0.1u 20u"
    130params   = [("V_p", 0.5)]
    131names    = {"V_out": "V(out)"}
    132tran, x_name, x_units  = sl.ngspice2traces("cir/" + fileName, simCmd, names, parList=params)
    133sl.plot("VampQspiceSIN", "$V_{out}$", "lin", tran , xName=x_name, xUnits=x_units,
    134        yUnits="V")

### FFT

    136# FFT
    137simCmd   = "TRAN 1u 512u 64u 10n"
    138params   = [("V_p", 0.5)]
    139# Eliminate DC component from output
    140names    = {"V_AC_rms": "V(c2)-{}".format(str(OPinfo['V_c2']))}
    141postProc = """
    142set specwindow=gaussian
    143set specwindoworder=8
    144FFT V_AC_rms
    145"""
    146options  = {"RELTOL": 1e-6}
    147mag, phase, x_name, x_units  = sl.ngspice2traces("cir/" + fileName, simCmd, names,
    148                                                 postProc=postProc, saveLog=True,
    149                                                 traceType='magPhase',
    150                                                 parList=params, optDict=options)
    151sl.plot("VampQspiceFFT", "$V_{out}$", "log", mag , xName=x_name, xUnits=x_units,
    152        yUnits="V", xLim=[10e3, 1e6], yLim=[2e-7, 2])

### FOURIER analysis

    154# FOURIER
    155simCmd   = "TRAN 1u 512u 64u 10n"
    156params   = [("V_p", 0.5)]
    157# Eliminate DC component from output
    158names    = {"V_AC": "V(c2)-{}".format(str(OPinfo['V_c2']))}
    159postProc = "FOURIER 100k V_AC"
    160options  = {"RELTOL": 1e-6}
    161results  = sl.ngspice2traces("cir/" + fileName, simCmd, names, optDict=options,
    162                             postProc=postProc, saveLog=True, parList=params)

The output of the Fourier analysis is found in the simulation log file. This file is stored in the `txt/` subfolder in the project directory:

    30Fourier analysis for v_ac:
    31  No. Harmonics: 10, THD: 0.0956761 %, Gridsize: 200, Interpolation Degree: 1
    32
    33Harmonic Frequency   Magnitude   Phase       Norm. Mag   Norm. Phase
    34-------- ---------   ---------   -----       ---------   -----------
    35 0       0           0.000171655 0           0           0
    36 1       100000      1.93936     69.4189     1           0
    37 2       200000      0.000319617 98.4118     0.000164805 28.9929
    38 3       300000      0.00179569  -63.728     0.000925916 -133.15
    39 4       400000      8.48382e-05 -9.8195     4.37454e-05 -79.238
    40 5       500000      0.000320931 -101.64     0.000165483 -171.06
    41 6       600000      3.59352e-05 -53.792     1.85294e-05 -123.21
    42 7       700000      6.66689e-05 -141.37     3.43767e-05 -210.78
    43 8       800000      1.09723e-05 -92.645     5.65768e-06 -162.06
    44 9       900000      1.44773e-05 177.593     7.46498e-06 108.174