SPICE (Simulation Program with Integrated Circuit Emphasis) is an analog electronic circuit simulator. SPICE can cover from the board-level circuit design to integrated circuits. It has originally developed at the Electronics Research Laboratory of the U.C. Berkeley in 1973. Since the update of Berkeley SPICE stopped at version 3f5 in 1993, many improved descendants came out from various vendors to the public.

There are many SPICE variations available HSPICE, PSPICE, NGSPICE, LTSPICE, SPICE OPUS, etc. BUT I chose NGSPICE basically it is free to the public, and it has good compatibly with KiCAD which is my main circuit design tool. HSPICE and PSPICE are the industrial majority, but it is a far too expensive for a hobbyist such as myself. LTSPICE is only for WINDOWS OS and I want to stick to Linux where I can go much more flexible in scripting and batch run.

How to run NGSPICE?

Basically, NGSPICE is a command line tool. So, everything is supposed to be done by typing commands and dealing with text files in the shell environment.  There are some GUI integrations, as in KiCAD or Qucs-S.  You will be temped to use GUI first because it looks easier at the beginning. But, you will be back to command-line mode in the end for the more flexibility and more options. Actually, the GUI is not really useful unless you understand how it works in command-line mode. Or, you will find the GUI tools are not so convenient compared to command-line mode. Most people do mixed way - Generate netlists using KiCAD or Qucs-S and include into input file to the simulation to run it in command-line. Therefore, learning NGSPICE the original way is inevitable.

Once you installed NGSPICE, Typing ngspice on the shell prompt will lead you to the interactive mode. Then, you can source the input file.

% > ngspice
*****************************************
some messages ...
*****************************************
ngspice 1 -> source input_file.cir

Once you've got into NGSPICE interactive mode, you can apply the various kinds of simulation requests and output requests. You can interactively test and get the result from the circuit described in the input file. But, my favourite way to run the simulation is to prepare the input_file with all the controls included and run the sim as below.

% > ngspice input_file.cir

This can run the sim all at once and either you can make it get interactive mode or you can run and exit to shell after the simulation. It is all depends on how to put controls in inpuit_file.cir. You can even run a batch simulation using the controls of NGSPICE or using the shell scripts.

Input File

An input file is an input to SPICE simulation. It contains circuit description - they call this SPICE netlist - and controls. The control block in the input file includes analysis requests, data output controls, and some flow controls.

The typical structure of an input file looks like this.

.title “Simulation Title”

* netlist
* subcircuits
* models

.control

* analysis requests and output controls

.endc

.END

SPICE input file is not case-sensitive. Uppercase or lowercase does not make any difference. It only helps readability. Any line that starts with an asterisk is a comment line. The first line has to be filled with a title or comment. An empty first line will cause an error and fail the simulation. NGSPICE supports HSPICE style, but putting all the control statements inside .control and .endc. give you more options and flexibility. You can have all the native NGSPICE features inside the control block. Finally, don't forget to put .end at the end of the simulation.

SPICE Netlist

A SPICE netlist is a circuit description in plain ASCII text. It just describes how the elements are connected to each other. It is like a text version of a circuit diagram. The format to describe an element connection is as below.

element_name <connected_nodes> <element_value or model_name> <optional_parameters>

The element name must start with a specific alphabet letter assigned to each types of electric elements. Here are some alphabet letters for the frequently used circuit elements.

Table 1. Frequently used netlist elements
First LetterElement TypeExample
RResistorRout out 0 1K
LInductorL12 vin node_1 12M
CCapacitorC10 3 0 1u
DDiodeDmod in GND 1N4001 Area=3.0 IC=0.2
QBJTQ1 nC nB nE QMOD IC=0.5
MMOSFETM0 nD nG nS nb MOSN L=5u W=2u
VIndependent Voltage SourceVCC PWR GND DC 15
VIN N1 N2 0.001 AC 1 SIN(0 1 1MEG)
IIndependent Current SourceISRC 23 21 AC 0.3333
EVCVS (Voltage Controlled Voltage Source)Evc0 n1 n2 ref+ ref- 2M
FCCCS (Current controlled Current Source)FDRV n1 n2 VSEN 5
* vsen is a name of a voltage source
GVCCS (Voltage Controlled Current Source)GOUT 2 0 in 0 2M
HCCVS (Current Controlled Voltage Source)HX0 5 17 VZ 0 0.5K
Xsubcircuits

