A simple 16-bit accumulator-based CPU built from scratch in Verilog. 256 words of addressable memory, 8 general-purpose registers, 16 instructions, 6-cycle pipeline. Runs in Icarus Verilog.
iverilog -o sim *.v # compile
vvp sim # run testbench
gtkwave dump.vcd # view waveforms (optional)| File | What |
|---|---|
cpu.v |
Top level -- wires everything together, contains FSM, PC, IR, ACC |
ALU.v |
ALU top -- routes between arithmetic and logic units |
arithmetic.v |
Add, subtract, increment, decrement |
logic.v |
AND, XOR, OR, NOT |
ALU_inst.v |
Instruction decoder -- maps opcodes to control signals |
cond.v |
Condition evaluation (less, equal, greater) |
memory.v |
Memory interface with address register |
ram.v |
256x16 RAM core |
register_file.v |
8x16 register file |
testbench.v |
Test program exercising all instructions |
isa.md |
Full instruction set documentation |
16 instructions, 4-bit opcode. Full reference in isa.md.
| Opcode | Name | Does |
|---|---|---|
| 0000 | NOP / register ops | No-op, or ACC_TO_REG / REG_TO_ACC |
| 0001 | LDA addr | ACC = mem[addr] |
| 0010 | STA addr | mem[addr] = ACC |
| 0011 | ADD addr | ACC = ACC + mem[addr] |
| 0100 | SUB addr | ACC = ACC - mem[addr] |
| 0101 | AND addr | ACC = ACC & mem[addr] |
| 0110 | XOR addr | ACC = ACC ^ mem[addr] |
| 0111 | OR addr | ACC = ACC | mem[addr] |
| 1000 | NOT | ACC = ~ACC |
| 1001 | INC | ACC = ACC + 1 |
| 1010 | DEC | ACC = ACC - 1 |
| 1011 | JMP addr | PC = addr |
| 1100 | JEQ addr | if ACC==0: PC = addr |
| 1101 | JLT addr | if ACC<0: PC = addr |
| 1110 | JGT addr | if ACC>0: PC = addr |
| 1111 | HLT | Stop |
Every instruction runs in 6 clock cycles (negedge):
- F1 -- load PC into memory address register
- F2 -- read instruction from RAM
- F3 -- latch instruction into IR, increment PC
- E1 -- set operand address, or do register-only ALU, or branch
- E2 -- read/write memory operand
- E3 -- latch ALU result into ACC
Beginner-friendly Verilog. All state elements update on negedge clock. Modules are flat and minimal -- no complicated abstractions, just wires, assigns, and simple always blocks.