Analog Circuit Simulator

In my final semester of my undergraduate degree I took a course on modelling and simulation. For the final project in this course we were asked to investigate a general engineering topic that was of interest to us. I chose to look at how variations in transistor parameters affected the output slew rate of a simple operational amplifier circuit. Along the way to solving this problem I made a simple analog circuit simulator!

In order to simulate this problem I needed to model resistors, capacitors, voltage source,  current sources, and bipolar junction transistors (both PNP and NPN). Modelling resistors, voltage sources, and current sources is pretty simple. An electrical circuit composed of these elements can be solved as a simple linear system. The matrices can be set up in the well-known Ax=b format, and the voltages at each node in the circuit, as well as the current through the sources, can be solved using your favourite matrix-solving method (I used QR decomposition as the A matrix tends to be sparse for larger networks).

I solved for the current through capacitors using a first order approximation of the voltage derivative. BJTs were a little trickier. I used the Ebers-Moll model, which is non-linear, so I had to use a non-linear solving method (Newton-Raphson) to determine the current at each of the three nodes for each transistor. However, once I got my head around the non-linear solver the simulator came together pretty quickly.

And now, here are some results that I got using the simulator to prove it works.

First of all, here is a simulation of a simple common-emitter (with 0.5 gain) circuit. The LTspice schematic of the circuit is shown in the figure below (with the node numbers labelled in red). This is a good proof of concept circuit because it shows that the simulation can handle resistors, capacitors, BJTs, and voltage sources (both DC and sinusoidal).

LTspice common emitter circuit with nodes labelled.

The LTspice output for the circuit is shown here:

LTspice’s output for the common emitter amplifier.

My software produced this output (which I graphed using Python). It matches LTspice’s results pretty closely! I was able to solve the common-emitter circuit using only 3-4 Newton-Raphson iterations per step. The 800 steps (80 ms @ 1 ms/step) took approximately 1.3 seconds to run.

The output from my software. It matches LTspice pretty closely!

Once I was pretty sure it worked, I decided to simulate a simple operational amplifier circuit. This is made out of two differential pairs (double-ended followed by single ended, a PNP gain stage, and NPN buffer stage).

LTspice simple op-amp circuit with nodes labelled.

To demonstrate the op-amp worked with feedback I hooked it up as both a buffer and inverting amplifier (0.5 gain). The results for these two configurations are shown below.

The op-amp worked when configured as a buffer (shows that the simulator can accommodate feedback).
The op-amp configured as a 0.5 gain amplifier.

The op-amp simulations took a lot longer to run than the common-emitter example did. Each iteration converged after approximately 1000 Newton-Raphson steps and the total simulation took around 40 seconds to run.

This is just a little overview of the project, I hope it was interesting. If you are interested in more details on the implementation, feel free to send me an e-mail.