Lets write a virtual machine.

Prelude to Part 2 – Why do computers use binary? – Transistor Transistor Logic.

In this part, we’re going to begin adding more useful instructions to our virtual machine. In order to do this, we’re going to be working on a lower level with binary numbers, and so it’s important that we understand binary. Why is binary so heavily used in computing? What is it? How can we perform arithmetic on binary numbers?

In most cases, with modern high level languages available to software engineers and developers, there is rarely a need to use binary directly. There are however, a number of problems which can only be solved efficiently and effectively with an understanding of how binary works, and one such problem is the design of a new CPU. Designing a new CPU is effectively what we are doing as we write our virtual machine. It’s important then, that we’re all have sufficient understanding of binary in order to proceed.

Why Binary?

To understand why binary is important in computing, we need a little understanding of the electronics behind what our computers are doing. So I’m going to give you a brief walk-through some of the fundamental principals of the electronics involved inside your computers, and most importantly, inside your CPU. Please note again that I am brushing over a lot of detail for the sake of the intuition that it brings. Please, if you are an electronics expert, be aware that I know where I’ve miss-spoken, or missed a detail, I did so intentionally…

All modern computers are made possible because of a single electrical component called a Transistor. The transisitor allowed us to develop a technology in digital electronics known as TTL, which stands for Transistor-Transistor-Logic. There are several variants of this technology, and so modern computers, using a more recent variant, aren’t really considered to be TTL devices any longer. Just as with our CPU model from the previous part, I’m going to be brushing over a lot of the detail here in the interests of brevity, however, the fundamental concepts of TTL still apply for modern computers. We’re going to think of modern CPU’s as TTL devices here for the sake of the intuition that it brings, and again, I would welcome you to explore the intricacies later, if it suites you.

Lets get started then, by looking at this electrical component called a transistor.
Just as with all other electronic components, there are a large range of transistors available, but perhaps the most well known from a packaging perspective, looks like this:

This little package of plastic with three wires protruding from it, contains a tiny piece of silicon which has been chemically modified to be, or behave as, a transistor. The CPU and Memory devices inside a computer, similarly, contain silicon usually with millions or billions of transistors on them.

If you were designing a circuit with a transistor in it, you’d draw a schematic diagram containing this, or a similar symbol:

The symbol shows three connections to reflect the three wires on the physical transistor above. They are labeled from left to right as ‘C’ for collector, ‘B’ for base and ‘E’ for emitter. The transistor behaves as a kind of switch, but unlike the kinds of switches you may be used to, such as light switches, or keyboard keys, the transistor is not operated mechanically by pressing it with a finger. Instead, the transistor is turned on or off electrically. When electrical current is applied to the ‘Base’ wire of the transistor, it is turned on, allowing current to flow between the collector and the emitter. When there is no current at the Base, the switch is turned off, and current is not able to flow from the collector to the emitter.

This simple on or off behavior is a limited view of the properties of a transistor, but it is sufficient to reflect what we need to understand for now. The two states of the transistor (switch) being on or off, are represented in software as ones and zeros, where one reflects the ‘on’ state, and zero reflects the ‘off’ state. Ones and Zeros being the basic digits of the binary numbering system.

Essentially, every wire inside a digital electronic circuit, such as a computers main logic board, either has current flowing through it, or it doesn’t. We map these two states to ones and zeros, giving rise, ultimately, to the binary numbering system in our software.

TTL – Logic Gates

In our model computer from the previous part, the computer was divided into two major components. We had a memory component to store information, and the CPU component (driven by a clock) to perform logic (including arithmetic) on that information. Each of these behaviors is constructed on an electrical level using transistor based circuits. In this part, we’ll take a look at how some of the logic is performed in circuitry.

All of the instructions that a CPU is able to perform are built up from simple circuits known as “Logic Gates.” Logic Gates are building blocks from which more sophisticated circuits are built. There are several of these gates, but in this part we’re going to look at just three of them, named ‘AND’, ‘OR’ and ‘NOT’.

The “AND” gate is by far the simplest of the gates, it’s circuit looks like this:

At this point you may be thinking “Hey! That’s just a transistor. What are you trying to pull?” and if you were thinking that, good for you, you’re right. The transistor behaves as a logical “AND” operation because the emitter only has current if both the collector “AND” the base have current. To restate that another way, if we consider the collector and the base pins as inputs A and B respectively, and the emitter as the output, then we can say that the output will be one only when both inputs A and B are one. If either input A or B is zero, then the output will also be zero.

The table below, known as a “truth table” describes the behavior of an “AND” gate in binary terms.
All combinations of inputs being on or off (one or zero) are presented in the left two columns, and the output for each combination appears in the output column. As you’ll note, the only combination for which the output is a one, is when both inputs are one.

Input A (Collector)Input B (Base)Output (Emitter)
000
010
100
111

Lets take a look at another logic gate circuit, the “OR” gate.

There are two important things to note about the above circuit. First, the collector for both transistors is connected directly to current, meaning that they are always on. The second, is that the emitter for both transistors are connected to each other, and to the output.

