Last time I looked at a simple 16-bit RISC processor aimed at students. It needed a little help on documentation and had a missing file, but I managed to get it to simulate using a free online tool called EDA Playground. This time, I’ll take you through the code details and how to run the simulation.
You’ll want to refer to the previous post if you didn’t read it already. The diagrams and tables give a high-level overview that will help you understand the files discussed in this post.
If you wanted to actually program this on a real FPGA, you’d have a little work to do. The memory and register initialization is done in a way that works fine for simulation, but wouldn’t work on a real FPGA. Anyway, let’s get started!
If you take each file individually, none of them are very difficult to understand. Here’s a quick rundown (I’m using the file names I’ll use in my online simulation):
- Parameter.v – This is like an include file that sets some basic definitions for every other file.
- prog.v – This is the instruction memory. A simple module, it takes an address and presents data for that address. The $readmemb directive reads the data from a file (test.prog).
- register.v – The register file. This is almost like the instruction memory but it has two read ports and you can write to it.
- data.v – The RAM memory. This is nearly like the registers, but larger and with a single read port. There is some simulation code that opens a file and prints the memory comments, but I deleted that as it was just for debugging. The initial content comes from the test.data file.
- alu.v – You’d think this would be complicated, but it isn’t. It just takes two inputs and does something to create the output. Something simple like adds or subtracts. The always @(*) tells Verilog not to create clocked logic for this. It just turns into some simple gates and muxes.
- Datapath_Unit.v – This is one of the more complex files, although if you dig into it, you’ll see it is mostly bulk. This file creates all the resources (like the registers and memories) and wires them together.
- Control_Unit.v – Another longer module, this one simply implements the instruction table, setting the control lines based on the current instruction.
- ALUControl.v – This file decodes instructions for the ALU. It was missing on the original post. Oddly, there is another similar CPU on the same site that has an ALUControl file, but it is clearly for a different instruction set. However, starting with that file and using the design table, I was able to recreate it. If [fpga4students] corrects this, the files may look very different.
- design.sv – This file is required for the EDAPlayground simulator I’m using. It contains the top-level components (the data path and the control unit). Because EDAPlayground only processes this file, it is necessary for it to include the other files mentioned above. This causes some warnings since each of them has a timescale directive, but this is harmless.
- testbench.sv – The testbench isn’t part of the real design, but simply sets up the simulation and collects results. I had to modify it a bit to work with EDAPlayground, but the operation is the same. It just creates a CPU, feeds it a clock, and lets it run for a while. The test program and memory contents are in test.prog and test.data.
You can do one of two things. You can open up my copy of the design ready-to-go, but that might not be your best option. I’d suggest you simply go to EDAPlayground and create a new Verilog project. Then start moving the files over from the original post. You’ll run into errors and missing files. See how many you can fix. If you get stumped, then you can use my copy to help you if you get stumped. You’ll learn more that way.
If you do decide to try it, here are a few tips about EDAPlayground. You don’t need UVM/OVM selected, nor do you need any other libraries. I used Icarus Verilog 0.9.7, but you could probably use any of the Verilog tools available. You do want to check the EPWave checkbox and you’ll need to add this to the inital part of testbench:
initial begin $dumpfile("dump.vcd"); $dumpvars;
Use the + sign next to the file name tabs to make new files. EDAPlayground has a limit of ten files per pane. Remember, you’ll have to include any .v files you create in either testbench.sv or design.sv. You don’t need to include the data files since the other files use them indirectly.
Once you have all the errors worked out, you can press Run and you’ll get the waveform viewer, EPWave. You have to add signals of interest so you can watch the CPU at work. It would be fun to add some I/O devices in memory or some debugging ports so you could watch things a little better. I’ll usually watch the program counter and the register write port to get an idea of what’s going on inside.
The original code had a program that exercised a lot of instructions. I commented it out and replaced it with this:
0000_0100_0000_0000 // 0000: Load R0 <- Mem(R2+ 0) since R2=0 this puts 1 in R0 0000_0100_0100_0000 // 0002: Load the same in R1 (R1 will always contain 1) // location 8 (byte), 4 (word): 0010_0000_0101_0000 // 0004: R2= R0+ R1 0001_0010_1000_0000 // 0006: Mem[R1]=R2 (that is Mem=R2 0000_0010_0000_0000 // 0008: R0=Mem[R1] 1101_0000_0000_0011 // 000A: Jump to location #4 (CPU will multiply by 2 and add 2) // no instruction at 000C, but PC will hang there while it processes jump
You should be able to follow the incrementing value writing to memory and watch the program counter cycle back to location 4 through each loop. Here’s a typical session:
I left out a lot of internal signals, but you can see that memory address 1 is set to 2 and then to 3 on the first two iterations of the loop.
Is this a good educational CPU? I’m not sure. Some simpler CPUs exist, but they are often small because they are tricky or they are highly impractical. Anything more complicated than this is probably too much to bite off for a beginner. While I think you should have some grasp of basic Verilog before you tackle something like this, the documentation was a little sparse (and confusing) in some areas. Obviously, it was good enough because I got it working, but if you are just starting out, you probably would appreciate a little more help and explanations.
Do you have a favorite educational Verilog CPU? I’m still looking for that one that is “just right.”