This week, I demonstrated how to make the register file and ALU, and talked about memory too. Now, you’ll be connecting the components I made into a “fake MIPS” sort of thing.
It’s not going to be a real CPU, but you will be able to “manually drive” it using the control signals.
0. Getting started
Right-click, download, rename, and open this circuit file. You will see something like this:
At the top left are the clock and control signals. These would be produced by the control unit (if we had one…).
At the bottom left are values that would come directly from the encoded machine instructions. rd
, rs
, and rt
are only 2 bits though, since our register file is only 4 registers (well, zero
+ 3 registers).
And on the right are the register file and ALU I made in class, plus a RAM component.
1. Your task
You’ll be recreating the “really simple fake MIPS” interconnect I showed on the slides. For reference:
What you’ll need
- Tunnels (please!)
- Multiplexers
- A bit extender (from the Wiring folder)
- A splitter
This isn’t too complicated, but there are some things to keep in mind.
- Remember to hook the clock up to the things that need it.
- Color-code your tunnels.
- Pick a scheme and stick with it. Use what makes sense to you.
- Tip: if you give every tunnel a totally different color, it will look like pretty nonsense. Try giving tunnels with similar purposes the same color!
- The memory component’s
str
input is its write enable.- You will not connect anything to
sel
,ld
, orclr
.
- You will not connect anything to
- The immediate is 16 bits, but the ALU expects a 32-bit number…
- So you will have to extend the bits with a bit extender.
- It is treated as a signed number.
- Logisim can’t simulate a full 32-bit address space for the memory.
- So, it only has an 8-bit address. That’s fine for our needs.
- To go from a 32-bit value to the 8-bit address, use a splitter with:
- Bit width in = 32
- Fan out = 1
- bits 2-9 go to 0 (Top)
- the rest of the bits go to “None.”
- The memory output is 32 bits and can go back to the reg file.
- Probes are a useful debugging tool.
- The image on the right is my debugging output so I can view some of the values going through my circuit.
2. Test-driving it
Now you have something like a CPU without a brain. It can compute and remember things! But you have to pull the levers and hit the switches to make that happen.
Let’s try putting a value in a register. We can do that by doing the equivalent of:
add v0, zero, 0x1008
Here is the set of control signals and inputs that will make that happen:
RegWrite = 1
(writing to a register)MemWrite = 0
(not storing to memory)RegDataSrc = 0
(from ALU)ALUSrc = 1
(from immediate)ALUOp = 00
(0 = +; look inside the ALU component to see the operations available)rd = 10
(rd
is the destination, and register 2 isv0
)rs = 00
(the first register to read iszero
)rt =
… anything! it’s not used here.Imm = 00010000 00001000
(same as0x1008
)
Now tick the clock. …did anything happen?
Use the hand tool to click on the reg file, then double click the magnifying glass. If it worked, you should see the v0
register now contains 00001008
!
You can get back out of the subcircuit with Ctrl+<Left arrow key>
(Cmd+<Left arrow key>
on mac).
If you have a probe showing the outputs of the reg file, you can set rs
or rt
to 10
so you can see what v0
’s value is without having to go into the reg file.
If it didn’t work, now would be a good idea to use those debugging probes. Make sure the values you expect are going to the places you expect. Don’t forget the write enable.
More “instructions” to try:
- Try doing the equivalent of
add v0, v0, v0
.- It’ll double the value in the register.
- Make the value in the register increment or decrement.
- You can decrement by subtracting 1 or by adding -1…
- How about a
lw
?- If you click on the memory contents with the hand tool, you can type in a hex number, like in the image on the right.
- The address is the contents of register
rs
+imm
, so if you users = 0
, then the address will just beimm
. - The word will be loaded into register
rd
.
- A
sw
?- The contents of register
rt
are stored into memory atrs
+imm
. - Don’t forget the memory’s write enable…
- The contents of register
Try this: Remember, this is optional! In class we talked about how bytes are loaded from memory by loading a word and then picking bytes out of the word and zero- or sign-extending them.
Add two more control signals: LoadSize
(00 = load word, 01 = load byte, 10 = load half, 11 = ??????) and LoadSigned
(0 = zero-extend, 1 = sign-extend).
On the memory output, you’ll need some splitters, muxes, and bit extenders. Bits 0 and 1 of the ALU output pick which byte to load; bit 1 of the ALU output picks which halfword to load.
See if you can do lb
, lbu
, lh
, and lhu
. If you put 0xAABBCCDD
into memory at address 0, loading a byte from address 0 should give you 0xDD
(little-endian, remember?); address 1 should give you 0xCC
and so on.
Last, how can you detect memory alignment errors when loading words or halfwords? 🤔
Submitting
Once you’re sure your circuit works and you’ve done some exploration on how it works, you can submit.
Name your circuit file username_lab7.circ
, like jfb42_lab7.circ
.
Drag your asm file into your browser to upload. If you can see your file, you uploaded it correctly!
You can also re-upload if you made a mistake and need to fix it.