Last time I talked about getting started with CPU design by looking at older designs before trying to tackle a more modern architecture. In particular, I recommended Caxton Foster’s Blue, even though (or maybe because) it was in schematic form. Even though the schematics are easy to understand, Blue does use a few dated constructs and you probably ought to build your take on the design using your choice of VHDL or Verilog.
In my case, my choice was Verilog. You can find my implementation of Blue on Opencores.org. I made quite a few changes to Foster’s original design. For example, armed with semiconductor memory, I managed to get all instructions to operate in one major cycle (which is, of course, 8 minor cycles). I also modernized the clock generation and added some resources and instructions.
Instructions
You can find my entire instruction set in the Blue archive (look in the file blue-instructions.xls). The spreadsheet shows the mnemonic, the op code, and what operation occurs in each of the eight subcycles. Here’s an example:
Speaking of mnemonics, there is a simple assembler written in Perl (use the shell script named asm to call it). This would have been a good place to use my universal assembler, but I had not written it yet.
While looking at my version of Blue is useful, you shouldn’t follow it too closely. For one thing, I used Blue as a test case for the tools I was using, so there are several places where there is alternate code and places where I mapped Foster’s gates rather literally to see how the tools handled it compared to more oblique constructs. Besides, your real goal should be to do your own design based on the architecture. Still, having a working example to look at when you get stuck isn’t always a bad thing.
Clock Generation
Top.v has the blue module in it (not the best naming convention). The clock generator is part of control.v and looks like this:
reg [7:0] onehot; reg wclks; assign cp[1]=onehot[0] && (xrun|xdep|xexam); assign cp[2]=onehot[1]; assign cp[3]=onehot[2]; assign cp[4]=onehot[3]; assign cp[5]=onehot[4]; assign cp[6]=onehot[5]; assign cp[7]=onehot[6]; assign cp[8]=onehot[7] && cycle; always @(posedge clk or posedge reset) begin if (reset) onehot<=8'b1; else begin if (start || exam || deposit || abortcycle) onehot<=8'b10000000; else if (xrun||xexam || xdep) onehot<={onehot[6:0], onehot[7]}; end end
The cp signals are the minor clock cycles. The onehot array is a simple shift register that tracks the state. The other bits like start, exam, and deposit are part of a custom front panel that I created (see the video below). That’s not part of Foster’s original design, but it is a great use of the Digilent Spartan 3 board that hosts the CPU. Unfortunately, that board is retired (another reason not to copy the design directly).
If you don’t want to do a front panel, my version of Blue also has a serial port, and I wrote a simple loader to read in a more powerful monitor (see the video from the last installment). In fact, the front panel is even more interesting than the CPU in some ways.
The demo board has four 7-segment displays, a few LEDs, a few pushbuttons, and eight switches. That’s not really enough to handle a 16-bit processor. I use one button to change the meaning of the display, and the discrete LEDs remind you which mode the display is in. Entering a byte on the switches shifts the previous byte up so you can enter 16 bits before you press the enter button. If you make a mistake, you can just keep entering bytes without pressing enter. You can see the operation in the video below.
Other CPUs
There are other small CPUs out there, some more modern than Blue and many with more features. One of the problems I see, though, is that some very small CPUs are either not complete enough to be practical, or they are hard to understand. The J1, for example, is only about 200 lines of Verilog. But it is an unusual architecture that might not be the best place to start. MCPU is another very small processor that can even fit in a CPLD.
Regardless of the path you take, I think your best bet is to remember the title: crawl, walk, run. Get the basics down and then progress to more and more complex designs.
These posts are great! I got the Foster book and I’m starting NAND To Tetris as well. Fascinating stuff!
NAND To Tetris was fun but I did not make it past the asm stage before starting a Ruby course. Learning a superficial language seemed a bit pointless. When I get back into FPGA’s I may implement the book on my Nexys then I would complete the whole thing up to a simple OS and optimizing hardware.
Is there any chance you could use a Verilog to VHDL converter and post both formats. I sure the *helpful* readers here would point out any errors from the converter.
I really would like to read articles about CPLD / FPGA and HDL but Verilog means nothing to me.