Xop in1 in2 out opamp_1

.subckt opamp_1 plus minus output
 * subcircuit netlists here
.ends

Any kind of string - numbers or text - can be used for the nodes, but number 0 is reserved for common global ground. The voltage controlled dependent sources - VCVS, VCCS - will have reference nodes right after the list of the connected nodes, and the current controlled dependent source - CCVS, CCCS will have a name of independent voltage source where the reference current will be sensed. An independent voltage source is the only way to check the current through it in SPICE simulations. So, whenever, you need to check the current on the branch, you want to put a zero-value independent source on the branch. 

Let's look at an example.

Fig 1. A BJT test circuit

The following is the netlist of the circuit depicted in Fig 1

.global vcc
vcc vcc 0 dc 10
vin in 0 dc 1.7
rb in nb 100k
rc vcc out 5k
qa out nb 0 model_name

Everything obvious already. .global vcc means set vcc node global. This simply means vcc is common to everywhere, hence can be connected from everywhere.  As depicted in Fig 1, the ground node is set to 0, which is the global node as well. The BJT element qa must use model name instead of element value. There are several ways to provide model to the active elements.

Applying models

You can use models that are provided by NGSPICE. These models are general and minimal models based on several different kinds of modelling method and application case. For the device-specific models, you'd better download them from the manufacture website. The models provided by the manufactures are much more specific and realistic in general. However, in case you want to model, for example, a transmission line to mimic a copper path on a PCB board, you can use NGSPICE default models with some good parameters to reach a reasonable realistic result.

.title The first simulation
*** first_sim.cir

*** Netlist starts here
.global vcc
vcc vcc 0 dc 10
vin in 0 dc 1.7
rb in nb 100k
rc vcc out 5k
qa out nb 0 QMOD
.model QMOD NPN level=1 BF=90

*** control starts here
.control
op
print v(out)
.endc

.end

In the list above, NGSPICE level 1 model is applied to the netlist of Fig 1 and some controls for the simulation are included. In the .model statement, QMOD is a model name. You can put any name you like, but this name must match with the one on the qa element line. NPN is the type of the BJT. BF=90 is the parameter that means Forward Beta parameter for the BJT.

In the control block, there is only one analysis request. The command op request the simulator to calculate quiescent operating points of the circuit. And, the print command prints out requested data. In the above example, it only prints out the voltage of the 'out' node. Create a file named "first_sim.cir" and run "ngspice first_sim.cir" then you will get into interactive mode with the simulation result right above the first prompt as below.

...
No. of Data Rows : 1
v(out) = 5.361446e+00

nqspice 1 -> _

Generating Signals

For the transient analysis, You need to generate signals, such as sine wave, square wave, pulse, etc. Most of SPICE provide signal generation command. You can simply put this command at the end of any independence source.

Fig 2. SPICE Signal generation commands

Let's attach a sine wave signal generator to the vin in the netlist of Fig 1.

.global vcc
vcc vcc 0 dc 10
vin in 0 dc 1.7 ac 1 SIN(1.7 1 10K 0 0)
rb in nb 100k
rc vcc out 5k
qa out nb 0 QMOD
.model QMOD NPN BF=90

On the vin independent voltage source line above, three different kinds of signal sources are added and these are independent of each other. dc 1.7V is for dc analysis and OP, and ac 1 is for ac analysis. In ac 1, 1 does not really mean 1V, rather 1 is more like a scale factor. SIN(1.7 1 10K 0 0) is added for the transient analysis. The added sine wave has 1.7V dc offset, 1V amplitude and 10KHz frequency. No delay, no decay, no phase shift applied.

