CS 447 – Project 3: Apocalypse CPU
Due: Tuesday, April 23, 2013 by 11:59pm

Description

For your final project, you will put together all that you have learned to design the simplest CPU that can do something slightly interesting. It will execute a small set of 16-bit instructions, of two formats:

R-type:

opcode (4-bits)

RS (2-bits)

RT (2-bits)

RD (2-bits)

Unused (6-bits) 000000

15

 

 

 

0

 

I-type (includes jump):

opcode (4-bits)

RS (2-bits)

RT (2-bits)

Immediate (8-bits)

15

 

 

 

0

Registers

There will be four 8-bit registers: $R0, $R1, $R2, and $R3. $R0 is always zero. The rest will hold readable and writeable data.

Instructions

Opcode

Instruction

Action

0000

add $RD, $RS, $RT

$RD = $RS + $RT

0001

sub $RD, $RS, $RT

$RD = $RS - $RT

0010

slt $RD, $RS, $RT

$RD = $RS < $RT

0011

bne $RS, $RT, Immediate

If $RS!=$RT then $PC=$PC+2+Immediate<<1

0100

addi $RT, $RS, Immediate

$RT = $RS + Immediate

0101

beq $RS, $RT, Immediate

If $RS==$RT then $PC=$PC+2+Immediate<<1

0110

nor $RD, $RS, $RT

$RD = !($RS || $RT)

0111

UNUSED

 

1000

sb $RT, Immediate($RS)

Memory[$RS + Immediate] = $RT

1001

UNUSED

 

1010

UNUSED

 

1011

j Immediate

$PC = Immediate

1100

lb $RT, Immediate($RS)

$RT = Memory[$RS + Immediate]

1101

rand $RT, $RS

$RT = random number [0, $RS-1]

1110

disp $RS

Display $RS on the 2 digit hex display

1111

halt

Stops the CPU

 

Example Program

This is a program to display a roll of a single die.

Instruction

Encoding

Comment

addi $r1, $r0, 6

0x4106

Loads 6 into $r1

rand $r2, $r1

0xD600

Sets $r2 to be a random number between 0 and $r1 (=6)

addi $r2, $r2, 1

0x4A01

Adds one to the random number (makes it [1,6])

disp $r2

0xE800

Display $r2 on the hexadecimal display

halt

0xF000

End the program

Circuit Implementation

As with large programs, designing a large circuit should be done in small, manageable chunks. You will want to create a subcircuit for the major parts such as the register file, control, and ALU.

Clock

The most important part of your circuit is a clock element. It will be wired into each of the state elements (Instruction Memory, Register File, Data Memory) to trigger an update.

The halt instruction should block the clock output from reaching the state elements which will effectively stop the CPU from running.

Instruction Memory

For instruction memory, we will use ROM. It will be 8-bit addressable and hold 16-bit data words (our instructions). You can edit the contents of the ROM using the pointer tool and typing hexadecimal numbers or by right clicking the ROM and saying edit or load… There is an assembler linked from the website or you can assemble them by hand. Once you do that, you may save programs you have input and load them later. I have provided a couple sample programs to test your CPU with.

The output of the ROM is an instruction. You can either use a bunch of splitters to extract the right bits and recombine them (for opcode, registers, immediate, etc.) or you can use a bit selector component in logisim. For instance, a bit selector with output bits set to 4 and the selection input of 3 (use a constant element in logisim) will select the 3rd group of 4-bits from the instruction word. Since it is zero-indexed, this means the highest order group of 4 bits, which is our opcode.

Data Memory

Data memory will be a RAM component. Use an 8-bit address and 8-bit data.

Register File

 


The register file is simply a bunch of registers (use the ones built into logisim) with a decoder to select which register to write to. A decoder takes an N-bit input and produces N outputs with only one set. For instance, a 2-to-1 decode will take the input 00 and assert output 0. It will take input 11 and assert output 3.

Use the schematic above to make a 4-register file (you can handle $r0 differently if you prefer) that can handle two different register reads and a single register write. Add the RegWrite control signal to indicate if the register data should be written to the register or not.

ALU

We have seen several ALU designs. You may use the built-in adder, subtracter, nor, and comparator. Make sure you have your result output as well as a zero detector.

We will not worry about overflow.

Output

The display opcode requires us to add two hexadecimal display components. The input to each should be the output of an 8-bit to 4-bit splitter (fan out of 2). We only want to see the displayed register when the display opcode is read. We can use an N-type transistor as a switch to prevent the data from reaching the displays. They will display a dash when no valid data is reaching them (known as “floating”).

Branches and Jumps

The ROM component should be set to 16-bits to grab a whole instruction word. This component then does something slightly different than RAM: It uses the address of a whole 16-bit quantity rather than being byte-addressable. This means to fetch the next instruction you should add in 1. For branches, the left shift by 1 does not need to be done, as the offset is automatically going to be the number of instructions to skip.

The jump instruction will simply replace the contents of PC with the immediate. No addition or scaling needs to be done.

Random

Logisim has a random number generator built-in. Use a divider’s modulus output for the result. Each clock tick will result in a new value (although with a seed of 0, each reset of logism might cause the same values to be displayed).

Control

Control puts it all together. As an input, your control unit will take the opcode. As outputs, you will need a 2-bit ALU op, and control signals for branch, halt, write register, selecting whether to write the result of the ALU, memory, or random number, etc. All of this will be some combinational logic using the opcode.

I have tried to make the opcode to control signal logic easy for many of the instructions.

Hints

·         The probe component quickly shows you the value of a wire going through it.

·         You can select a wire with the pointer tool to see the value it carries as well.

·         Bright green wires are 1-bit true values (useful for debugging control signals).

·         Test components individually. Start with the register file.

·         Read the help on the components. You may use anything in the default built-in library of logisim.

Requirements

By the due date, you need to submit:

·         Your circuit file from logisim with at least the ALU, Register file, and control as subcircuits.

·         2 different programs that run on your CPU written by you in assembly.

·         The machine code version of the 2 programs above saved from the ROM component in logisim.

Submission

Create a zip file of the above and a README.txt text file that has your name, your Pitt username and any notes for the TA to help with grading.

Name the file USERNAME-project3.zip

You will upload the zip file to the directory specified below using a program like FileZilla or WinSCP:

Server: unixs.cis.pitt.edu

Login: Your Pitt username (email before @)/Your password

For the Monday section:

Directory: /afs/pitt.edu/home/j/r/jrmst106/submit/447/monday/

For the Tuesday section:

Directory: /afs/pitt.edu/home/j/r/jrmst106/submit/447/tuesday/