Ben Eater (whose website can be found here), is the person responsible for getting me to decide to pursue computer engineering. Ben, thank you for your excellent YouTube series, which allowed me to realize what I wanted to do as a career. Your willingness to teach freely on the internet has changed my life.
When you tell someone you’ve built a computer, what they think you mean is you’ve taken various components and stuck them inside of a case, that then acts as a desktop PC. While yes, this can refer to putting together desktop computer parts to yield a complete machine, building a computer can also mean constructing an entire computer (using the loose definition of a computer) from scratch, using only logic ICs, insane amounts of wire, and lots of breadboards.
My goal with this project was to build a computer from scratch, to learn and understand at a low, almost transistor-level, the inner workings of a computer. I wanted answers to the questions of how does binary work? and how does a computer remember? Of course, I understood that I was going to be taking a digital logic class at some point during my time in academia, but I wanted to understand now, so I decided to purchase Ben Eater’s kit and construct an 8-Bit breadboard computer.
After six months of painstaking construction, debugging, breaking, re-starting, and rebuilding, this is the finished product:
To build a computer, you need to understand the core components that structure it. While some computers may be more complex, the minimum structure is going to require:
A clock to synchronize all parts of the system.
Registers to act as the lowest form of data storage.
An arithmetic logic unit to perform logical and mathematical computations.
Memory to store programs that will be run.
A program counter to keep track of where in the program execution the computer is at.
Control logic for allowing each component to interact with one another.
Of course, all these components need to be connected as well and that is why there is also a bus that acts as the main point of connection for everything in the system.
CPU clock circuit. Credit: Eater.net
The purpose of a clock in a computer is to keep everything in sync. When a computer is running, it is the time in-between clock pulses when data is moving around, and then all the signals should be settled in the desired state at the change of the clock pulse.
For this computer, there are two modes of operation: Adjustable mode, where the speed of the clock can be a variable-speed, continuous clock. Or manual pulse mode, where the operator presses a pushbutton to pulse the clock, making debugging and stepping through programs much simpler.
The A register circuit. Credit: Eater.net
Registers in a computer act as the smallest form of storage. They hold a single word of data and are not persistent between power cycles. Registers, however, are important because although they are the smallest form of memory in a computer, they are also the fastest. In the computer I built, there are five registers: the A register, B register, Memory address register, Instruction register, and Output register.
In this computer, the A and B registers are primarily used for storing the values that the ALU will utilize, with one of the most common instructions being summing the values of the A and B registers together, and storing the result back into the B register.
The schematic for the ALU circuit. Credit: Eater.net
The ALU is one of the most important components of a computer. In this design, the ALU is made to have only two operations, adding and subtracting. Whether to add or subtract is decided by one of the control signals, which toggles the ALU's operating mode.
One of the interesting things about the ALU is that when calling the ADD instruction, the ALU doesn't start doing anything. Its operation is static, and it is always adding the A and B registers together, rather the ADD instruction takes the output of the ALU and saves it, making it usable in the future.
The RAM circuit. Credit: Eater.net
Rando access memory (sometimes just called memory) is another type of memory that is larger than registers but is also much slower. RAM is what stores the program that we want to run, and the memory address register, is what stores the memory address, allowing us to choose where and when we want to access a specific point in memory. The memory address register (MAR), often simply increments by one, as a way to linearly step through the program, but the MAR can store any value in it and so we can navigate the memory in any way that a program needs.
In this build, the memory is the largest limiting factor to the power of the machine, as the computer only has sixteen <em>bytes</em> of memory. That is so much smaller than anything we see today, and it limits the machine to not being able to do much more than calculate the Fibonacci sequence.
The program counter schematic. Credit: Eater.net
The program counter, as mentioned briefly before, is a small but crucial element in a computer. A program counter simply counts, it increments once for each instruction that is executed. This is crucial because without counting something when we complete an instruction, there is no way for the computer to know what to do next. Without a program counter, the MAR wouldn’t be very useful because there would be no sense of direction in the program. The program counter advances the entire computer forward in time.
This computer also has a JMP instruction, meaning that we can program it to move around the memory in a non-linear path. This is important to understand when creating a program counter because the program counter needs to be able to have a value loaded into it, so that when we jump, the counter continues forward from the jump, and doesn't take us back to where we jumped from!
The Control Logic circuit. Credit: Eater.net
What arguably brings the whole computer together is the control logic. Each component is designed to be operated via an interface of control lines. These lines do things such as outputting the value of a register to the bus, switching the operating mode of a unit, taking a value from the bus and storing it in a register, etc. Because these units are all controlled in this way, we can make one final circuit that can decode binary instructions, as a series of control signal inputs, which will, in turn, cause the computer to perform an operation! Learning about this is what made it all click for me, and is what made me want to do computer engineering.
When first learning about computer science, a lot of what is taught seems rather arbitrary. You can have a teacher tell you "Oh computers run on binary, a series of ones and zeros." But understanding how those ones and zeroes become CPU instructions makes it all make sense.
I've skipped a couple of parts of the computer like the instruction register and output because they are less interesting and function similarly to the other components already explained previously.
This project has taught me many things. I learned not only about computer architecture, but also learned and practiced many practical skills as well, including using diagnostic tools like logic probes and multimeters, as well as soldering components together that couldn’t be placed in a breadboard. I also learned the importance of understanding the components you’re using. (Combining different silicon families does not work well you know!)
In the future, I would like to build another computer. I want to model it after the 6502 microprocessor, in the hopes of perhaps being able to hack it into a game console or tool that uses the 6502. I think it would be amazing to have a retro game running on hardware that I created with my own hands. Perhaps I'm being a bit too ambitious with that, but you can't give up before you start trying!