The MIPS CPU in P&H
Figure 5.17
implements eight instructions. It is obviously incomplete. However,
almost all the missing instructions can make use of the existing
structure. Last time we saw that to implement and instruction, we first
identify the
functional units—register file, ALU, PC, or memory—needed by the
instruction. There must be data paths along which information can
access these functional units. We then choose existing control signals,
perhaps with extra gates, or add new control signals that route
information appropriately. (The meaning of the control signals produced
by the Control and the ALU control logic is given here.)
The table below gives the values of the control signals for the
instructions that we saw last time.
inst | operation | Register Transfer | ALUSrc | ALU op | MemRead | MemToReg | MemWrite | RegWrite | RegDst |
lw | load word | R[rt]=Mem[ R[rs]+SX(im16) ]; PC = PC+4 | 0 | 00 | 1 | 1 | 0 | 1 | 0 |
sw | store word | Mem[ R[rs]+SX(im16) ] = R[rt]; PC = PC+4 | 1 | 00 | 0 | x | 1 | 0 | x |
beq | branch equal | PC = R[rs] == R[rt] ? PC+4 + SX(im16) : PC+4 | 0 | 01 | 0 | x | 0 | 0 | x |
add | add | R[rd] = R[rs] + R[rt]; PC = PC+4 | 0 | 10 | 0 | 0 | 0 | 1 | 1 |
sub | subtract | R[rd] = R[rs] - R[rt]; PC = PC+4 | |||||||
and | and | R[rd] = R[rs] & R[rt]; PC = PC+4 | |||||||
or | or | R[rd] = R[rs] | R[rt]; PC = PC+4 | |||||||
slt | set less than | R[rd] = R[rs] < R[rt]; PC = PC+4 | |||||||
addi | add immediate | |
Complete the final row.
We move to the j (Jump) instruction. Adding it to the instruction set requires a different approach, since it uses neither registers nor the ALU nor memory access. Its sole effect on the CPU's state elements is to change the PC. (Recall that the new PC address is the concatenation of the top four bits of the current PC+4, bits 25-0 of the instruction, and 00.
Figure 5.24 shows what's needed:
shift-left-2 logic, and a wire supplying bits 25-0 of the instruction to the shifter;
logic to concatenate the top four bits of PC+4 to the shifted address;
a new control signal named "Jump", and a multiplexor that uses Jump to select either the computed branch address or the jump address as the new PC.
The new wires and logic appear in solid black in Figure 5.24.
(Note: My copy of the book has a bug in the added portion of the
diagram. Can you identify it.)
We can add the additional colums to our table to contain the control
points for the sequencer. Note that all the sequential
instruction need to set both of these control
points to 0 so that the MUXes in the sequencer give us PC = PC +
4.
inst | operation | Register Transfer | ALUSrc | ALU op | MemRead | MemToReg | MemWrite | RegWrite | RegDst | Br | J |
lw | load word | R[rt]=Mem[ R[rs]+SX(im16) ]; PC = PC+4 | 0 | 00 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
sw | store word | Mem[ R[rs]+SX(im16) ] = R[rt]; PC = PC+4 | 1 | 00 | 0 | x | 1 | 0 | x | 0 | 0 |
beq | branch equal | PC = R[rs] == R[rt] ? PC+4 + SX(im16) : PC+4 | 0 | 01 | 0 | x | 0 | 0 | x | 1 | 0 |
add | add | R[rd] = R[rs] + R[rt]; PC = PC+4 | 0 | 10 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
sub | subtract | R[rd] = R[rs] - R[rt]; PC = PC+4 | |||||||||
and | and | R[rd] = R[rs] & R[rt]; PC = PC+4 | |||||||||
or | or | R[rd] = R[rs] | R[rt]; PC = PC+4 | |||||||||
slt | set less than | R[rd] = R[rs] < R[rt]; PC = PC+4 | |||||||||
addi | add immediate | R[rt] = R[rs] + SX(im16) | 1 | 00 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
j | jump | PC = JumpAddr | x | x | x | x | 0 | 0 | x | 0 | 1 |
inst | Register Transfer | Inst[31-26] | ALUSrc | ALU op | MemRead | MemToReg | MemWrite | RegWrite | RegDst | Br | J |
lw | R[rt]=Mem[ R[rs]+SX(im16) ]; PC = PC+4 | 10 0011 | 0 | 00 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |
sw | Mem[ R[rs]+SX(im16) ] = R[rt]; PC = PC+4 | 10 1011 | 1 | 00 | 0 | x | 1 | 0 | x | 0 | 0 |
beq | PC = R[rs] == R[rt] ? PC+4 + SX(im16) : PC+4 | 00 0100 | 0 | 01 | 0 | x | 0 | 0 | x | 1 | 0 |
add | R[rd] = R[rs] + R[rt]; PC = PC+4 | 00 0000 | 0 | 10 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
sub | R[rd] = R[rs] - R[rt]; PC = PC+4 | ||||||||||
and | R[rd] = R[rs] & R[rt]; PC = PC+4 | ||||||||||
or | R[rd] = R[rs] | R[rt]; PC = PC+4 | ||||||||||
slt | R[rd] = R[rs] < R[rt]; PC = PC+4 | ||||||||||
addi | R[rt] = R[rs] + SX(im16) | 00 1000 | 1 | 00 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
j | PC = JumpAddr | 00 0010 | x | x | x | x | 0 | 0 | x | 0 | 1 |
It already include built-in libraries
- Memory - arithmetic - plexers - input/outputBuild up some of the basic tools that you will need for your data path. You are given subcircuit templates for each of these. Do not change the orientation or relative placement of the input and output pins. Otherwise it will modify the symbol that appears in the main schematic.
We have provided you an implementation of the following.
Reg16 - 16-bit register with async clr and selective load. - Inputs: D[15:0] ld clr - Outputs Q[15:0] - Internally clockedComplete the following using the reg16 component.
RegFile - 16x16-bit register file, 2 read ports and 1 write port. R0 always reads as zero. - Inputs D[15:0] Asel[4:0] Bsel[4:0] Csel[4:0] clr - Outputs A[15:0] B[15:0] - Internally clockedRegister 0 always reads a zero. If no reg write is desired, Dsel should be set to 0.
Complete the design of these two subcircuits and verify their correctness
Drop this in your main circuit as a starting point for your design and build around it. Make sure the component has the pin labels. Add text in the middle of the component so that it is clear what it is.
- Inputs A[15:0] B[15:0] op[2:0] Cin - Outputs R[15:0] Cout The functional behavior is given by the following table op operation 0 0 0 and R = A & B 0 0 1 or R = A | B 0 1 0 xnor R = ~(A ^ B) 0 1 1 add Cout:R = A + B + cin 1 0 0 passB R = BDrop your ALU into main. You can connect input and output pins to verify that it works. You can wire it to your ALU, but you will have to pull them apart again later.