Using subcircuits

A subcircuit is a block of netlist packed for the frequent usage in a circuit. Subcircuits are similar to functions in a programming language. It reduces time and labour by reducing repetitive tasks for the circuit designers. Also, it is another way to apply a model to electronic compounds such as circuit modules or integrated circuits. For example, for an opamp, you use a subcircuit instead of a model.

Let's try to make a subcircuit to the BJT in the Fig 1. They don't usually use subcircuits for a BJT, but I want to show that it is also possible.

Fig 3. Simple small signal BJT model and its SPICE subcircuit equivalent

Fig 3 shows a simple BJT small signal model and its SPICE subcircuit equivalent. The voltage source vsen is added to sense the reference current for CCCS Fce. And beta is the current gain of the BJT. The input file that uses this subcircuit looks like the following.

.title The subcircut example
* first_sim_w_subckt.cir
.global vcc vcc vcc 0 dc 10 vin in 0 dc 1.7 ac 1 SIN(1.7 1 10K 0 0) rb in nb 100k rc vcc out 5k xqa out nB 0 my_bjt beta=90 rpi=2.5K ro=150K .subckt my_bjt C B E beta=100 rpi=3K ro=100K rpi B nSen {rpi} vsib nSen E 0 Fce C E vsib {beta} ro C E {ro} .ends .control ac dec 10 1 1e6 let vgain = v(out) / v(in) meas ac voltage_gain find vgain at=1K .endc .end

In the above input file, the subcircuit definition begins with .subckt and my_bjt is a subcircuit name. C, B, E are the terminals of the subcircuit. And, there are some parameters after the list of terminals.  The values inside { and } will substitute the parameters listed on .subckt statement. These values can be overwritten when the subcircuit is invoked in the netlist. The first letter of a subcircuit element name must be x, so xqa is used for the BJT subcircuit element name in the example above. 

Save the input file into first_sim.w_subckt.cir and run ngspice first_sim.w_subckt.cir, then you will get

...
No. of Data Rows : 61
voltage_gain        =  -4.248623e+00
ngspice 1 ->

This matches the hand calculation result from below.

\begin{align} A_v &= {v_{out} \over v_{in} }\\[10pt] &= -\beta\cdot{R_C\parallel r_o \over R_B + r_\pi }\\[10pt] &= -90\cdot{150K\Omega\parallel 5K\Omega \over 100K\Omega + 2.5K\Omega }\\[10pt] &= -4.248623131 \end{align}

This subcircuit only works for ac analysis because the model in Fig 3 is a small-signal model. And, its frequency response is meaningless because it will be infinite.

Controls

You can put analysis requests and output controls in the control block. NGSPICE also provides language-like control statements such as while, dowhile, repeat, foreach, and more.

Analysis requests

To get meaningful results from the simulation, you must give instruction to the simulator about what to simulate or how to simulate. These instructions are called analysis requests. There are many types of request - DC, AC, Transient, Pole-Zero, Distortion, Noise, and more. Some basic and frequently used requests are listed in Table 2.
Table 2. Basic Analysis Requests
Analysis RequestsSpice Context
Operating Point Analysisop
DC Transfer Function

dc srcnam vstart vstop vincr [src2 start2 stop2 incr2]

dc VIN 0.25 5.0 0.25
dc VDS 0 10 .5 VGS 0 5 1
dc VCE 0 10 .25 IB 0 10u 1u
dc RLoad 1k 2k 100
dc TEMP -15 75 5

Small-Signal AC Analysis

ac ( dec | oct | lin ) np fstart fstop

ac dec 10 1 10K
ac dec 10 1K 100MEG
ac lin 100 1 100HZ

Transient Analysis

tran Tstep Tstop [ Tstart [ Tmax ] ] [ UIC ]


tran 1ns 100ns
tran 1ns 1000ns 500ns
tran 10ns 1us

Output controls

