Computer Architecture |
Course
Index Return to Dr. Margush's page |
CPU (Crazy Professor's Unit) (Get the revised CLOCK unit) The CPU diagram (you can click on the image to view it full size) for our Multimedia Logic project will serve as a reference for your work. The first step will be to design the program counter unit. Next we will add the program memory and inbstruction registers. Then we can add the major data path, and finally the data memory unit.
The file for the program counter is mostly completed. You can download it and use it as a starting point for the project. Be sure to replace the clock with this version before going on to part II.
Part I:
The first assignment is to connect up a program memory and opcode and operand register. You should also begin building a main control panel.
The control panel needs a clock enable, a reset pushbutton, and a single step pushbutton. You should also be able to load an opcode and operand directly into the instruction register by dialing in the desired values and pressing a pushbutton. This will copy the data into the instruction registers (independent of the clock settings).
Your control panel must also display the current PC value, and the opcode and operand. We will be adding more later. There should also be a text control that shows the decoded instruction (LOAD, STORE, etc). You will need to build a program memory file (be sure only the filename is shown in the settings window, and not a complete path to the file). Place a sequence of instructions in this file to illustrate all possible instructions.
When you run the simulator, you should be able to see each instruction fetched in turn. By the way... the JSL should be hard-wired to simply increment the PC for this assignment (or you can keep the control switches I provided).
Instruction format: 16 bits - [operation byte][operand byte]
Opcode Table (Opcode is in bits 2-0 of operation byte)
| Mnemonic | Opcode | Instruction description |
| load | 000 | Load register |
| store | 001 | Store register |
| add | 010 | Add to A |
| sub | 011 | Subtract from A |
| j | 100 | Jump |
| jz | 101 | Jump if Z flag is set |
| jc | 110 | Jump if C flag is set |
| nop | 111 | NOP (or for future expansion) |
Target register (bit 3 of operation byte)
Addressing modes (bits 5-4 of operation byte)
| Mode | Code | Notes |
| Immediate | 00 | Operand is the data. Available with load, add, subtract. |
| PC-Relative | 00 | Operand is a signed integer to be added to the program counter. Avaliable only with the jump instructions. |
| Direct | 01 | Operand is memory address. Available with load, store, add, subtract , and jump instructions. |
| Indirect | 10 | Address is in B. Available with load, store, add, subtract , and jump instructions. |
| Implied Register | 11 | The operand is a register (usually the opposite of target). Available with load, add, subtract. |
Expansion bits (bits 7-6 of operation byte) are always zero in this version of the processor. This allows for future expansion.
Here are some example pseudo-assembly instructions and what is intended.
| Assembly | Instruction | Interpretation |
| load A, #46 | 00000000 01000110 | Load A with the constant 0x46. Any constant 0x00 - 0xFF may be specified. Register B may also be specified as the destination. |
| load B, 46 | 00011000 01000110 | Load B with the byte at memory location 0x46. Any address 0x00 - 0xFF may be specified. Register A may also be specified as the destination. |
| load A, (B) | 00100000 00000000 | Load A with byte at memory location found in B. This mode also allows load B, (B). The operand is not relevant. |
| load A, B | 00110000 00000000 | Load A from B. This mode also allows load B, A. The operand is not relevant. |
| store 46, B | 00011001 01000110 | Store B at memory location 0x46. |
| store (B), A | 00100001 00000000 | Store A at memory location found in B. This mode also allows store (B), B. The operand is not relevant. |
| add A, #46 | 00000010 01000110 | A = A + 0x46. You can also specify B as the destination, but A is always the first operand of an add instruction. You may substitute sub (subtract) in any of these examples. The zero and carry flags are set according to the result when an add or subtract instruction is executed. |
| add B, 46 | 00011010 01000110 | B = A + mem[0x46] |
| add A, (B) | 00100010 00000000 | A = A + mem[B]. This mode also allows add B, (B). The operand is not relevant. |
| add A, B | 00111010 00000000 | A = A + B. The second addend B is implied - there is no other register it can be. The other option, add B, B, would perform B = A + B. |
| j 46 | 00010100 01000110 | PC = 0x46. The target register is not relevant, but will always be 0. Any address 0x00 - 0xFF may be specified. The same formats hold for jz and jc. |
| j (B) | 00100100 00000000 | PC = B. The target register is not relevant, but will always be 0. The operand is not relevant. |
| j (46) | 00000100 01000110 | PC = PC + 0x46 + 1. The target register is not relevant, but will always be 0. |
Part II:
Implement the opcode and operand registers and instruction decoder and internal data pathway (A, B, ALU). The opcode should select an address in a read-only memory (the decode unit). The decode unit's outputs will be the control signals for the processor. Each opcode will assert certain control signals. To initialize the decode unit signals, create a memory file with the appropriate control signal data. For the ALU unit, you can use the ALU in MML. It only needs a few control options.
Control signals are indicated on the system diagram above. Most of these will need to be encoded to reduce the number of bits needed; I think a single byte will suffice. For example, there are 4 sources for the B-Bus, so only two bits are needed in the control signal data - only one of these may be applied to the B-Bus at one time. Be sure you document the control signals for your own sanity.
Note that the opcode/operand registers load on the rising edge, while all other operations (PC, memory write, and load A or B take place on the falling edge (meaining you will use the inverted clock signal to control these actions).
For now, we will leave out the ALU status bits (Zero and Carry flag), jump control, and indirect addressing control, so the PC circuit will still just increment, and the operand register can feed directly into the memory address bus (and optionally onto B). You should be able to place a program in program memory that tests the basic instructions above. Create a small program that uses immediate mode to load registers and add. Then add memory store and loads using direct addressing mode, and test the subtract feature. Be sure to test register, direct, and immediate addressing for the arithmetic operations. Here is a simple test program that you should encode and supply with your program submission. Please zip all files and email the archive to me. You must also provide a printed report explaining how the control signals are encoded.
load a, #46 load b, #72 add a, b add b, b add a, #2 store 3, b load b, a store 4, b sub a, #1 nop (either one) load b, #0 load a, b load a, #3 load b, #4 add a, 4 sub b, 3 add b, b sub a, b
Feel free to add other things that I did not think of; you should also notify me if any of these instructions are illegal
Part III:
This will add the indirect addressing and the jump instructions. Basically this will require some additional control signals and a little more added to the circuit. Be sure to capture the Z and C ALU outputs only for instructions that affect these flags. These values are then used as input for conditional jumps in the JSL circuit.
The jump instructions will need to place the correct address on the C Bus (for PC-relative, direct and indirect jumps) and implement the JSL logic appropriately.
Indirect addressing for the other instructions simply needs a 2x1 mux to select between Operand and B as the address applied to the memory unit.
Test the new instructions. Write a program that does someting interesting.