CS2200 Intro to Systems and Networks
|
Project 1 is designed to give you a good feel for exactly how a processor works. In Phase I, you will design a datapath to implement a supplied instruction set architecture. You will use the datapath as a tool to determine the control signals needed to execute each instruction. In Phases II and III you are required to build a simple finite state machine to control your computer and actually run programs on it.
Note: You will need to have a working knowledge of GT Logisim. Make sure that you know how to make basic circuits as well as subcircuits before proceeding. Also, make sure you have the most updated version of GT Logisim! It can be found here.
The assignment is broken up into three phases:
But first you need to see the detailed specification of the Instruction Set Architecture or ISA
The LC-2200-16 (Little Computer 2200-16 bits) is very simple, but it is general enough to solve complex problems. (Note: This is a 16-bit version of the ISA specification you will find in the Ramachandran & Leahy textbook for CS 2200.) This section describes the instruction set and instruction format of the LC-2200. The LC-2200-16 is a 16-register, 16-bit computer. All addresses are word-addresses.
Although, the 16 registers are known as general purpose they are generally assigned special duties by software convention.
Reg# |
Name |
Use |
Callee Save? |
0 |
$zero |
always zero (by hardware) |
n.a. |
1 |
$at |
reserved for assembler |
n.a. |
2 |
$v0 |
return value |
no |
3 |
$a0 |
argument |
no |
4 |
$a1 |
argument |
no |
5 |
$a2 |
argument |
no |
6 |
$t0 |
temporary |
no |
7 |
$t1 |
temporary |
no |
8 |
$t2 |
temporary |
no |
9 |
$s0 |
saved register |
YES |
10 |
$s1 |
saved register |
YES |
11 |
$s2 |
saved register |
YES |
12 |
$k0 |
reserved for OS/traps |
n.a. |
13 |
$sp |
stack pointer |
no |
14 |
$fp |
Frame pointer |
YES |
15 |
$ra |
return address |
no |
Register 0: This register will always contain zero when read from. As an additional feature it may be written to in those cases where a value is not needed.
Note: For the purposes of this project, you must implement the zero register. Regardless of what is written to this register, it should always output zero.
Register 1: Although this is a general purpose register by convention, programmers should not use it. It may be used by the assembler when processing pseudo-instructions.
Register 2: Is designated as the register used to return values from functions.
Registers 3-5: Are designated to be used for passing arguments to functions.
Registers 6-8: Are designated for temporary variables.
Note: When calling a function the programmer should assume that the contents of registers 2-8 that were present when the call was made will no longer be valid. Thus, if needed after the call those values should be saved by the programmer calling the function.
Registers 9-11: These are saved registers.The caller of a function may assume that once the function returns the values that were in these registers before the call will still be there.
Note: This implies that a programmer writing a function that wishes to use these registers should first save them (most likely on the activation stack), then use them and then restore them before returning control to the caller
Register 12: This register is reserved for handling interrupts.
Register 13: The stack pointer which is used to keep track of the location of the top of the activation stack.
Register 14: This is the frame pointer discussed in the class and covered in the textbook. You can ignore it for this project.
Register 15: When a function is called the JALR instruction will save the address to return to and by convention this register is used for that purpose.
There are 4 instruction formats (bit 0 is the least- significant bit).
R-type instructions (add, nand): bits 15-13: opcode bits 12-9: RX bits 8-5: RY bit 4: unused bits 3-0: RZ
I-type instructions (addi, lw, sw, beq): bits 15-13: opcode bits 12-9: RX bits 8-5: RY bits 4-0: offsetField (a 5-bit, 2's complement number with a range of -16 to +15)
J-type instructions (jalr): bits 15-13: opcode bits 12-9: RX bits 8-5: RY bits 4-0: unused (should all be 0)
S-type instructions (halt): bits 15-13: opcode bits 12-0: unused (should all be 0)
Symbolic instructions should follow the same layout. For
example, the add instruction is written in assembly as:
add
<RX><RY><RZ>
------------------------------------------------------------------ Table 1: Description of Machine Instructions ------------------------------------------------------------------ Assembly language Opcode (binary name for instruction) Action (bits 15-13) ------------------------------------------------------------------ add (R-type format) 000 Add contents of RY with contents of RZ, store results in RX. format: add RX, RY, RZ ex: add $v0, $a0, $a1 nand (R-type format) 001 Nand contents of RY with contents of RZ, store results in RX. format: nand RX, RY, RZ ex: nand $v0, $a0, $a1 addi (I-type format) 010 Add contents of RY to contents of offset field and store result in RX. format: addi RX, RY, offsetField ex: addi $v0, $a0, 25 lw (I-type format) 011 Retrieves data from memory location [RY+offsetField] and loads that data into RX. format: lw RX, offsetField(RY) ex: lw $v0, 0x42($sp) sw (I-type format) 100 Retrieves data from RX and stores that data in memory location [RY+offsetField] format: sw RX, offsetField(RY) ex: sw $a0, 0x42($sp) beq (I-type format) 101 Compare the contents of RX and RY; if they are the same, then branch to the address PC+1+offsetField, where PC is the address of the beq instruction. format: beq RX, RY, offsetField ex: beq $a0, $a1, done jalr (J-type format) 110 First store PC+1 into RY where PC is the address of the jalr instruction. Then branch to the address now contained in RX. Note that if RX is the same as RY, the processor will first store PC+1 into that register, then end up branching to PC+1. format: jalr RX, RY ex: jalr $at, $ra halt (S-type format) 111 Halts the processor. ex: halt
Like many processors an assembler for the LC-2200-16 would supply a number of pseudo instructions:
noop - No operation: does nothing ex: noop (actually emits add $zero, $zero, $zero) .byte (pseudo-op) - fill word with a value. ex: .byte 32
The assembler supports labels which represent the address of the line. If a label is used in a beq instruction, it will evaluate to the relative offset.
Example: (address 0): add $s0, $zero, $zero (address 1): loop: addi $s0, $s0, -1 (address 2): beq $s0, $zero, end (address 3): beq $zero, $zero, loop (address 4): end: halt becomes (address 0): 000 1001 0000 0000 0 or 0x1200 (address 1): 010 1001 1001 11111 or 0x533F (address 2): 101 1001 0000 00001 or 0xB201 (address 3): 101 0000 0000 11101 or 0xA01D (address 4): 111 00000000000 00 or oxE000
Figure 1: LC-2200 Datapath
The first thing you must do is to build your basic LC-2200-16 datapath. The basic operation of the datapath will be discussed in class. As you construct your datapath, build in as much functionality that will allow you to operate it "by hand" to allow you to experiment and test the operation.
We suggest your datapath might include devices to allow you to arbitrarily put a value on the bus as well as view the current value of the bus. Feel free to add any additional bells and whistles (maybe LEDs would be better) that you desire to help you understand what is going on.
This semester, you have two choices for Phases II and III of this project. In Phases II and III, you will be building a microcontrol unit which will control all of the signal lines to the various parts of the datapath.
For standard credit, you will be building a very simple control unit that simply consists of a single ROM and a register. If you wish to do this, keep reading the next section. This is very similar to the class discussion and coverage in the textbook.
However, for an additional 10 possible points, you can choose to implement a three ROM microsequencer. This version of the microcontrol unit is a bit more complicated, but it is a MUCH more efficient use of total ROM space. If you want to do this, skip down to the "Bonus" section.
Note that, while the microcode does not change very much between the two versions, the format of how you need to write the microcode is different since we use two different programs to generate the HEX files that you will put into the ROM(s). See the README files in the respective folders for details.
SM control units may be implemented in a number of ways:
Combinational logic combined with a state element such as a
register may be used. Quite common in practice are microcode
designs where the information for each state is stored in a ROM.
For this project, we suggest a simple version of the microcode
approach. Examine figure 2.
Figure 2: Single-ROM Microcontrol Unit
This approach combines a ROM with a register. Operation is simple. The current state is stored in a register as a number. The bits from this register are combined with opcode bits, other bits from the datapath (e.g., Z register) and all together these bits form an address. The contents of that address are bits that are used to specify all control signals to the datapath as well as the number of the next state. The new state gets stored at the end of the clock cycle.
Before getting down to specifics you need to determine the control scheme for the datapath. To do this, examine each instruction, one by one, and construct a finite state bubble diagram showing exactly what control signals will be set in each state. Also, determine what are the conditions necessary to pass from one state to the next. Experiment with the supplied datapath to make sure that your logic is sound.
Once the finite state bubble diagram is produced, the next step is to encode the contents of the Control Unit ROM with a tool we are providing. Then you must design and build (in GT Logisim) the Control Unit circuit which will contain one ROM, a MUX, and a state register. Your design will be better if it allows you to single step and insure that it is working properly. Finally, you will load the Control Unit's ROM with the output of the tool.
Here is a table defining the bits you should use for your control logic:
Note: The control signals listed here are ever so slightly different than those in the Bonus version, so if you decide to switch versions, make sure you account for that.
Input Address to State Machine ROM Bit 0 lower bit State 1 2 3 4 5 higher bit state 6 lower bit opcode 7 8 higher bit opcode 9 lower bit cc (feel free to set to 0) 10 higher bit cc (feel free to set to 0) 11 Z State Machine ROM Contents Bit 0 lower bit State 1 2 3 4 5 higher bit State 6 DrREG 7 DrMEM 8 DrALU 9 DrPC 10 DrOFF 11 LdPC 12 LdIR 13 LdMAR 14 LdA 15 LdB 16 LdZ 17 WrREG 18 WrMEM 19 SelPR 20 RegSelLo 21 RegSelHi 22 ALULo 23 ALUHi RegSelHi RegSelLo Select Register Field 0 0 RX 0 1 RY 1 0 RZ 1 1 Unused ALUHi ALULo ALU Function 0 0 ADD 0 1 NAND 1 0 A-B 1 1 A+1
If you choose to complete this version of the project, you can earn up to 10 bonus points
You will make a Microcontrol Unit which will drive control of the signal lines to the various items on the datapath.
FSM control units may be implemented in a number of ways: Combinational logic combined with a state element such as a register may be used. Quite common in practice are microcode designs where the information for each state is stored in a ROM.
As mentioned above, the simple, single-ROM solution has a lot of wasted space in the ROM since most of the microstates do not depend on the OP code or the Z register to determine which signals to assert. For example, since Z register is an input for the address, every microstate would have to have an address for Z = 0 as well as Z = 1, even though this only matters for one particular microstate.
To solve this problem, we will use a three ROM microcontroller. In this arrangement, we have three ROMs - the main ROM, which outputs the control signals, the sequencer ROM, which helps to determine which microstate to go at the end of the FETCH state, and the OnZ ROM, which helps to determine whether or not to branch during the BEQ instruction. See the following figure.
Figure 3: Three ROM Microcontrol Unit
As you can see, there are three different locations that the next state can come from - part of the output from the previous state (main ROM), the sequencer ROM, and the OnZ ROM. The mux controls which of these sources gets through to the state register. If the previous state's "next state" field determines where to go, neither the OPTest nor chkZ signals will be asserted. If the Op Code from the IR determines the next state (such as at the end of the Fetch state), the OpTest signal will be asserted. If the zero-detection circuitry determines the next state (such as in the BEQ instruction), the TestZ signal will be asserted. Note that these two signals should never be asserted at the same time since nothing is input into the "11" pin on the MUX.
Since we no longer consider the OpCode and zero detection as part of our input for the main ROM, the main ROM can be significantly smaller - more specifically, one address per microstate. The OpCheck ROM should have one address per instruction, and the OnZ ROM should have one address for taking the branch and one for not taking the branch.
NOTE: GT Logisim has a minimum of two address bits for a ROM (i.e. four addresses), even though only one address bit (two addresses) is needed for the OnZ ROM. Just ignore the other two addresses. You may want to do something so that the high address bit for this ROM is permanently set to zero.
Before getting down to specifics you need to determine the control scheme for the datapath. To do this examine each instruction, one by one, and construct a finite state bubble diagram showing exactly what control signals will be set in each state. Also determine what are the conditions necessary to pass from one state to the next. Experiment with the supplied datapath to make sure that your logic is sound.
Once the finite state bubble diagram is produced, the next step is to encode the contents of the Control Unit ROM with a tool we are providing. Then you must design and build (in GT Logisim) the Control Unit circuit which will contain the three ROMs, a MUX, and a state register. Your design will be better if it allows you to single step and insure that it is working properly. Finally, you will load the Control Unit's ROMs with the output of the tool.
Here is a table defining the bits you should use for your control logic:
Note: The control signals listed here are ever so slightly different than those in the Standard version, so if you decide to switch versions, make sure you account for that.
Input Address to State Machine ROM Bit 0 lower bit State 1 2 3 4 5 higher bit state State Machine ROM Contents Bit 0 lower bit State 1 2 3 4 5 higher bit State 6 DrREG 7 DrMEM 8 DrALU 9 DrPC 10 DrOFF 11 LdPC 12 LdIR 13 LdMAR 14 LdA 15 LdB 16 LdZ 17 WrREG 18 WrMEM 19 RegSelLo 20 RegSelHi 21 ALULo 22 ALUHi 23 OPTest 24 chkZ RegSelHi RegSelLo Select Register Field 0 0 RX 0 1 RY 1 0 RZ 1 1 Unused ALUHi ALULo ALU Function 0 0 ADD 0 1 NAND 1 0 A-B 1 1 A+1
Make sure that you are using the tools in the folder that correspond to the version of the project that you are completing.
End of Project 1