There are control commands to control how to manipulate the simulation results. You can print, plot and save to a file for the further data manipulation or analysis. For the arguments of the output controls, v(n1<,n2>) specifies the voltage between n1 and n2. If n2 is not specified, then it regarded as the voltage between n1 and ground. I(vsens) specifies the current flowing in the independent voltage source named vsens. The current from the positive terminal to the negative terminal is regarded as positive. vm(node), vp(node) mean the voltage magnitude and phase, each. vdb(node) means voltage magnitude in decibel.

Control functionSPICE context
print out the result in tabular form.

print prtype ov1 <ov2 ... ov8>

print tran v(4) i(vin)
print dc v(2) i(vsrc) v(23, 17)
print ac vm(4, 2) vr(7) vp(8, 3)

plot the graphs.

plot expr1 [vs scale_expr1] [expr2 [vs scale_expr2]] [all] [allv] [alli] <other options>

Plot v(o), I(vsens)
Plot v(out) vs I(vbs)
Plot all

gnuplotgnuplot [file] [extrs]
writewrite [file] [exprs]

Using models from the manufacture

Let's do a more realistic simulation with a model from a manufacture. Download 2N2222A NPN BJT spice model from here. This model is written in PSPICE parameter format. You need to set the compatibility to PSPICE to use this model. Create a file name ".spiceinit" at home directory of your account and add text as following.

set ngbehavior=ps
Then, change the name of the downloaded file, 2N2222A.LIB.TXT to 2N2222A.LIB. If you look into the file, you can see the .model line.
.MODEL Q2n2222a npn
...
Now, all you have to do is include the LIB into the input file and use the model name Q2n2222a on qa element line.
.title The first simulation

*** Netlist starts here
.global vcc
vcc vcc 0 dc 10
vin in 0 dc 1.7 ac 1 SIN(1.7 1 10K 0 0)
rb in nb 100k
rc vcc out 5k
qa out nb 0 Q2n2222a

.inc 2N2222A.LIB

*** control starts here
.control
...
.endc

.end

Flow control

ngspice provides language-like flow control. You can use while, dowhile, repeat, foreach, if-then clause. Even, you can use goto and label. continue and break statements are also provided. Let's add some flow control and analysis requests to the netlist with manufacture's BJT model to get some realistic results. The input file below is to running all 3 kinds of simulations at the same time, and repeat flow control is used for the DC sweep to get a curve trace for the BJT 2N222A.
.title The first simulation

*** Netlist starts here
.global vcc
vcc vcc 0 dc 10
vin in 0 dc 1.7 ac 1 SIN(1.7 1 10K 0 0)
rb in nb 100k
rc vcc out 5k
qa out nb 0 Q2n2222a

.inc 2N2222A.LIB

*** control starts here
.control
set xbrushwidth=3
let vinn = 0.7
repeat 5
  alter vin $&vinn
  dc vcc 0 20 10mv
  let vinn = vinn + 0.1
end
plot (-dc1.I(vcc)) (-dc2.I(vcc)) (-dc3.I(vcc)) (-dc4.I(vcc)) (-dc5.I(vcc))
reset
tran 10n 500u
plot v(in) v(out)
reset
ac dec 10 1 1e6
set units=degrees
plot db(out)
plot ph(out)
.endc

.end

The input file above repeated 5 times of dc sweep, with the vin values increased by 0.1 for each run. You need to put negative sign to I(vcc) since the examining current on the collector to emitter branch is coming out of vcc source - current flow into the plus terminal of vcc source is positive.  Once you run 5 dc analysis, you can retrieve the 5 different data groups dc1, dc2, … , dc5. You can run all different types of analysis at the same time by putting reset command at the end of each analysis.

The followings are the plots that will pop up after the simulations are done.

Fig 4. DC sweep simulation for 5 different vin voltages
Fig 5. Waveforms from Transient analysis
Fig 6. Bode plot - gain in dB vs. frequency in log scale
Fig 7. Bode plot - phase in degree vs. frequency in log scale

The default NGSPICE plots are quite basic and limited in usage. You can get better plot manipulation with GNUplot.

Using Gnuplot

