Last month, I've reported about a great 4-Bit Self-Made CPU project called "The Nibbler". It continues to fascinate me as the tools that are freely available such as an assembler and a simulator for it help me to get a deeper understanding of how "computers" work at their core. But while simulating the CPU is great fun I'd really like to build the real thing myself. Wire wrapping is not my thing so I went ahead and ordered the printed circuit board for self assembly. Despite being shipped out of Canada it only took a week to arrive. I was quick to order it because there were only a few left. In the meantime the PCB is sold out but there's a waiting list. I guess if there are enough requests there might be second batch. Great, now the hunt for the parts begins 🙂
Time flies but it still seems like yesterday when I discovered "But How Do It Know", the must-read book if you want to understand how a CPU works, the central piece of electronics in any electronic device today be it a SIM card, a smartphone, a notebook or a supercomputer at a large computing facility. Once you have read this book and have some background in tinkering with electronics you can build a working CPU with memory and I/O at home. I started doing this and came as far as making shift registers and memory work. Unfortunately, there just wasn't enough time and there were too many components I wanted to use in my design so that's about as far as I got. But perhaps there is yet another way to achieve this goal without waiting for retirement: The Nibbler by Steve Chamberlin.
The Nibbler is a 4-bit CPU with ROM and RAM, fitting on a single medium sized board. The difference between what I had in mind and the Nibbler is that it uses a single chip 4-bit Arithmetic Logical Unit (ALU) which I initially wanted to build out of individual logic chips like adders, etc. Also, I had an 8-bit ALU and address bus in mind, but obviously the 4-bit approach makes wiring a lot more practicable. And finally, the Nibbler simplifies things by separating the program ROM and RAM, which again saves a lot of wires. While the original Nibbler design was done in wire-wrap technology, William Buchholz has picked up the project and produced a "real" PCB which again significantly reduces the time it takes to put things together.
Obviously this design is a bit different from the CPU discussed in "But How Do It Know". But in the end that doesn't matter because the concepts are the same. Using a single ALU chip is somewhat of a compromise between reducing complexity and being as discrete as possible to understand how the stuff really works. Fortunately there's a good description of the 74HC181 ALU chip on Wikipedia and a great diagram that shows how it looks like inside, basically consisting of several function blocks for different arithmetic functions and a total of 75 gates.
Another thing that makes this ALU chip appealing is its historical background. According to the Wikipedia page linked above, it was the basis for a number of historically important computers that were designed before fully integrated CPU chips became available, the DEC PDP-11 being one of them. The PDP-11 was obviously not a 4-bit computer but with the help of a support chip it's possible to daisy chain a number of these 4-bit ALUs to perform arithmetical operations on bytes and words.
Finding stuff like this is one of the reasons why the Internet is so great. Without it, it's unlikely that I would have ever found this project because building your own CPU does not only seem to be a niche, its more of a nano-niche. What I find a bit amazing, and sadly so, is that William didn't sell too many of his boards yet even though the price makes it a no-brainer for those with ambitions to understand how a CPU works not only from a theoretical point of view but also in practice.
Now that I know how to read and write data to the memory chip the next step in my Do It Yourself CPU project was to extend the possibilities of my Raspi Input / Output Interface. The 8 input and 8 output ports are not sufficient for controlling and testing the different functionalities I want to build over time. Already, outputing 8 data bits and 8 address bits at the same time is not feasible that way.
To fix this shortcoming I've decided to use several 8 bit serial to parallel converter chips. By chaining four of those chips together I only need 1 Raspi output port to write data to 32 output ports sequentially and one port for clocking in one bit after the other. To be able to individually enable output to the data bus, the address bus and the control lines (e.g. memory output enable, memory write enable, etc) that are accessible this way I need three additional Raspi output ports. In other word I need 1+1+3 = 5 lines to control 32 output ports. Not too bad.
The picture on the left shows the circuit I have put together to test the shift register approach. The memory chip is at the top of the breadboard, followed by a NOT gate chip that I use to invert the output of the first three bits of the data bus as the input bits of the Raspi work with negative logic. Also, this setup separates the Raspi Inputs from the bus lines which I decided to do because I noticed that they lower the voltage on the lines which could become a problem later on when I connect registers and other things to the bus line which will further influence the overall behavior.
An additional NOT gate on the chip is used to invert the Enable signal to the second serial to parallel (SIPO) converter chip which allows me to control whether I want to output data from the Raspi to the data bus or not (i.e. the outputs of the SIPO is in tri-state mode). The two chips at the bottom are MOS 4094 8 bit tri-state shift registers. For the experimental setup I used the first SIPO to output data to the address bus and the second one to output data to the address bus.
Yes, the setup starts to look a bit complicated. Time, therefore, to put what I have so far on a real board and solder things together.
Now that I know a couple of ways how to build a clock generator I've moved on to the next step and have started looking into what kind of RAM I want to use for my Do It Yourself CPU (DIY-CPU). Here's the story of how that went:
As it's an experimental system I only need a couple of bytes of RAM to hold a short program and a few bytes of data. I don't want to build it myself, however, as I feel confident that I understand how static RAM is composed of flip-flops, how flip-flops are built with gates and why they have two stable states. Therefore I had a look around for a small off-the-shelf RAM chip that I can.
The smallest static RAM chip I could find has a size of 8 kilobytes which sounds very little by today's standards of course. However, that is far beyond what I need anyway, I would have already been content with a 256 byte version. Anyway, so I bought an 8 kB CMOS RAM chip and for those who'd like to take a closer look you can find the datasheet of the WS6264 here.
To get a feeling of how I can write data into the chip and get it back out again I used a breadboard to experiment a bit. To make life a bit easier I decided not to use physical switches and LEDs to control and read data from the address and data buses. Instead I decided to use a Raspberry Pi with a Pi-Face extension board that offers 8 digital inputs and 8 digital outputs and the flexibility of Python programs to read and write data on the various pins of the RAM chip. As 8 inputs and 8 outputs are obviously not enough to control all of the 8 address bus pins, the 8 data bus pins and the various enable and set lines I had to simplify a bit and only use 3 bits of the address bus and 3 bits of the data bus and grounding all other lines. In other words I limited myself to reading and writing 2^3 = 8 bytes. More than enough to get a feeling for how to read and write data into the chip. In addition to the bus pins I also control the Output Enable line and Write Enable line of the chip with two output ports of the Raspberry Pi.
The first picture on the left shows this setup. The green cables between the breadboard and the Raspi go from the RAMs first three data bus pins to three input ports of the Raspi so I can monitor the data bus. The forth green cable is the common ground. The red cables between the Raspi and the RAM are the first three address bus pins that I can control with 3 output port pins of the Pi. The orange cable connects to the Write Enable line and the yellow cable connects to the Output Enable line.
To write something to a memory location I used a little Python program to put the address over the red cables on the address bus. The red button that can bee seen at the bottom of the image is used to set one of the 8 bits of the byte to either 0 or 1 while all other bits of the data bus are pulled to ground. This way I can cycle through the 8 bytes I can address and set one of the 8 bits to either 0 or 1 while all other bits are always 0. Remember, it's only to figure out how things work so there's no need to set all 8 bits of the byte. Just seeing that the bits come out correctly again later on is enough.
Once the address is on the address bus and I have either pressed the button or not to write a 1 or 0 respectively to one of the bits I activate the Write Enable line for a short time (by pulling it to ground) and release it again to commit the value to the chip. With a loop in the Python program I then go to the subsequent memory addresses and repeat the exercise seven more times. In a second loop that follows I cycle through all addresses again but this time I use the Output Enable line to put the stored data on the data bus and read it's values via the Pi-Faces input ports and display the result in a console window and also on the graphical simulation in the exported GUI as shown in the second figure on the left.
It took a couple of hours to get everything working but in the end I managed to figure out how to use the control lines to write and read my bits. Every day, I must read and write billions of bytes to a RAM chip by working with computers, smartphones and other devices. But that's something that happens in the background without me consciously doing it. With this experiment I have physically written and read bytes to and from memory by hand for the first time in my life. Quite an interesting thought 🙂
Also, I figured out how to pull the data bus lines to ground via 33k Ohm resistors so I can use the lines for both input and output which will be required in the next step when I hook up a number of other components such as registers to the bus that will be part of the CPU so I can transfer CPU instructions and data between them and the RAM chip. The order for the additional chips has already gone out and I will soon report how that went.
After reading about how a simple CPU works in J. Clark Scott's book and other sources I've been toying with the thought about building a CPU myself. It's a bit of a project and it will take a while but the journey is the reward. As one has to start somewhere I decided to start with the clock as the details of how one is built is a bit vague in the book.
As the CPU is for educational purposes I want it to run at a clock cycle of around one Hertz, so one can actually see how things are working. In addition to a long clock cycle to drive an 'enable' signal to put something on the data and address bus that interconnects everything, a shorter clock cycle in the middle of the overall clock cycle is required to drive the set inputs to a number of components such as registers, the memory etc. to tell them to take over what's currently on the bus. These two signals can be generated out of a clock and a delay of itself of half a clock cycle. The book describes how to use AND and OR gates to generate the enable and set pulses ot of those signals but not how to create clock signal itself and how to derive the delayed clock from the original clock.
So I improvised a bit and used two inverters (NOT gates) with a resistor and capacitor for a 1 Hz clock generator (in the middle of the picture), a transistor, some resistors and a capacitor for the delayed but inverted signal (the right part in the picture) and another NOT gate to revert the delayed impulse back. The circuit with the AND and NOT gates described in the book to generate the two output signals are shown on the left together with two LEDs to visualize the final signals.
The result looks a bit complicated but it's actually not, because there are three distinct and independent building blocks that can work independently of each other. One thing that makes things look a bit complicated is the use of one AND of the chip on the left and three NOT gates in the chip in the middle to create a single OR gate.
Using parts of the electronic kits I got as a teenager and parts of kits I recently bought to have a more complete setup was ideal for prototyping the circuit. I'm sure there are a million ways to build this more efficiently and with fewer parts. But efficiency was not the point of the exercise. There we go, the first step towards my own CPU is done.
Looking at historical computing educational kits that explain how computers work rather than 'only' how to work with and program computers I started thinking a bit about the different levels of abstraction on which people understand computers. Here's what I came up with:
The Working Level Understanding: This is how most people understand computers today. They use it as a tool and know how to work with programs that serve their needs such as word processors, spreadsheets, web browsers, etc. Most people on this level, however, know little about what's inside that notebook or smartphones and can not explain the difference between, let's say, a hard drive and RAM or even know that such things exist.
Hardware Understanding: The next level from what I can tell is knowing about the components a computer consists of such as a processor, RAM, the hard drive, etc. and what they do.
Programming: The next level is programming. One can certainly learn programming without knowing about the hardware but I guess learning about that would come in the process of learning how to program anyway.
Understanding how the individual components work: The next level is to understand how the different parts of a computer work and what they are based on, i.e. logical gates, bits and bytes to simplify it a bit. There are certainly different depths one can go into on this level as pretty much on all other levels as well. The "But How Do It Know" book I've reviewed some time ago is one of the best ways to really feel comfortable on this level.
The physics behind the gates: Next in line is to understand how gates are built, i.e understand how transistors work on how they are implemented on silicon. I liked this video on Youtube which gives a good introduction from a non-technical point of view. Obviously one can go much further here, down to the quantum level and beyond but I think the basics of this level are still understandable for somebody interested in the topic without a deep technical background.
Personally I think I have a pretty good grasp on most of these levels, at least from a high level point of view. But I decided to go a bit further about understanding how individual components work. As I said in a previous post I learned early in my career how a CPU works and what is inside. However, the control part of it always remained a bit mysterious. I wouldn't have thought it to be possible to build my own CPU before, but after reading the "How Do It Know" book plus some extra material I am sure I can pull it off, given some time and dedication. So there we go I have my new quality time project: Building my own CPU. I'll call it the Do It Yourself (DIY) CPU and will of course blog about it as things develop 🙂