# CPU in 40 lines of SV This project builds a small 16-bit CPU in five incremental steps. Each step is complete, and adds only few new lines. Programs are written directly in SV testbench. [Full CPU here](#full-cpu-40-loc). ```{raw} html
16-bit CPU circuit in 7nm (ASAP7) visualized in 3D. Drag to rotate, scroll to zoom.
``` ### Quickstart ```bash make fresh # if you havent started the container make enter # to enter the running container make sim gtkwave DESIGN=cpu_3_store_data # simulate the step 3 design & view waveform # Ctrl+C to exit gtkwave make sim gtkwave DESIGN=cpu_factorial # run factorial on the final CPU make gds show_layout DESIGN=cpu_factorial # Run GDS flow ``` Example programs: * [`sum_to_n`](https://github.com/abarajithan11/digital-design/blob/main/material/tb/cpu/tb_cpu_sum_to_n.sv) * [`dot_product`](https://github.com/abarajithan11/digital-design/blob/main/material/tb/cpu/tb_cpu_dot_product.sv) * [`factorial`](https://github.com/abarajithan11/digital-design/blob/main/material/tb/cpu/tb_cpu_factorial.sv) * [`fibonacci`](https://github.com/abarajithan11/digital-design/blob/main/material/tb/cpu/tb_cpu_fibonacci.sv) ## Incremental evolution | Level | Feature | RTL | | --- | --- | --- | | `0_memory` | Simple memory with zero-latency read and 1-cycle-latency write | [RTL](https://github.com/abarajithan11/digital-design/blob/main/material/rtl/cpu/memory.sv) | | `1_load_instruction` | Just a counter to load instructions (PC) | [RTL](https://github.com/abarajithan11/digital-design/blob/main/material/rtl/cpu/cpu_1_load_instruction.sv) | | `2_load_data_into_registers` | Sixteen registers and `LOAD` | [RTL](https://github.com/abarajithan11/digital-design/blob/main/material/rtl/cpu/cpu_2_load_data_into_registers.sv) | | `3_store_data` | `STORE` | [RTL](https://github.com/abarajithan11/digital-design/blob/main/material/rtl/cpu/cpu_3_store_data.sv) | | `4_move_alu` | `MOVE`, `ADD`, `SUB`, and `MUL` | [RTL](https://github.com/abarajithan11/digital-design/blob/main/material/rtl/cpu/cpu_4_move_alu.sv) | | `5_jump` | `JNZ`: jump to a given address if a given register is not zero | [RTL](https://github.com/abarajithan11/digital-design/blob/main/material/rtl/cpu/cpu_5_jump.sv) | ## CPU Design * Only 7 opcodes: `LOAD=0`, `STORE=1`, `MOVE=2`, `ADD=3`, `SUB=4`, `MUL=5`, and `JNZ=6`. * Two instruction formats: * Address type: `LOAD, STORE, JNZ` take an `addr`ess and register index (`i_reg`) * Register type: `MOVE, ADD, SUB, MUL` take indices of three registers. Two source (`i_rs1, i_rs2`) and one destination `i_rd`. * `JNZ` jumps to the `addr` when `regs[i_reg]` is nonzero.
Instructions Format 4 Bits [15:12] 4 Bits [11:8] 4 Bits [7:4] 4 Bits [3:0]
LOAD, STORE, JNZ Address addr i_reg opcode
MOVE, ADD, SUB, MUL Register i_rs2 i_rs1 i_rd opcode
### Reading Instructions Each instruction field is 4-bits, so it becomes a character when displayed as hex, making it easy to read binary. Read right to left (little endian). e.g. ``` 0x 1250 : 0=LOAD regs[5] <- dmem[0x12] 0x 0123 : 3=ADD regs[2] <- regs[1] + regs[0] ``` Waveform of Fibonacci program: ![Fibonacci Code](https://media.abapages.com/course-site/fibonacci.png) ## Full CPU (40 LOC) ```{literalinclude} ../material/rtl/cpu/cpu.sv :language: systemverilog ```