GNUplot is a popular plot application. To use GNUplot, you can use the gnuplot command instead of the plot command. There is an additional argument that needs to be passed.

.control
…
reset
ac dec 10 1  1e6
set units=degrees
gnuplot ac_sim db(out) ph(out)
exit
.endc

With the NGSPICE basic plot, all the plots disappear once you exit the interactive mode. On the other hand, the GNUplot stays even if you exit the interactive mode. Now, you can put exit command to get out of the interactive mode after the simulation completed.  Another good news is the fact that the gnuplot command above will save plot control file ac_sim.plt and data file ac_sim.dat each when it draws the plot so that you can modify the ac_sim.plt to make the plot nicer. By keeping these .plt and .data files you can redraw later anytime you want.  Here is the list of ac_sim.plt file that modified for dual plot with some better labels. Fig 8 is the plot result of the modified ac_sim.plt

# ac_sim.plt
# generated when by gnuplot ac_sim db(out) ph(out) 
# in the input file "first_sim.cir"

...(ommitted)

# This original plot is commented.
# plot 'ac_sim.data' using 1:2 with lines lw 3 title "db(out)",\
# 'ac_sim.data' using 3:4 with lines lw 3 title "ph(out)"

# modified for multi-plot
set multiplot
set size 1, 0.5
set origin 0, 0.5
set yrange [0:20]
set ylabel "gain, dB"
set title "The AC Analysis - gain"
plot 'ac_sim.data' using 1:2 with lines lw 3 lt rgb "blue" title "db(out)"
set origin 0, 0
set yrange [0:180]
set ylabel "phase, degree"
set title "The AC Analysis - phase"
plot 'ac_sim.data' using 3:4 with lines lw 3 lt rgb "red" title "ph(out)"
unset multiplot
Fig 8. The GNU plot output

Using Gtk Analog Wave viewer(gaw)

If you want something like AvanWaves that comes with hspice, you can try gaw - Awaves are much better but not a free tool. gaw lets you use the cursor line to check the value of every each point on the graph, and you can have as many as panels you want. To use gaw, you need to write the simulation data into a file.

.control
set xbrushwidth=3
let vinn = 0.7
repeat 5
  alter vin $&vinn
  dc vcc 0 20 10mv
  let vinn = vinn + 0.1
end
write dc_sim.out (-dc1.I(vcc)) (-dc2.I(vcc)) (-dc3.I(vcc)) (-dc4.I(vcc)) (-dc5.I(vcc))
…
exit
.endc

Usage of the write command is similar to the gnuplot command. Once you run the simulation input file, the example above will save the simulation result into “ac_sim.out” file. Now you can open “ac_sim.out" file with gaw waveform viewer. Select the panel to draw on first, and then choose the signals to draw the graph.

Fig 9. gaw plot panel

You can use two cursors to get the differences as shown in Fig 9.

Conclusion

NGSPICE is as good as other spice simulators, or better in a way. NGSPICE is a handy tool for hobbyists who want to build a precision analog circuits such as amplifiers, RF frontend, and some sensor frontends. And, also, it is a reliable tool for one who aims to check the interface between analog front-end and the digital I/O's. The usage shown here is just a basic introduction. I hope this will be a little clue to the hobbyist who wants to get into the SPICE world. There are a lot more features to enjoy. Even in the analog only applications, switch models, transmission line models, Monte Carlo simulation, noise sources, Non-linear dependent sources, and more. NGSPICE also covers mixed-mode(analog-digital altogether simulation mode) applications. NGSPICE supports XSPICE mixed-mode and Behavioural Modelling, Verilog-A Compact Device Models, and Digital Device Models and Digital simulation, etc. Vast application area you can play with.

References

  1. Ngspice User's Manual (ngspice release version) - version 44plus. Holger Vogt, Giles Atkinson, Paolo Nenzi, December 29th, 2024
  2. NGSPICE home - tutorials, introductory videos, downloads, news, etc.
  3. gnuplot homepage - all the information and gnuplot download
  4. xschem-gaw github - gaw download and install