CS 447 – Project 3: Apocalypse CPU
Due: Sunday, July 29, 2012 by 11:59pm


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:


opcode (4-bits)

RS (2-bits)

RT (2-bits)

RD (2-bits)

Unused (6-bits) 000000







I-type (includes jump):

opcode (4-bits)

RS (2-bits)

RT (2-bits)

Immediate (8-bits)







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






add $RD, $RS, $RT

$RD = $RS + $RT


sub $RD, $RS, $RT

$RD = $RS - $RT


slt $RD, $RS, $RT

$RD = $RS < $RT


xor $RD, $RS, $RT

$RD = $RS ^ $RT


addi $RT, $RS, Immediate

$RT = $RS + Immediate


beq $RS, $RT, Immediate

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


j Immediate

$PC = Immediate





lb $RT, Immediate($RS)

$RT = Memory[$RS + Immediate]











sb $RT, Immediate($RS)

Memory[$RS + Immediate] = $RT


rand $RT, $RS

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


disp $RS

Display $RS on the 2 digit hex display



Stops the CPU


Programming Manual

·         To do li, first zero out the register by xoring it with itself, and then do an addi.

Example Program

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




xor $r1, $r1, $r1


Zero out $r1

addi $r1, $r1, 6


With xor, loads 6 into $r1

rand $r0, $r1


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

addi $r0, $r0, 1


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

disp $r0


Display $r0 on the hexadecimal display



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.


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… I hope to have an assembler for you soon, but in the meantime, you can assemble them by hand. Once you do that, you may save programs you have input and load them later. I will provide a few 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 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.


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

We will not worry about overflow.


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 a 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.


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 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.


·         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.


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 in assembly.

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

Put these in a zip file and upload to the submission site. Remember that your username is your @pitt.edu email address and your password is your peoplesoft number.