The CPU (Central processing unit) is the brain of all systems, it takes instructions as simple as electric variations and performs complex tasks by running electricity through circuits, but, how do they do it?

Not even engineers knows exactly how a CPU works, indeed, I’ve meet very few people (Developer, analyst, Architect or IT) who knows exactly how electricity is evaluated in a logical way to perform concrete calculations in order to run a digitally written program.

Can you even imagine how your computer performs a Node javascript file execution? I bet not…

The beginning

There were a man who thought the basics, his name is George Boole, a XIX century mathematician who introduced the well-known “Boolean algebra“; this, ladies and gentlemen, is the birth of the computation as we know it.

The Boolean algebra lets us to perform different logic calculations with boolean data (ones and zeros, can you make it simpler?), and, in a practical way (with many steps) allows complex arithmetic and logical operations.

Taking boolean logic, some copper and a semiconductor (i guess you know how that works), we can create logic gates.

Logic gates controls the electric flow between the systems anode and cathode based on an input, so, using logic gates we can define when, where and in what case electricity will pass through the circuit.

Logic gates are physical devices who implements boolean functions, there are 3 basic logical gates:

AND

The AND gate takes two bits as input and lets electricity pass through if both bits are true.

This logic gate behaves according to the following truth table

OR

The OR gate, it takes two bits as input and lets electricity pass through if at least one of those bits is true.

NOT

Last but not least there’s the NOT gate, also known as inverter, it gets 1 bit as input and outputs the opposite.

So, with this three logic gates we can build all other gates such NOR (OR + NOT), NAND (AND + NOT), XOR (NAND + NOR), etc.

Just for fun, NAND and NOR are functionally complete, this means that you can build any other logic gate by using just them.

Back to the topic, we need the basic arithmetic unit, a counter, using this logical gates and mixing them together a half adder can be built.

In this case, we have 2 bits in and 1 bit out plus carry (C in the graphic), but there’s some information lost after the operation, if we stack two of these making the carry of the first one join the second adder’s carry with an OR gate, and the output of the first half adder feed the second’s B port we happen to have 2 bits in and 1 bit out plus carry who takes control of the carry, we are adding two numbers!!

this is what we call, a fully adder.

Of course, with 1 bit we can count just to 1, so we need more.

Gimme new numbers

With 1 bit (0 or 1) we can represent just 2 numbers, with 2 bits we can represent 4 numbers and with 3 bits 8 numbers, from 0 to 7; but, if we want to be able to count, we need more than that, to be able to represent the 10 numbers in the decimal scale we would need 4 bits of information, meaning this that we would be wasting 6 possible numbers (4 bits could represent 16 numbers instead), here base16 or Hexadecimal numbers comes to scene.

Now, with 4 bits we can have 16 hexadecimal units, so, from 0 to 15.

Now we have 4 bit long numbers, how do we add them? we need bigger adders, so, if we stack 4 full adders in a box and link them together by the carry, we will be able to perform 4bit operations (4+4 bits in, 4 bits out).

MUX and DEMUX

Adders are where the math lives and MUX (Multiplexers) and DEMUX (Demultiplexers) are were the logic does.

A multiplexer can be explained with “many come in, one goes out”, this device takes data from many channels and redirects the data flow of one of those chanels (selected by an input, AB in the graphic) to the main output wire (Y in the graphic), this lets the system choose, in this 4bits example, AB input selects which one of the 4 different inputs will be streamed to the circuit.

DEMUX does the opposite, it takes one data flow and forwards it through one channel of its choice, in this 4bit example, it’ll take the stream and, based on the S input, will send through one of the 4 available channels.

With this simple dispositives, we are able to manage the data flow based on the electric flow. This devices has 2 bit input (plus data), but we can manage our 4bit data flow by stacking 2 *MUXs together, we have built now a fully operational 4 bit plexers controlling the information flow, this is the control unit, the most important difference between your laptop and a calculator.

Fully arithmetic

Our processor can now add and take care of the data flow but it’s not a CPU yet, we need serious arithmetic, in a real CPU, arithmetic is controlled by two different units, the ALU (Arithmetic Logic Unit) who controls the integer calculations and the FPU (Floating point unit) who takes care of floating-point operations.

The ALU is no more than a circuit of logical gates that takes input, performs operations and outputs the results.

Stacking all that shit in a box and giving it a 8 bit input interface and a 4 bit output channel we will be able to perform complex operations like ADD, SUB, INC, DEC, POW, etc.

So, we have data, we send it to the multiplexer with the instruction we want to perform (do you know Assembly?), the instructions says what to do with the data to the MUX, the info is sent to the ALU with the instruction and suddenly 0100 0010 0011 (0x4 0x2 0x3 in hex or ADD 2, 3 in assembly) has become 5.

Negating

What about SUB 3, 4 ? we need negative numbers, how does negative numbers work in binary systems?

Easy, a negative number is no more than the complement of a positive one:

0001 => 1

1110 => -1

Lets push our data through some NOT gates and we are already negating our signed numbers.

Storing

We can process data but our system is not more than a complex calculator yet, we need to be able to store and process data in order to perform more complex operations and become a CPU, this is done with storing.

In CPUs we use SRAM or static RAM, this type of memory is managed by flip-flops, as easy as that.

Flip-flop switches are on or off. This kind of memory is bigger in size and smaller in capacity than RAM or HDD but is muuch more faster.

So, if we stack our output to the cache flip-flops and take our input from the same place when there’s something to get, we could do operations retrieving the output of previous executions, this is what a CPU does and those flip-flops stacks are the registers.

With this we have built a basic CPU, we now need an Address generator (a simple counter) and we will be able to store in the RAM too keeping track of the block.

So, now we can get some input data and an instruction, pass through the logic (MUX) selecting the operation we want to perform and send your info to the ALU, this module will execute the operations storing the output in the register (cache) and letting the system grab it from there again if the next instruction requires it (popping from the stack?).

This is how you build a CPU, hope it’s interesting.