Project 2 - Fully Pipelined Mips

FAQ

Usage of Comparators - 3/15/2014
You may use as many comparators as you like, however you will still be penalized for usages that are extremely inefficient (e.g. using a comparator only for equality).
Forwarding from the MEM Stage - 3/12/2014, updated 3/13/2014
You may forward from the MEM stage, but only in certain circumstances.
Bad idea: Forwarding the output of the RAM inside the MEM stage.
It is better to forward the value from the WB stage. You will be penalized for forwarding the wire circled in red.

Memory operations are the most time consuming operations. Consequently, the path that goes through the RAM in the MEM stage defines the clock cycle for the circuit (as it is the critical path). Forwarding the result of the memory operation out from the RAM will increase the critical path, and this is undesirable. You may forward data in the MEM stage before it is passed through the RAM. Please show that you are following this spec in your documentation.
Nesting the register file in subcircuits
The register file must be visible either in the toplevel circuit or one level down in a subcircuit. Do not nest the register file two or more levels down!
MIPS Program ROM and symbolic register names
The assembler built into the MIPS Program ROM accepts standard MIPS register names: $zero, $at, $v0, $v1, $a0 - $a4, $s0 - $s7, $t0 - $t9, $k0, $k1, $sp, $gp, $fp, and $ra.
Testing and input for hailstone functions
Your hailstone functions are just that: functions. They should get their inputs from registers, typically $a0 and $a1, and they should leave their results in a register, typically $v0. To test the functions, you will nead to create a "main" program which initializes the stack (by setting $sp and $fp to something reasonable and usable), puts some input in the argument registers, then calls the function via JAL. The hailstone functions never make system calls or any other function calls that could possibly read input from the user. Your main program can if you managed to wire up a keyboard though.
MIPS RAM as byte addressed and little endian RAM

Here is a screenshot as I am writing the byte value 0x44 into byte address 32. Since the RAM is word addressed, this byte gets written to one of the four bytes at word address 32/4 = 8; you can see the A input to the RAM is 8. Since I want little-endian behavior, address 32 corresponds to the little end of the word (address 35 would be the big end of the same word, where 0x11 is stored); you can see the selector input is set to activate only the little end of the word. I am also reading at the same time, so you can see the 0x44 being read out on the litle end of the D output. If I were to activate all of the selectors, the RAM would output 0x11223344, which is the word stored at word address 8, i.e. byte address 4 * 8 = 32, which contains bytes 32 through 35.

ram2

Here is another screenshot as I am writing the byte value 0x2b into byte address 43. Since the ram is word addressed, this byte gets written to one of the bytes at word address 43/4 = 10; you can see the A input to the RAM is 0xa = 10. Since I want little-endian behavior, address 43 corresponds to the big end of the word (address 40 would be the little end of the same word, where 0x52 is stored); you can see the selector input is set to activate only the big end of the word. I am also reading at the same time, so you can see the 0x2b being read out on the big end of the D output. If I were to activate all of the selectors, the RAM would output 0x2b000d52, which is the word stored at word address 0xa = 10, i.e. byte address 4 * 10 = 40, which contains bytes 40 through 43.

ram1

For writing byte 0xbb, depending on the address, I might want to put it at the big end, little end, or somewhere in the middle. Similarly for reading a byte, depending on the address, I might want to grab the bytes from the big end, little end, or somewhere in the middle. Hint: For writing, just direct the desired byte to all four positions then activate writing for just the one you want. For reading, you will need to select between the four possible positions where the byte might appear on the RAM's D output.

On the other hand, reading and writing whole words is trivial. The RAM is 32 bits wide, so just send the whole 32-bits to the memory, and read the whole 32-bits back to the CPU. You could try to be clever by swapping the order of each word's four bytes when writing to RAM, and un-swapping them when reading from RAM. This, however, would be entirely pointless. Can you tell why? Try it to see if it makes it any easier to read and write bytes.

JALR and the implicit $31
The MIPS manual lists two forms of the JALR instruction. This is misleading. There is only one binary encoding for the JALR instruction, and it is the version that takes two register arguments: JALR rd, rs. This is the only one you have to implement. The alternate version of JALR, with rd omitted, is just an assembler pseudo-instruction: whenever you write JALR rs, the assembler converts this to JALR $31, rs before it encodes it in binary.