Registers

Memory

This is a Harvard (2-memory) architecture. This allows us to implement it as a single-cycle machine.

The instruction memory is a word-addressed read-only memory with 8 address bits and 22 data bits. Unlike MIPS, the instruction memory is not byte-addressed. Instead, each address holds 1 instruction, meaning the memory can hold 256 instructions. This also means that the “next instruction” is at PC + 1, not PC + 4.

The data memory is a byte-addressed RAM with 8 address bits and 8 data bits. This memory can hold 256 8-bit bytes.

Instruction format

cpu2251 instructions are 22 bits long. There is only one instruction format.


The cpu2251 instruction set


Basic instructions

The tutorial walks you through implementing these instructions so I won’t say much here.

Opcode Mnemonic Operation
00000 hlt disable PC register and turn on HALT LED
00001 put rs, rt display <- REG[rs] : REG[rt]
00010 li rd, imm REG[rd] <- imm
00011 mov rd, rs REG[rd] <- REG[rs]

ALU operations

Both shr and sri use logical (unsigned) right shifts.

The not instruction does not use rs or REG[rs] at all. It does bitwise NOT on the second input to the ALU.

Opcode Mnemonic Operation
00100 add rd, rs, rt REG[rd] <- REG[rs] + REG[rt]
00101 sub rd, rs, rt REG[rd] <- REG[rs] - REG[rt]
00110 and rd, rs, rt REG[rd] <- REG[rs] & REG[rt]
00111 or rd, rs, rt REG[rd] <- REG[rs] | REG[rt]
01000 xor rd, rs, rt REG[rd] <- REG[rs] ^ REG[rt]
01001 not rd, rt REG[rd] <- ~REG[rt]
01010 shl rd, rs, rt REG[rd] <- REG[rs] << REG[rt][2:0] (see below)
01011 shr rd, rs, rt REG[rd] <- REG[rs] >>> REG[rt][2:0] (see below)
01100 adi rd, rs, imm REG[rd] <- REG[rs] + imm
01101 sbi rd, rs, imm REG[rd] <- REG[rs] - imm
01110 ani rd, rs, imm REG[rd] <- REG[rs] & imm
01111 ori rd, rs, imm REG[rd] <- REG[rs] | imm
10000 xri rd, rs, imm REG[rd] <- REG[rs] ^ imm
10001 sli rd, rs, imm REG[rd] <- REG[rs] << imm[2:0] (see below)
10010 sri rd, rs, imm REG[rd] <- REG[rs] >>> imm[2:0] (see below)

The not instruction does not use rs or REG[rs] at all. It does bitwise NOT on the second input to the ALU. If you followed the directions in lab 7, your ALU already does this correctly.

Notes on shifting:


Memory access

Opcode Mnemonic Operation
10011 ld rd, [rs+imm] REG[rd] <- RAM[REG[rs] + imm]
10100 st [rs+imm], rt RAM[REG[rs] + imm] <- REG[rt]

When implementing these, think to yourself: do you really need another component to do the addition for the memory address? ;) (Remember the interconnect slides…)


Jumps

Opcode Mnemonic Operation
10101 j imm PC <- imm
10110 jal rd, imm REG[rd] <- PC + 1 see below!
PC <- imm
10111 jr rs PC <- REG[rs]

Two important things about jal:


Branches

All conditional branch comparisons are to be done using signed arithmetic. That means any Comparator component you use must be set to do signed (“2’s complement”) comparisons, or else certain tests will break!

Opcode Mnemonic Operation
11000 blt rs, rt, imm if(REG[rs] < REG[rt]) PC <- PC + imm; else PC <- PC + 1;
11001 bge rs, rt, imm if(REG[rs] >= REG[rt]) PC <- PC + imm; else PC <- PC + 1;
11010 beq rs, rt, imm if(REG[rs] == REG[rt]) PC <- PC + imm; else PC <- PC + 1;
11011 bne rs, rt, imm if(REG[rs] != REG[rt]) PC <- PC + imm; else PC <- PC + 1;

(opcodes 11100 through 11111 are unused.)