The SPICE program (Simulated Program with Integrated Circuit Emphasis) performs simulations of analog electronic circuits. The reference version (spice 2g6, 1983) is written in FORTRAN. A more recent version (spice 3, 1985) is written in C. Many commercial simulation software uses the SPICE calculation engine, adding additional functions.
We are interested here in the free versions of spice, ngspice and SpiceOpus, which are based on spice3f5. These two programs read a text file comprising a description of the circuit and various commands. The PLOT command allows you to draw curves but does not export as a file. The PRINT command is used to export the results to a text file. We will use a python function allowing to read the files produced by PRINT.
This document explains the principle of using SPICE (ngspice) through a simple example. Only the most common functions are described.
2. Circuit description
We consider as an example the following circuit:
It is first necessary to number the nodes of the circuit, by assigning the number 0 to the mass. This circuit has 3 nodes (not counting the mass).
A voltage source is defined by the following syntax:
Vxxx N1 N2
The name begins with V and xxx is a name that identifies the source if there is more than one. N1 and N2 are the two nodes of the source: the voltage applied is by convention VN1-VN2.
A resistance is defined by:
Rxxx N1 N2 VALUE
The value is given in Ω. To enter a very small or very large value, one of the multiples defined in the following table can be used:
The syntax of capacitors and inductors is similar, with names starting with C and L. respectively.
Here is the description of the previous circuit with numerical values for the passive components:
V1 1 0 R1 1 2 10K C1 2 0 100N L1 2 3 10M R 3 0 10
The description of this circuit is not entirely complete. It is also necessary to specify the type of voltage source, which depends on the type of analysis that is to be carried out.
3. Continuous analysis
To perform a continuous analysis, the DC option must be added to the sources. For example, a source applying a direct voltage of 1 volt will be defined by:
V1 1 0 DC 1V
The V symbol attached to 1 is not taken into account by SPICE: it is added to make the code more readable.
Continuous scanning is defined by the .DC command. the commands are preceded by a period. You can also place all the commands (without the dots) between the two commands .CONTROL and .ENDC.
The .DC command actually performs a sweep of voltages or dc currents, that is to say having a constant value. Here is its minimal syntax:
.DC SRC1 START1 STOP1 INC1
SRC1 designates the source (voltage or current) whose value we want to vary. START1 is the start value, STOP1 the end value and INC1 the increment.
The description of the circuit and the commands are placed in a .cir file. Here is the complete .cir file for the previous circuit, with DC analysis:
RLC Circuit V1 1 0 DC R1 1 2 10K C1 2 0 100N L1 2 3 10M R 3 0 10 .CONTROL DC V1 0 10 1 PLOT V(2) .ENDC .END
The first line is the name of the circuit. The last line should be .END. PLOT command has been added.
To process this file with ngspice, open ngspice from a console then run
The curve plotted is the voltage of node 2 as a function of the swept voltage (v-sweep), which here is the voltage of the source V1. In the present case, the curve obtained is linear because the circuit is linear.
To retrieve the data in python (or in Mathematica), we will replace the PLOT command with the PRINT command, redirecting the output to a file:
RLC Circuit V1 1 0 DC R1 1 2 10K C1 2 0 100N L1 2 3 10M R 3 0 10 .CONTROL DC V1 0 10 1 PRINT V(2) > export-2.txt .ENDC .END
In this case, we can run the file with ngspice without opening the ngspice console (batch mode with the -b option):
The resulting text file contains one column for v-sweep, one column for v (2). The lectureSpicePrint.py python function described in Reading SPICE outputs with Python allows you to read this file (in some cases the exported values are complex).
from lectureSpicePrint import lectureSpicePrint from matplotlib.pyplot import * data = lectureSpicePrint("export-2.txt") V1 = data["v-sweep"] V2 = data["v(2)"]
Here is the plot of V2 against V1:
figure(figsize=(6,6)) plot(V1,V2) xlabel("V1 (V)") ylabel("V2 (V)") grid()
4. Sinusoidal analysis
To perform a frequency analysis in sinusoidal mode, you must declare a source in AC mode, with the following syntax:
Vxxx N1 N2 AC (AMP) (PHASE)
Parameters in parentheses are optional. AMP is the amplitude of the sinusoidal source (in V or in A). Its default value is 1. This parameter is irrelevant for linear circuits. PHASE is the phase of the source, zero by default.
The analysis is defined by the .AC command, whose syntax is:
.AC BALAYAGE NB_POINTS FSTART STOP
FSTART and the departure frequency, FSTOP the arrival frequency (in Hertz). There are three types of scanning:
- DEC: scan by decade, with NB_POINTS points by decade.
- OCT: scan by octave, with NP_POINTS by octave.
- LIN: linear sweep, with NP_POINTS over the entire frequency range.
Here is the .cir file for a frequency analysis from 100 Hz to 100 kHz:
RLC Circuit V1 1 0 AC 1 R1 1 2 10K C1 2 0 100N L1 2 3 10M R 3 0 10 .CONTROL AC DEC 100 100 100K PRINT VDB(2) VP(2) > export-3.txt .ENDC .END
In this case, the exported data is the voltage of node 2 in decibels and the phase in radians. If the node is the output of a filter, we directly obtain the gain in decibels because the input has an amplitude of 1. The phase obtained is the phase shift with respect to the input since the latter has a phase of 0.
We can also export the voltage in the form of complex numbers, with:
The plot of the Bode diagram directly in ngspice is obtained with the commands:
PLOT VDB(2) PLOT VP(2)
Here is the plot of Bode’s diagram in python:
data = lectureSpicePrint("export-3.txt") freq = data["frequency"] gdb = data["vdb(2)"] phi = data["vp(2)"] figure(figsize=(10,10)) subplot("211") plot(freq,gdb) xscale('symlog') xlabel('f (Hz)') ylabel('GdB') grid() subplot("212") plot(freq,phi) xscale('symlog') xlabel('f (Hz)') ylabel('phi (rad)') grid()
In some cases, the magnitude that we want to study is a current. To obtain the current in a branch, it is necessary to add a DC voltage source of zero voltage in this branch. Here is for example how to get the current in the inductor:
RLC Circuit V1 1 0 AC 1 R1 1 2 10K C1 2 0 100N L1 2 3 10M R 3 4 10 VIL 4 0 DC 0 .CONTROL AC DEC 100 100 100K PRINT I(VIL) > export-4.txt .ENDC .END
The source VIL has been added between the resistor R and the ground, to obtain the current in this branch. The I (Vxxx) syntax is used to obtain the current flowing through a voltage source. The decibel and phase output does not work on ngspice for current; we must therefore export the voltage in the form of complex numbers. The calculation of the gain and the phase shift is done without difficulty with python:
import numpy data = lectureSpicePrint("export-4.txt") freq = data["frequency"] iL = data["i(vil)"] gdb = 20*numpy.log10(numpy.absolute(iL)) phi = numpy.angle(iL) figure(figsize=(10,10)) subplot("211") plot(freq,gdb) xscale('symlog') xlabel('f (Hz)') ylabel('GdB') grid() subplot("212") plot(freq,phi) xscale('symlog') xlabel('f (Hz)') ylabel('phi (rad)') grid()
5. Transient analysis
Transient analysis, more generally called temporal analysis, consists in obtaining the voltages as a function of time. For this, it is necessary to precisely define the time signals delivered by the sources. The different types of signals are:
- PULSE: pulse source, used in particular for step responses and impulse responses.
- SIN: sinusoidal source, possibly with exponential decrease.
- EXP: exponential source.
- PWL: linear source by interval.
- SFFM: sinusoidal source with frequency modulation.
We will describe the PULSE source in detail. Consult SPICE for other sources.
The syntax of a pulse source is:
Vxxx N1 N2 PULSE(V1 V2 TD TR TF PW PER)
The parameters are:
- V1: minimum value.
- V2: maximum value.
- TD: delay after time zero.
- TR: rise time.
- TF: descent time.
- PW: pulse width.
- PER: pulse repetition period, which must be greater than PW.
The transient analysis is obtained with the .TRAN command, the syntax of which is:
.TRAN PAS TSTOP
PAS is the time step, TSTOP the final time.
It may be necessary to specify certain initial conditions. For this, we use the .IC command. You can also add the IC option to some components.
Let’s see how to get the response to a step with the studied circuit:
RLC Circuit V1 1 0 PULSE(0 1 0 0 0 10M 20M) R1 1 2 10K C1 2 0 100N L1 2 3 10M R 3 4 10 VIL 4 0 DC 0 .CONTROL IC V(2)=0 TRAN 1U 20M PRINT V(2) > export-5.txt .ENDC .END
data = lectureSpicePrint("export-5.txt") time = data["time"]*1000 V2 = data["v(2)"] figure(figsize=(15,5)) plot(time,V2) xlabel("t (ms)") ylabel("V2 (V)") grid()