Close
0%
0%

Worlds first 32 bit Homebrew CPU

Creating the worlds first 32 bit homebrew CPU using 74' series logic.

Similar projects worth following
There is a major CPU that is missing from the world. A 32 bit homebrew CPU that implements a full and modern instruction set. The solution is to use 74' series logic chips and the RISC-V open source instruction set architecture. With a GNU toolchain already created for RISC-V it means we already have an assembler and compiler ready and waiting for our machine. So lets get rocking and create the ultimate in homebrew projects.

Browsing the web I found a fascinating niche activity. People have built homebrew CPUs/computers using just basic logic chips. And they actually worked, they did real computation. These ranged from trivial 4 bit machines, that barely did anything, up to impressive 8 bit machines that run a customized version of Mimix. One crazy guy in England has used several thousand transistors to create a machine that takes up half a room. They look cool, sound great fun to build and I want in on the action.

But what to do? Well there seems no point in just copying what others have done. The fun is in designing your own unique project and the journey taking it from idea to working machine. Well it seems worthwhile to tread new ground, do something not done before. As far as I can tell, there is no homebrew 32 bit machine (I don't count an FPGA implementation). And certainly none seem to implement a fully specified existing instruction set architecture (ISA). This is something that must change.

So a bit of research later and I have found the perfect ISA. There is relatively new open source 32 bit RISC architecture called RISC-V that has been designed by researchers at UC Berkeley. Being a RISC design it is relatively small in the number and complexity of the instructions that need implementing. This is important as any 32 bit design is already going to be a big project, so lets not make it impossible by going for something like the CISC of the 80386!

  • Instruction decoder

    Phil Wright04/05/2017 at 03:51 6 comments

    Instruction decoding is one of the simpler parts of the system. For example, all the branch instructions can be identified using the same 7 bits of the incoming instruction value:-

    All branches have the same '1100011' pattern at positions [0-6]. So I only need a single decoder board that compares and matches this 7 bit sequence in order to generate the correct control lines for the rest of the CPU. The actual comparison of registers rs1 and rs2 is performed by a separate comparison board. This comparison board takes as input the 3 bits at positions [21-14] that uniquely identity the actual branch operation. So '000' will mean BEQ and '001' BNE and so forth.

    This same approach works for other major groups as well. All the ALU operations that take an immediate value have the same '0010011' pattern. The ALU operations that take two registers have the '0110011' pattern. In both cases the ALU implementation will perform the correct function by using the function code that is part of the instruction format and passed directly to the ALU.

    By grouping this way we only need a decoder board for each instruction group that we need to support. As I am only implementing 37 instructions it works out I will need 9 decoder boards.

    A single board looks like this:-

    At the bottom right is an 8-DIP switch that is used to match against the incoming first 7 bits. This means the left most switch on this DIP package is not connected and ignored, but it is easier to order and use 8-DIP packages than try to find ones that support exactly 7.

    Above that are two more DIP packages that are used to define the 16 control output signals. I am assuming that my final design will not have more than 16 different MUX or other boards that need control lines!

    By making the board completely configurable I have the flexibility to implement the rest of the CPU in multiple ways and to change the design if needed. Like my other boards these can be stacked vertically because I am using long female headers for the instruction input, control line outputs and the power connection. So I anticipate a final setup with 9 of these high.

    I use a 74HC688 for the bit pattern comparison, 2 x 74HC241 output drivers for the 16 control lines and an 74HC04 to invert the output of the '688 for use with the output drivers.

  • Let it fly!

    Phil Wright03/20/2017 at 22:40 3 comments

    It took a whole weekend but finally the register file is complete. I took a delivery of new boards last week and the first to be built is the register control board. This is used to drive the 16 individual registers. Once finished it looks quite impressive...

    The control board takes three 4-bit values. The register to output on port A, the register to output on port B and the register to be written to. Our control board has three output headers that are 16 lines wide. So register zero takes bit 0 from each of the three headers as its input. Register one takes bit 1 from all three headers and so forth. This results in the monster wiring loom shown above. I had to make it all by hand using DuPont connectors, a crimper and some heat shrink tubing.

    It would have gone much faster except for some errors that took a long time to notice. Each of the two register stacks had misconnected pins in the middle of the stacks. When connecting them together it can be tricky getting all the 100 long headers to match up. Well I hadn't noticed a couple that had missed on insertion and were not connected. Compounding this I found that one of the ribbon cables I was using to make a test connection had two of the wires transposed. Luckily it was a rainbow coloured cable so I eventually noticed that red and blue lines were in the opposite order at the other end of the cable. Otherwise I would still be scratching my head!

  • Program Counter

    Phil Wright03/14/2017 at 22:18 3 comments

    The program counter module is split between two different boards because there are too many IC's to fit on a single 100mm x 80mm sized board. The top board provides storage by using 4 x 74HC574 IC's that each store 8 bits. Every clock cycle the storage is updated with the incoming 32-bit address. Because our CPU design is single cycle the PC needs updating every cycle. Hence there is no need for a control line that determines if the PC needs updating during the next tick.

    The current value is constantly output to a long header that is connected to the bottom board. This uses 8 x 74HC283 IC's to perform an add of the constant value 4. Because we are implementing the RV32E specification we know it does not need to support the condensed instructions, therefore all instructions are aligned on a 4-byte boundary. Moving to the next instruction always involves adding 4 to the current value. The CPU design will include multiplexors that determine how the input is provided to the PC. It could be the result of adding 4 but it could be the result of a conditional branch or the destination of a jump.

  • Register Control Board

    Phil Wright03/01/2017 at 00:08 0 comments

    Just because the register control board is green doesn't prevent us from testing it. The purpose of this board is to take information from the current instruction and use that to generate individual select lines for the 16 registers in our register file.

    Many of the RISC-V instructions specify two registers as the source of values for the operation. These are called rs1 and rs2 in the ISA description. Here is the specification for the ADD and SUB instructions as an example.

    Our board will take bits 15-18 (4 bits) and 20-23 (4 bits) as inputs. Notice that the instruction above specifies five bits allowing 32 registers to be selected from. But we are implementing the RV32E specification and not the full RV32I version. The RV32E spec only supports 16 registers, so we can simply ignore the most significant bit as the top 16 registers will never be referenced.

    We assume that the code running on our CPU is valid, a commercial system would have checking for invalid instructions and accessing registers out of range. We are not going to bother with that, if your code is wrong then good luck with strange actions occurring!

    So, bits 15-18 arrive at the board representing the rs1 field and are decoded into 16 output lines with only the matching register line selected. In practice, we have implemented the register storage boards to output on a low value. So 15 lines will be high and the matched register number will be set to low.

    We can see this being tested and working below...


    The top left shows our fixed value input board. It has a value of 01 as shown by the output on the top right hex display board. The green board outputs 16 lines and the hex value of that can just about be seen as BFFF or 1011111111111111 as binary. Starting counting at zero it has indeed selected the first line if you start count from the left-hand side. I have tested it with all 16 input values and it does indeed select the correct bit appropriately.

    You might be surprised that it counts from the left and not the right side. Well me too and it turns out I make a snafu on the design. When I reorder it in blue I will rotate the output headers 180 degrees so it matches my expectations. It is not a big deal but as I want to reorder in blue anyway I might as well make the change. It will make wiring slightly neater.

    Bits 20-23 from the instruction provide the rs2 field and are decoded in exactly the same way and simply output on a different header. The final functionality is similar but a little more complicated. Many instructions use the rd field to specify a destination register that should be written to with the result of the operation.

    So we need to decode from a binary number to 16 values. But this time we also need to invert the outputs because writing to a register really does need to be high for a write and low for ignore. Simple enough we just add a bunch of NOT gates. But we also need to ensure we only write when the CLK occurs and the WRITE line is defined. Only some instructions need to update a register and this decoding will set the WRITE line. We only want the update to occur synchronously on the next CLK signal. So, we AND the CLK and WRITE and only when both are set do we enable the outputs for write lines.

    This sounds fine in theory. Time will tell!

  • Am I going colour blind?

    Phil Wright02/28/2017 at 22:45 2 comments

    The next batch of PCB's are in...

    Hang on. I always order blue boards for my cool looking blue CPU. What the hell is this? I double checked my online orders and sure enough, I selected blue for them all. After 8 orders with PCBWAY.COM this is the first mistake they have made. I wonder if they ran out of blue board and just substituted? Wouldn't surprise me.

  • Never trust your Eagle

    Phil Wright02/20/2017 at 08:51 6 comments

    I recently took delivery of some more PCB's from PCBWAY. Given I have never managed to get a design to work the first time around I was not optimistic. Sure enough, I had made a mistake that messed up the board.

    Using Eagle the 74688 IC has an P = Q output pin at the top right.

    The 74688 is used to compare two 8 bit values. So naturally I assumed the P = Q output was HIGH when the two values are equal. When debugging the board I noticed it was the opposite value of what I was expecting. So time to check the actual datasheet.

    What the! The schematic is inverted to the datasheet and so no wonder it doesn't work. So, it seems in future I need to double check the schematic against the actual datasheet for all IC's.

  • Calling clock experts...

    Phil Wright01/27/2017 at 11:59 6 comments

    I am designing a video driver for my upcoming computer. So I have a MX045HS which outputs a 25.175 MHZ signal which is needed to generate a 600x480 resolution VGA output signal. Connecting the crystal output to my trusty oscilloscope gives a pretty poor click signal...

    Using the reference source on the oscilloscope I can see that the poor signal is not a measurement/probe problem...

    I assume it is normal for a crystal to have such a poor signal. What is the standard way to improve this to a nice square wave? A standard circuit you can point me to?

  • Fixed value board

    Phil Wright01/08/2017 at 12:10 9 comments

    Well the latest batch of PCB's have arrived. Finally I have a simple 32 bit fixed value board. This allows me to set a 32 bit value using dip switches so I can then feed that value into other boards as test values. This makes debugging so much easier.

    I must have picked the wrong component in Eagle to represent a standard resistor because you can see that the space allocated for each one is much greater then really needed. Fortunately it does not really matter as there is plenty of room on the board anyway. Although, adding 32 pull up resistors seems like I am doing things the hard way. There must be a simpler way of achieving the same effect? Any ideas?

    I used the boards straight away to test each of the 2-1 mux boards I have built. I can set two values going in and then use two display boards (each display board only shows 16 bits) to show the 32 bit output. Then just toggle the output select line and instantly check it works as expected.

    Next up was checking that each of the register store boards works. I need a total of 16 for the 16 general registers in the RISC-V ISA. Unfortunately I ran out of components once I have built 10 of them but it still makes quite the impressive vertical stack. The input and two output ports are all connected vertically Arduino style as is the power supply connector. That just leaves a 3 pin right angle connector for each register that allows for per-register selection for output and writing.

    My next job is to get the components ordered to finish the stack and then the board that will be needed to generate the 16 sets of control outputs for them. Then finally the first major block of the CPU will be completed, the general register file.

  • Register Store

    Phil Wright12/26/2016 at 10:10 1 comment

    I finally got some free time over Xmas to test out the register store board. It needs to store 32 bits so I use 4 x 74HC574 in order to store the value for output on port A and then another 4 to store the same value output on port B. So the value is stored twice but always updated together on the write line going high. Because the '574 has buffer out lines it means we end up not needing any separate buffer drivers. Remember that there will be 16 registers all connected to the port A and B and so we can only output when the specific register is selected.

    The left board is the register store and the right just a simple bus board used to distribute values and power. Now I need to order some for '574 chips so I can build out the other 14 that I need.

  • Fame at last

    Phil Wright12/20/2016 at 04:34 3 comments

    I was browsing the popular Hacker News website yesterday when I noticed something a little unexpected. Someone had submitted a link to this project!


    It stayed at the top spot for several hours and resulted in the project views jumping from about 1K to 6.5K overnight. Guess I had better pick up the pace and make more progress!

    I will be designing some new PCB boards in the evenings this week with a view to ordering them from PCBWay before the weekend. I have the following two weeks off as holiday so they should arrive during that time allowing me to continue with development.

View all 16 project logs

Enjoy this project?

Share

Discussions

agp.cooper wrote 11/30/2016 at 13:46 point

Hi Phil,

In "Register File Deux" you said "Based on the feedback I have come up with another design that brings the number down to 138 IC's and 18 PCB's. Quite the saving!"

Would you like to share your design/schematic? I would be very interested in having a look. I am particularly interested in your approach to the timing and instruction decoder.

----

I have used Eagle CAD but unless you pay more than $1k you are limited to 160mm x 100mm (=$169), which is in my mind is too small for a 32 bit CPU sub-board.

I use EasyEDA which is free web based PCB design tool. You can import and export your work (but it is not that faithful). The quote/manufacture is dead simple and pretty cheap (similar to the prices you mention). The main advantage is that there is practically no size limitations. Having said that it can be slow and auto-routing usually need to be manually edited (for large boards).

---

Something you should consider early is the connection/bus standard between the boards. Having a common bus standard will speed up PCB design significantly. It will also dictate the minimum PCB board width.

---

For 100+ TTL chips you will need a proper power supply. I spent a lot of time debugging my first CPU only to realise (after much frustration) that the power supply was not up to task.

---

You will need to think about your method for testing each board and the stack of boards as they are connected. I used an Arduino but you will probably need to use a Mega for the extra IO pins. I can safely say that if you expect the assemble the boards into a full CPU and expect it to work first time you will be disappointed. The game is really about minimising the number of concurrent errors (i.e. debugging a board with one error is much easier than debugging a board with multiple errors) and reworks (i.e. a new PCB).

---

Unfortunately, building a CPU also requires designing the user interface and operating system. How else are you going to test/demonstrate your CPU when finished? A front panel is okay for my simple CPUs but the more powerful CPU that you are planning will need something better. A serial terminal perhaps? You can cheat here and use a USB to serial converter and use your PC as a terminal (keyboard and display).

----

Anyway, the above are just suggestions and/or ideas, regards AlanX

  Are you sure? yes | no

Phil Wright wrote 11/30/2016 at 21:57 point

Hi

Your make some very good points, if you read the previous 'Register File' entry I outline a few more details. I will be building from 100mm x 80mm boards and so can use the free Eagle software. That means I end up with quite a few boards that need interconnects but that is fine by me. I am not looking to make the fastest CPU or the prettiest.

I am not designing it all in one go and then building, instead I am designing and building a section at a time in a modular way. I have an overall block diagram that you can see in the project images but the rest I design as I go. Not the most efficient way to go but as a hobby it is fun which is the main objective.

Testing will be done using a simple Arduino and using shift/latch IC's to go from serial to parallel to generate 32 bit values.

I am a professional programmer so the software side is easier for me than the hardware. I can use the existing open source GNU RISC-V tool chain to generate machine code from either assembly or C. I suspect I will write my own little OS for the fun of it. Maybe even my own assembler and C compiler and so make it self hosting. Time will tell!

  Are you sure? yes | no

agp.cooper wrote 12/01/2016 at 04:41 point

Hi Phil,

No problems.

If you are staying with the free version of Eagle and the 100mm x 80mm PCB limit, and don't mind lots of boards; You may want to consider strip-board construction. I used it for my Weird CPU (https://hackaday.io/project/12879-weird-cpu). I used DIYLC (free) for the design work.

The main advantages are:

1) its cheap.

2) it can be rewired if a mistake is made.

The main disadvantages are:

1) manual routing.

2) lots of wire links (I hate the wire links!).

3) limited bus width (~41 strips).

But if you are not using a bus standard then the limit bus width is not much of an issue.

Even though I now use EasyEDA, I still use strip-board for smaller one off support projects.

Regards AlanX

  Are you sure? yes | no

vasili111 wrote 03/21/2017 at 04:09 point

I think it is better to adap NetBSD for your CPU rather than making your OS from scratch. NetBSD was designed to be easy to port to other platforms.

  Are you sure? yes | no

Ingo M. wrote 11/28/2016 at 17:34 point

This is an awesome and very ambitious project! We really need such projects (and Open-V and the like) to ignite the Open Hardware movement. I intend to build the same CPU for myself when the first runs have been successful. I am amazed there have been no comments so far.

Good luck! 

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates