Overview
You will implement a multi-cycle MIPS processor in CircuitVerse. You will receive a CircuitVerse group invitation for the project, and must use this group for your project submission to count.
MIPS ISA changes
You only need to support add, addi, lw, sw, j, jr, and blez (the instructions from your homework 1 assembler, or mine), though you can add more if you choose.
Control
Use a horizontal table-based/microprogram control using a CircuitVerse ROM. You will need some external logic for instruction dispatch in the ID-stage microprogram, and to control the PC mux on branch instructions.
In the first and second cycle of an instruction, all instructions should use the same instruction fetch control table entry. For instruction decode, you should dispatch to a different location in the control table for each instruction. JR instructions should take just two cycles IF ID. Branch(es) should take three IF ID EX. ALU instructions should use four IF ID EX WB. Store instructions should also take four, but those cycles should be IF ID EX DM. Finally load instructions should take five cycles IF ID EX DM WB.
The built-in ROM unit is quite limited in the bit width of data, and number of entries. However, if you drop a ROM unit into your circuit, select and copy it, then paste into a text editor, you get JSON-format data describing the ROM and its contents. You can edit this directly, then copy the entire JSON block and paste back into CircuitVerse. Change the "bitWidth" of the "Address" section to allow more entries. Change the "bitWidth" of the "DataOut" section (up to 32) to allow wider data. If you need more than 32 control bits, you will need two parallel control table ROM units. Initialize the ROM data with a comma-separated list of integers in the "constructorParameters" section.
Memory
You'll use a single EEPROM unit for both data and instruction memory. We will not be using the CircuitVerse RAM element because its data cannot be pre-initialized. The EEPROM unit has the same interface, but can be set with initial data by editing the JSON in the same way that the ROM can. You can modify your homework 1 assembler (or mine) to output decimal instead of hex numbers, then paste the resulting programs directly into the EEPROM JSON.
You can examine the values after your program runs, either by pasting the JSON definition into a text editor, or by clicking the "Core Dump" button in the element properties. With the Core Dump button, the data contained in the EEPROM will be displayed in your browser's JavaScript developer console.
CircuitVerse elements
You are free to use any of the standard CircuitVerse elements. Here are some that you'll need to use to complete the project
- Clock: You'll want to use a single Clock element to control the timing of your circuit.
- ALU: Use the ALU unit for both the PC adder and primary ALU. Be sure to change the BitWidth to 32 in the Properties window
- Splitter: The splitter can split multi-bit signals into smaller parts or merge them back together again. The only difference between the split and merge is which side you connect to the input. When you create one, it will ask for a bitWidth, then the Split. The first bitWidth should be the size of the merged signal (e.g. 32 bits). The split is a space-separated list of widths, starting at the least significant bit. So using bitWidth of "32", and split of "31 1" will create a splitter to separate the sign bit from the remaining 31 data bits of a 32-bit two's complement integer. If you only need the sign bit, you can leave the 31-bit output disconnected.
- D Flip-Flop: Use a 32-bit D flip flop for any single registers in the datapath. This element stores the value present on its D input when the Clock input transitions from 0 to 1.
- Registers: For your 32 registers, use a set of 32-bit D flip-flops with two 32-way multiplexers to choose the two register outputs, and a 32-way demultiplexer to enable writing on the one register you want to write during a cycle. Package all of this up into a named SubCircuit.
Circuit cleanliness
A clean and organized circuit will help to avoid bugs, and when trying to find/debug them. Plus it will help for grading, which could get you more partial credit if things are not working as they should.
Some tips:
- Be very careful to keep your wire runs neat, since wires that overlap with each other or touch an element's input or output pin in any way are considered to be connected.
- Using the Direction and Label Direction properties can help to have the input or output on the side you need rather than having to route around the element.
- You can feed a signal into a Tunnel element in one part of your circuit and use additional Tunnel elements with the same name ("Debug Flag identifier") elsewhere in the circuit. This can help to avoid long wire runs. You should still use wires for shorter runs.
- Feel free to package elements into SubCircuits if it will make your design cleaner.
- Use Text and Rectangle elements to document your circuit so we can figure out what you were trying to do.