If we were to apply current to the base of the transistor on the left (labeled as ‘Input A’), then current could flow from the collector of that transistor to it’s emitter, ultimately powering the output…

Similarly, if we were to apply power to the base of the right transistor instead, then power would flow from it’s collector to it’s emitter, and power on the output.

Essentially, if we set either Input A “OR” Input B to one, then the output will be one.
Here’s the truth table for the “OR Gate” circuit.

Input AInput BOutput
000
011
101
111

The astute among you may have noticed something about this “OR Gate” circuit. If both inputs are one, then so too is the output. That’s okay! This is how an “OR Gate” functions, and it stands true that when both inputs are powered the statement “if InputA OR Input B” still evaluates true. There is however another logic gate which behaves as an OR operation, but does not accept both inputs being on. It’s called an “XOR” (for exclusive OR), and will only output a one if exclusively input A, or exclusively input B is one.

TTL – Logic Shorthand.

The third gate that I’d like to look at today is called the “NOT Gate” or sometimes it’s referred to as an “inverter”, however, I’m not going to draw the circuit for it. The reason that I’m not drawing the circuit is that while it is still a simple circuit, understanding it requires a more nuanced understanding of the physics of electricity which, if I tried to explain to you, would potentially undo some of the intuition that we’ve learned thus far. Instead, I’ll introduce you to a form of logic gate short-hand which is used when designing circuits.

As the number of components required to draw the circuits for logic gates increases, rather than draw them each out, circuit designers substitute alternative symbols for the gates which form a sort of schematic short-hand…

The two symbols in the above image, represent the “AND Gate” and “OR Gate” that we’ve explored already. The two wires indicated to the left of each symbol represent the two inputs, and the wire on the right represents the output.

The new “NOT Gate” that we’re going to examine uses the following symbol.

The “NOT Gate” has only one input. When the input is set to zero, the output will be one, and when the input is set to one, the output will be zero. This is why the gate is sometimes referred to as an inverter. I’m including the “Not Gate” here because it’s a critical component of the way that we create memory devices, which we’ll look at in a moment. First, lets see the truth table for this not gate…

InputOutput
01
10

This is the simplest of the truth tables that we’ve seen so far, and by now, should require no further explanation. I include it here for reference.

TTL Memory

We’ve now taken a look at some of the internal workings of the CPU, in the form of logic operations, lets take a look at the internal workings of the memory device.
Consider the following circuit…

The above circuit contains a single AND Gate, which you’ll recall is really just a single transistor. The first input (Input A) is tied directly to power, just as we did with the collector pins in our OR Gate circuit. However, the output of this AND Gate is fed back into Input B.

If we set input B to one, by applying current, then the AND condition becomes true and the output would change to one.

Because the output feeds back into the B input, we could dis-continue the current that we supply to input B, but input B would remain one, because the output of the gate is now feeding it.

At this point, we can say that this circuit “remembers” that we applied current at Input B, even after we discontinue that current, because of the feedback to Input B from the output. This is fundamentally how computer memory functions.
This circuit can be in either the zero state, before we apply current to Input B, or in the one state after, being able to store either a zero or a one. This is sufficient storage for a single binary digit, otherwise called a ‘bit’.

As you’ll see when we look at the binary numbering system in a moment, numbers in binary use up digits far more quickly than decimal numbers do. In other words, binary numbers get long. Computer memory devices have many repetitons of the memory circuit to provide ample storage for a large number of bits.

Just for perspective, a computer with 16GB of ram has 16 * 1024 * 1024 * 1024 * 8 = 137,438,953,472 bits of storage, and therefore around 137.5 billion little memory circuits, not unlike the one we just explored.

There’s a little more to the memory circuit than we’ve seen so far however. Suppose you turned on this memory circuit in order to set the memory bit to a one. Then you wish to store a different value, in this case zero, in that memory bit. Currently our circuit has no mechanism to reset it to a zero. We need an additional two logic gates to provide a ‘reset’ to our memory bit…

Hold your breath and here we go…
Essentially this memory circuit functions in the same way as our previous memory circuit, except that the output feeding back to Input B goes through another AND Gate along the way. The second AND Gate is enabled when Input B is enabled because it’s own first input is connected to a NOT Gate. The NOT Gate being powered off, defaults to outputting a one, and so the circuit activates the same was as before. Until, that-is, the Reset input is set to one, at which point the output of the NOT Gate becomes zero, and therefore becomes a zero to the input on the second AND Gate, shutting off the supply back to Input B on the first AND Gate.

Don’t worry if this doesn’t entirely make sense on your first pass, the circuit is becoming a little more complex and you’ve already had a lot to take in. Besides, if you really need to understand this, the video referenced above explains it very clearly with animation, so check it out, and consider hitting the subscribe button 🙂

Still not up for watching the video? That’s okay. It’s sufficient to know at this point that we are now able to store ones and zeros in our memory circuit at will. In the next part, we’ll look more closely at the binary numbering system it’s self. The intention being that in the subsequent part, we can return to our source code armed with more knowledge, and make our virtual machine just a little bit more useful.