 Now that we've seen what all of our instructions look like, we can go back to our hardware and we can see how the structure of those instructions affects how we're going to assemble our hardware. I've cleaned up the architecture that we had from before and you can see one I've added all three types of instructions at the bottom of the page. I've also gone through and highlighted the instruction in yellow. All of the parts of our instruction that come out regardless of where they're going or what they're doing have been highlighted in yellow so that they'll be easier for us to see to work with. So probably the first place to start is the Simplest. We can notice that all three types of instructions come with an opcode so we'll obviously need to be able to process this opcode to do anything with our hardware. And this opcode is really telling us what our control should be. What should each of these pieces of hardware be doing? So this line here represents our opcode. So now I've annotated the line for the opcode indicating that yes, this is the opcode. And I'm also saying that this is the six bits from bit 26 up through bit 31 from our instruction. The next easiest thing to work with will probably be our registers. So we can notice that both the R-type and the I-type have both an RS and an RT field. The R-type also has an RD field. Since both of these have an RS field and we know that's always going to go to Source 1, we can add that note as well. Next, with our R-type instruction, the RT field is always used to point to the second source register so I can add that one as well. And at least for our R-type instructions, the RT field is used for the destination register. So I'll go ahead and add that note as well. But for the I-type instructions, it's a little different. The RS field is still always used for Source 1, but the RT field can now sometimes be used as the second source and sometimes it's used as the destination. If I have a load word instruction, for example, RS is the base address, but the RT is actually the destination that's the register that we're going to store our data into. So sometimes I actually want this RT field to point to my destination instead of the second source. So to do this, we're going to have to modify our architecture a little bit. I will start by making some more room here. And now I'd like to be able to choose whether my destination register comes from my RT field or my RD field, which means that I will need a multiplexer. The RD field is still only relevant to the destination, but now I have a choice between whether I use the RD field or the RT field as my destination. So either of these two options could be my destination. I'm still always going to pass RT in as my second source. I might not use it because of the ALU source multiplexer, but it's still being passed in as Source 2. So far, our hardware isn't set up to handle shift instructions, so I don't have to worry about that part of my instruction, but now I have the function code. So far, I don't have anything here that can really use the function code. The function code is used solely to control what the ALU does. But it's only used for R-type instructions, so whether the function code is relevant or not is also going to depend on our control unit. The way we'll do this is by adding another control unit that is just for the ALU. So now I've added a new unit, this ALU control, which takes its parameters both from the control and from the function field, and it will use those to decide what the ALU should be set to. And I will go ahead and annotate the name for this line as well. That covers all of the parts of our R-type instruction. We have our opcode, our RS field, our RT field, our RD field, and the function code. We've also found the opcode from the I-type instruction, as well as the RS and the RT fields. Next, we can look at the immediate field for the I-type instruction. We have two uses for this immediate field. One is just to be used as an immediate and, say, an add immediate instruction. Here we want to take this value and add it to something coming out of our registers. So in that case it's really easy. We've got this line here that's going to the ALU source multiplexer, and we can feed that into the ALU if we want. But there's a problem with just doing this. Here I have a 16-bit number that I'd like to add to a 32-bit number. The second piece of data coming out of the registers would be a 32-bit piece of data. So it seems a little odd to try to add a 16-bit piece of data to a 32-bit piece of data, while also keeping the ability to add a 32-bit piece of data to a 32-bit piece of data. So what I'd like to do is convert this 16-bit piece of data into a 32-bit number instead. Since my numbers are always represented in 2's complement, I can do this pretty easily just by copying out the leftmost bit of my number. This process is called sign extension. And this process is really pretty easy to do. We're just going to take the leftmost bit of my immediate and send it out to a whole bunch of different places, and instead of just having one wire for this bit, we're going to turn it into 17 wires. So now I have a 32-bit number that comes out of my sign extension unit, and that I can easily add to the data coming out of a register. The other thing we'd like to be able to do with our immediate is to use them for branch instructions. Our immediate is up here for our branch target address hardware, but as you probably recall from learning how the branch instructions are represented, this is a number that tells us something about the number of instructions to jump forwards or backwards. However, our program counter counts in terms of bytes. These two lines are, again, not directly comparable. We need to make some changes so that we can add this number to this number. As before, we have a 16-bit number coming in. We need a 32-bit number coming out. So I'll go ahead and add another sign extension unit, but this will quite be enough. Since our immediate is written in terms of number of instructions rather than number of bytes, we also need to convert from number of instructions to number of bytes. And the easy way to do that is to add two more zeros to the right-hand side of our number. With the j-type instructions, we were able to chop those two bits off because we knew there were always zeros. And we used the same argument here, really. It meant that our immediate looks like it's counting in terms of instructions rather than bytes, but all we really did was chop off the last two zeros and turn this into an offset from program counter plus four. So we're going to need to add those two zeros back in. We could use a shift instruction to just shift two zeros in the right-hand side, but really that's no different than just adding in two more zeros on the right-hand side anyway. So I will add a note here showing that we're going to place two more zeros at the end of our number. So we have 16 bits that come in as part of our immediate. They get sign extended to 30 bits, and then we add two more zeros on the right-hand side so that now we have a total of 32 bits coming into our ALU that can be added to the 32 bits from the program counter plus four. For our J-type instructions, we really just have the address to worry about. We've already taken care of the opcode, so we're just left with this address. Since the address is pseudo-direct, it's not going to be too much different from what we got. We really need to take this address and copy it over to this multiplexer, but there's still going to be a little bit of funny stuff happening here as well. Rather like with the branch instructions, we're going to need to add two more zeros to the end of our address. I've kind of made some space for us to work with. And as before, we will add in two zeros on the right-hand side of our address, and now I just need the top four bits from my program counter plus four. I've managed to produce this Frankenstein-esque address by taking the top four bits from my program counter plus four, then adding in the 26 bits from my address field, and finally tacking on two zeros at the end. All of this is then passed together as one number to the Jumper multiplexer, which decides whether it should take that address or the results of the branch multiplexer instead. And we finish this off by adding an annotation for the address field, showing that it is coming into this collection of wires that together will form our jump target address. And that's it. We now know what all of the parts of our instruction are being used for, where they're going, and how they're interacting with other parts of the hardware here. Once we knew the format of some of these elements, we discovered we had to add some additional hardware to choose what destination register we wanted, as well as to just convert the form of some of this data. Not all of it was in an immediately useful format, but it all pretty much worked with the hardware as we built it so far.