Designing a Simple CPU
35.1 Architecture
An 8-bit accumulator CPU with:
Program counter (PC), instruction register (IR), accumulator (ACC), zero flag (Z).
A 256-word memory holding both instructions and data, with 16-bit instructions: a 4-bit opcode, 4 unused bits, and an 8-bit operand (address).
Instructions: LOAD addr, STORE addr, ADD addr, SUB addr, JMP addr, JZ addr, OUT, HALT.
Multi-cycle FSM: FETCH → DECODE → EXECUTE (→ MEMORY → WRITEBACK).
35.2 Implementation sketch
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tiny_cpu is
port (
clk, rst : in std_logic;
out_port : out std_logic_vector(7 downto 0);
halted : out std_logic);
end entity;
architecture rtl of tiny_cpu is
type mem_t is array (0 to 255) of std_logic_vector(15 downto 0);
-- Program: count down from 5 to 0, outputting each value
signal mem : mem_t := (
0 => x"1" & x"0" & x"10", -- LOAD [16]
1 => x"7" & x"0" & x"00", -- OUT
2 => x"4" & x"0" & x"11", -- SUB [17]
3 => x"6" & x"0" & x"05", -- JZ 5
4 => x"5" & x"0" & x"01", -- JMP 1
5 => x"7" & x"0" & x"00", -- OUT (prints 0)
6 => x"F" & x"0" & x"00", -- HALT
16 => x"0005", -- data: 5
17 => x"0001", -- data: 1
others => (others => '0'));
type state_t is (FETCH, DECODE, EXECUTE, HALT_ST);
signal state : state_t := FETCH;
signal pc : unsigned(7 downto 0) := (others => '0');
signal ir : std_logic_vector(15 downto 0);
signal acc : unsigned(7 downto 0) := (others => '0');
alias opcode : std_logic_vector(3 downto 0) is ir(15 downto 12);
alias operand : std_logic_vector(7 downto 0) is ir(7 d
…35.3 Going further
Separate datapath and control unit; register file; ALU from §12.4.
Pipelined RISC (IF/ID/EX/MEM/WB) with hazard detection and forwarding.
Implement a subset of RISC-V RV32I and run C programs compiled with GCC (study NEORV32, a full RISC-V SoC written in VHDL).
Add UART, timers, GPIO via a memory-mapped bus; write an assembler in Python.