Design and build a custom CPU using the Digital circuit simulation software.
The CPU must:
- Load a program into memory.
- Execute it step by step.
- Store the result.
- Output the result when requested.
To view or edit this project, open the .dig file using the Digital circuit simulator:
🔗 Digital by hneemann on GitHub
- Size: 256 × 14 bits
- Purpose: Store program instructions loaded from input
progIn.
- Size: 256 × 8 bits
- Purpose: Store results produced by the CPU (addresses
0x00–0x0F).
| Signal | Size | Description |
|---|---|---|
| M | 8 bits | Parameter 1 |
| N | 8 bits | Parameter 2 |
| progIn | 14 bits | Program data input (one instruction at a time) |
| reset | 1 bit | Resets CPU and clears all rRAM values to 0 |
| progLoad | 1 bit | When 1, loads instructions from progIn into pRAM sequentially |
| start | 1 bit | Starts executing the program stored in pRAM |
| result | 1 bit | When 1, outputs results stored in rRAM |
| clk | 1 bit | Clock signal for synchronization |
| Signal | Size | Description |
|---|---|---|
| valid | 1 bit | Goes high when execution finishes and CPU is ready to output results |
| done | 1 bit | Goes high when everything is done (after sending results or after reset) |
| output | 8 bits | Shows rRAM data (hex values, addresses 0x00–0x0F) after result signal |
| 7-segment (2 units) | — | Displays the output value for verification |
- Architecture: Must be Multiple-Cycle or Pipeline — Single-Cycle is not allowed.
- Control Unit: Can be sequential logic or microprogrammed.
- Arithmetic: Use 8-bit 2’s complement representation (unless otherwise stated).
- Registers: You must design additional registers as needed.
- Instruction Set: You don’t need to support every possible instruction — only the ones required for test cases.
- Execution:
- Program starts from address 0x00 in pRAM.
- Runs until it encounters a “halt” instruction.
- Then waits for the
resultsignal to send outputs.
- Timing: Operates on the positive edge of the clock.
- Reset behavior: Must clear rRAM and set
donehigh after at least 20 clock cycles.
Each instruction has a 14-bit structure divided into:
- Opcode (6 bits) — defines the operation.
- Operand (8 bits) — provides data or an address.
| Bits | Field | Description |
|---|---|---|
| [13:8] | Opcode (6 bits) | Operation code |
| [7:0] | Operand (8 bits) | Data / address / immediate value |
- All registers (
accA,accB,regC,regD) are 8-bit. - Arithmetic operations are performed in 2’s complement, unless otherwise stated.
- The CPU uses multi-cycle or pipelined execution.
- The program executes sequentially from address 0x00 until a
STOPinstruction is encountered.
| Name | Description |
|---|---|
accA |
Accumulator A |
accB |
Accumulator B |
regC |
General-purpose Register C |
regD |
General-purpose Register D |
| Opcode | Mnemonic | Description |
|---|---|---|
| 000000 | NOPE | Do nothing, go to the next instruction. |
| 000001 | accA ← Operand | Load the 8-bit operand into accA. |
| 000010 | accB ← Operand | Load the 8-bit operand into accB. |
| 000011 | accA ← accB | Copy accB into accA. |
| 000100 | accB ← accA | Copy accA into accB. |
| 000101 | regC ← accA | Store accA into regC. |
| 000110 | accA ← regC | Load accA from regC. |
| 000111 | regD ← accA | Store accA into regD. |
| 001000 | accA ← regD | Load accA from regD. |
| 001001 | regC ← M | Load input M into regC. |
| 001010 | regC ← N | Load input N into regC. |
| 001011 | regD ← M | Load input M into regD. |
| 001100 | regD ← N | Load input N into regD. |
| 001101 | regC ← M; regD ← N | Load M into regC and N into regD. |
| 001110 | accA ← regC; accB ← regD | Load accA from regC and accB from regD. |
| 001111 | accA ← pRAM[Operand] | Load lower 8 bits from pRAM at the given operand address into accA. |
| 010000 | accA ← rRAM[Operand] | Load data from rRAM at the operand address into accA. |
| 010001 | rRAM[Operand] ← accA | Store accA into rRAM at the operand address. |
| 010010 | JMP Operand | Unconditional jump to address = operand. |
| 010011 | JMP.EQ Operand | Jump if equal flag = 1. |
| 010100 | JMP.GR Operand | Jump if greater flag = 1. |
| 010101 | JMP.LE Operand | Jump if lesser flag = 1. |
| 010110 | JMP.EQ/GR Operand | Jump if equal or greater flag = 1. |
| 010111 | JMP.EQ/LE Operand | Jump if equal or lesser flag = 1. |
| 100000 | accA ← accA + accB | Add accB to accA, store in accA (2’s complement). |
| 100001 | accA ← accA - accB | Subtract accB from accA, store in accA (2’s complement). |
| 100010 | accA ← accA × accB | Multiply lower 4 bits (accA[3..0] × accB[3..0]), store in accA (unsigned). |
| 100011 | accA ← accA ÷ accB | Divide accA by accB (unsigned), store in accA. |
| 100100 | accA ← accA % accB | Compute modulus (unsigned), store in accA. |
| 100101 | accA ← accA ^ accB | Raise accA[2..0] to the power of accB[2..0], store in accA (ignore overflow). |
| 101000 | accA ← NOT(accA) | Bitwise NOT of accA. |
| 101001 | accA ← accA AND accB | Bitwise AND. |
| 101010 | accA ← accA OR accB | Bitwise OR. |
| 101011 | accA ← accA XOR accB | Bitwise XOR. |
| 101100 | accA ← accA << accB | Logical shift left by accB[2..0] bits (max 7). |
| 101101 | accA ← accA <<< accB | Rotate left by accB[2..0] bits (max 7). |
| 101110 | accA ← accA >> accB | Logical shift right by accB[2..0] bits (max 7). |
| 101111 | accA ← accA >>> accB | Rotate right by accB[2..0] bits (max 7). |
| 110000 | CMP accA, accB | Compare (2’s complement) and set flags: • equal=1 if accA == accB • greater=1 if accA > accB • lesser=1 if accA < accB |
| 110001 | isPrime(accA) | Check if accA is prime (unsigned). • equal=1 if prime • greater and lesser flags unaffected. |
| 110010 | accB | accA | Check if accA is divisible by accB (unsigned). • equal=1 if divisible • Other flags unaffected. Example: accA=20, accB=5 → divisible → equal=1. |
| 110011 | rRAM[0x0E:0x0F] ← LCM(rRAM[Operand[7:4]], rRAM[Operand[3:0]]) | Compute Least Common Multiple (LCM) of two rRAM values: • m = rRAM[Operand[7:4]] • n = rRAM[Operand[3:0]] Store result[15:8] → rRAM[0x0E], result[7:0] → rRAM[0x0F]. LCM Reference |
| 110100 | rRAM[0x0A:0x0B] ← FAC(accA[2:0]) | Compute Factorial of accA[2:0] (0–7 range). Store result[15:8] → rRAM[0x0A], result[7:0] → rRAM[0x0B]. Must be implemented using ASM loops (no ROM shortcuts). Factorial Reference |
| 110101 | rRAM[0x09] ← max(pRAM[accA:accB]) | Find maximum value among pRAM[accA] to pRAM[accB] (lower 8 bits only). Result stored in rRAM[0x09]. Comparison uses 2’s complement. Guaranteed that accA <= accB. |
| 111111 | STOP | Halt program execution and wait for the result signal. |
This Mini CPU is developed as part of the CEDT Final Project for the course:
2110252 – Digital Computer Logic