Skip to the content
PCBKitNew board
2 layers160 × 140 mm8-Bit CPU, the printed circuit board in 3D

Microcoded 8-bit CPU built from 24 74HC-series ICs: a custom 10-instruction ISA, 4 general-purpose registers, and an EEPROM-driven control unit.

Size
160 × 140 mm
Copper layers
2
Thickness
1.6 mm
Parts
69
Nets
128
Pads
567
Tracks, vias
2,342, 329
Pours
2
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
25 Sep 2026
Updated
25 Sep 2026

Overview

8-Bit CPU is an open-source printed circuit board by otterbox901, from the otterbox901/8-Bit_CPU repository on GitHub. It is a 2-layer board of 160 × 140 mm with 69 parts on 128 nets, routed with 2,342 tracks and 329 vias.

It is built around the 74HC283P-E, 74HC86D and 74HC00D, with the 74HC14, 74HC157D and 74HC161S among its other parts. Its parts include 27 capacitors, 24 ICs, 5 resistors, 3 connectors and 1 diode. It belongs with the retro computing and games boards of this library.

Main components

7

README

README.md

8-Bit CPU

A microcoded 8-bit CPU built from 24 74HC-series logic and memory ICs: custom instruction set, 4 general-purpose registers, add/subtract ALU with Zero and Carry flags, and a control unit driven entirely by two EEPROMs.

image *Preview from JLCPCB

Status: In progress

  • Instruction set (10 instructions, 1- and 2-byte encodings)
  • Microcode ROM generator (ROM/microcode_rom_gen.py)
  • Emulator + assembler, full test program passing
  • Schematic: 24 ICs, 0 ERC errors
  • Schematic verified by simulation: the KiCad netlist runs the test program at the chip-pin level with the real ROM images (kicad_files/sim_netlist.py)
  • PCB: 2-layer, 160 × 140 mm, fully routed (Freerouting), GND pour on both layers; DRC clean (0 errors, 0 warnings, 0 unconnected) and 0 schematic-parity differences
  • Fabrication outputs: Gerbers + drill (fab/8-bit-cpu-gerbers.zip), BOM and pick-and-place files
  • Order boards, burn the EEPROMs, and bring up the hardware

Overview

Data path8-bit
RegistersR0–R3 (2 × 74HC670 register file), plus PC, MAR, IR, A, TEMP
Control unitMicrocoded: 2 × 28C256, addressed by opcode, 2-bit step, Z, C
ALUAdd, subtract (two's complement), Zero and Carry flags
MemoryHarvard: 256 B program EEPROM (28C64), 256 B data SRAM (6116)
Clock1 MHz canned oscillator (target 1–2 MHz), or external via jumper
IC count24 (+ oscillator)
Board2-layer, 160 × 140 mm, SMD logic; EEPROMs and SRAM in DIP sockets so they can be reprogrammed
PowerUSB-C, 5 V, polyfuse

Instruction Set

OpcodeMnemonicBytesOperation
0000NOP1No operation
0001LOAD Rd, addr2Rd ← RAM[addr]
0010STORE Rd, addr2RAM[addr] ← Rd
0011ADD Rd, Rs1Rd ← Rd + Rs (sets Z, C)
0100SUB Rd, Rs1Rd ← Rd − Rs (sets Z, C; C=1 means no borrow)
0101JMP addr2PC ← addr
0110JZ addr2PC ← addr if Z
0111JC addr2PC ← addr if C
1000MOV Rd, Rs1Rd ← Rs
1111HLT1Stop the clock

Unused opcodes behave as NOP. Encoding: byte 0 is [opcode:4][Rd:2][Rs:2]; address instructions add one address byte.

Every instruction takes 4 clock cycles (the 2-bit step counter wraps). Step 0 is always the fetch; conditional jumps are resolved by the control ROM, since Z and C are part of its address.

Control ROM

ROM/microcode_rom_gen.py walks all 256 (opcode, step, Z, C) addresses and writes microcode_table.csv (human-readable) and rom1.bin / rom2.bin (32 KB images for the two 28C256s). Active-low signals are stored inverted, so the ROM outputs drive chip enable pins directly without inverter chips.

bash
cd ROM && python3 microcode_rom_gen.py

Emulator

emulator.py runs programs against microcode_table.csv directly, and includes a two-pass assembler (labels, hex/decimal, .byte, .ram addr, val).

bash
python3 emulator.py test_program.asm           # full ISA test, 6/6 checks
python3 emulator.py test_program.asm --trace-micro
python3 emulator.py -q test_program.asm        # results only

Schematic

kicad_files/8-bit cpu.kicad_sch is generated: edit the PARTS tables in gen_schematic.py and re-run it. It uses only KiCad's stock symbol and footprint libraries, except for the 6116 symbol, which is embedded.

bash
cd kicad_files
python3 gen_schematic.py     # rewrite the schematic
python3 sim_netlist.py       # run test_program.asm on the netlist itself

sim_netlist.py exports the netlist with kicad-cli and models every chip by its datasheet pin numbers. It fails on bus contention, floating inputs, or wrong results. Swapped bus bits and a stuck output enable were both confirmed to be caught.

PCB

Ordering the board

Upload fab/8-bit-cpu-gerbers.zip to JLCPCB, PCBWay, etc. with:

SettingValue
Layers2
Size160 × 140 mm
Thickness1.6 mm
Copper1 oz
Min track / space0.187 mm / 0.2 mm (standard service)
Min hole0.3 mm (vias 0.6 / 0.3 mm)
Plated slotsYes: 4 on the USB-C shell (0.6 × 1.2 mm)
Surface finishAny (HASL is fine)

Checked before export: DRC with freshly refilled zones reports 0 errors, 0 warnings, 0 unconnected and 0 schematic-parity issues. The drill file holds exactly the board's 454 plated holes (329 vias + 125 pads) plus 4 NPTH mounting holes.

fab/bom.csv lists every part to solder. fab/positions.csv is the pick-and-place file (origin at the board's bottom-left corner) for assembled orders. Not in the BOM, but needed:

  • 3 × 28-pin 600-mil DIP sockets (U1–U3) and 1 × 24-pin (U4). The EEPROMs have to come out to be programmed.
  • 1 × 2.54 mm jumper shunt for J2 (pins 1–2 = on-board oscillator).
  • The oscillator (Y1) must be a 7050-size, 5 V part with a tri-state OE on pin 1. HLT stops the clock through that pin.

To regenerate the outputs after a board change:

bash
P="kicad_files/8-bit cpu.kicad_pcb"
kicad-cli pcb drc --refill-zones --schematic-parity "$P"
kicad-cli pcb export gerbers --layers F.Cu,B.Cu,F.Paste,B.Paste,F.Silkscreen,B.Silkscreen,F.Mask,B.Mask,Edge.Cuts --subtract-soldermask -o fab/gerbers/ "$P"
kicad-cli pcb export drill --format excellon --excellon-separate-th -u mm -o fab/gerbers/ "$P"
kicad-cli pcb export pos --format csv --units mm --side both --use-drill-file-origin -o fab/positions.csv "$P"
kicad-cli sch export bom --fields 'Reference,Value,Footprint,${QUANTITY}' --group-by 'Value,Footprint' -o fab/bom.csv "kicad_files/8-bit cpu.kicad_sch"

Clock and timing

  • Registers, PC and flags latch on CLK's rising edge.
  • The step counter (U7) and a control-ROM address latch (U10, holding the opcode and flags) change on CLK's falling edge. The control word only changes while CLK is low and stays stable, glitch-free, while it's high.
  • The two level-sensitive writes, RAM /WE and register-file /Ew, are NAND(CLK, enable), so they only happen during that stable high phase.
  • HLT drives the oscillator's OE low; the clock stops low (R2 pull-down). Reset restarts it.
  • Reset (SW1, RC + Schmitt '14) asserts immediately but is only released on a falling clock edge, via U10 bit 6 and two '00 gates. Without this, a release while CLK is high skips the first fetch's PC increment. The netlist simulation found this bug.
  • J2 CLK SEL: jumper 1-2 selects the on-board oscillator; 2-3 selects EXT_CLK for single-stepping from a button or microcontroller. HLT can't stop an external clock.
  • J3 DEBUG: bus, CLK and GND for a logic analyser.

Known Issues

  • Tracks go down to 0.15 mm where the router threads between SOIC pins (min clearance 0.2 mm); fine for JLCPCB/PCBWay standard service.
  • 74HC670 availability: check stock before ordering; 74LS670 has the same pinout (mixing LS into an HC design is fine at these speeds).
  • ERC warnings (no errors): "symbol doesn't match library" (the embedded copies are flattened), tri-state/output on the '245's input side, the local 6116 symbol, and the intentionally single-pin EXT_CLK label.
  • No on-board regulator: the board runs straight off USB VBUS.
  • Nothing has been tested on real hardware yet.

Repo Contents

text
├── emulator.py              Microcode-driven emulator + assembler
├── test_program.asm         Full instruction-set test
├── ROM/
│   ├── microcode_rom_gen.py Control ROM generator
│   ├── microcode_table.csv  Human-readable ROM contents
│   └── rom1.bin rom2.bin    28C256 images
├── fab/
│   ├── 8-bit-cpu-gerbers.zip  Upload this to the board house
│   ├── gerbers/               Gerbers + Excellon drill files (+ job file)
│   ├── bom.csv                Bill of materials
│   └── positions.csv          Pick-and-place (board-corner origin)
└── kicad_files/
    ├── sim_netlist.py       Netlist-level simulation
    ├── 8-bit cpu.kicad_sch  Generated schematic
    ├── 8-bit cpu.kicad_pcb  Routed 2-layer board
    └── 8-bit cpu.kicad_pro  Project + design rules

Parts

69
QtyValueFootprintReferences
25100nFCapacitor_SMD:C_0603_1608MetricC10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25 +9
4M3MountingHole:MountingHole_3.2mm_M3H1, H2, H3, H4
210kResistor_SMD:R_0603_1608MetricR1, R2
210k x4Resistor_SMD:R_Array_Convex_4x0603RN1, RN2
25.1kResistor_SMD:R_0603_1608MetricR3, R4
274HC283Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU18, U19
274HC86Package_SO:SOIC-14_3.9x8.7mm_P1.27mmU16, U17
110uFCapacitor_SMD:C_0805_2012MetricC2
11MHz osc, tri-state OEOscillator:Oscillator_SMD_SeikoEpson_SG8002CA-4Pin_7.0x5.0mmY1
11kResistor_SMD:R_0603_1608MetricR5
11uFCapacitor_SMD:C_0603_1608MetricC1
174HC00Package_SO:SOIC-14_3.9x8.7mm_P1.27mmU23
174HC14Package_SO:SOIC-14_3.9x8.7mm_P1.27mmU24
174HC157Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU15
174HC161Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU7
174HC161 (PC hi)Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU6
174HC161 (PC lo)Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU5
174HC173 (flags)Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU22
174HC245 (ALU out)Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU20
174HC377Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU10
174HC377 (A)Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU11
174HC377 (IR)Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU9
174HC377 (MAR)Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU8
174HC377 (TEMP)Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU12
174HC670 (R0-R3 bits 0-3)Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU13
174HC670 (R0-R3 bits 4-7)Package_SO:SOIC-16_3.9x9.9mm_P1.27mmU14
174HC688 (zero detect)Package_SO:SOIC-20W_7.5x12.8mm_P1.27mmU21
1750mA holdFuse:Fuse_1206_3216MetricF1
1AT28C256 (ctrl ROM 1)Package_DIP:DIP-28_W15.24mm_SocketU1
1AT28C256 (ctrl ROM 2)Package_DIP:DIP-28_W15.24mm_SocketU2
1AT28C64B (program ROM)Package_DIP:DIP-28_W15.24mm_SocketU3
1CLK SELConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ2
1DEBUGConnector_PinHeader_2.54mm:PinHeader_1x10_P2.54mm_VerticalJ3
1HM6116 (data RAM)Package_DIP:DIP-24_W15.24mm_SocketU4
1PWRLED_SMD:LED_0603_1608MetricD1
1RESETButton_Switch_SMD:SW_SPST_TL3342SW1
1USB-C 5VConnector_USB:USB_C_Receptacle_GCT_USB4125-xx-x_6P_TopMnt_HorizontalJ1

Questions

How big is the 8-Bit CPU PCB?

It measures 160 × 140 mm and has 2 copper layers, 1.6 mm thick.

What parts does the 8-Bit CPU use?

69 parts, built around the 74HC283P-E, 74HC86D, 74HC00D and 74HC14. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the 8-Bit CPU KiCad files?

From the otterbox901/8-Bit_CPU repository on GitHub, at the commit this page was made from: the board is 8-Bit-CPU-main/kicad_files/8-bit cpu.kicad_pcb and its schematic 8-Bit-CPU-main/kicad_files/8-bit cpu.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the 8-Bit CPU design in my own project?

Its repository states no licence, so its author keeps all rights: ask otterbox901 before reusing the design.

Similar boards

  • 2 layers245.1 × 160 mm8-Bit CPU 32k, the printed circuit board in 3D

    8-Bit CPU 32k

    slu4coder/Minimal-64x4-Home-Computer

    My DIY TTL home computer with VGA and PS/2 and 4x the processing power of a Commodore C64 or Apple II.

    139 parts326
  • 2 layers100 × 100 mmHC4 KiCad EE, the printed circuit board in 3D

    HC4 KiCad EE

    nasu8151/HC4

    Schematics and board of HC4 E (E means "for Education").

    125 parts8
  • 2 layers208 × 110 mm8 16 computer 2, the printed circuit board in 3D

    8 16 computer 2

    halfburnttoast/TCPU816-v1

    Version 1.1 of my 8-bit, TTL computer.

    120 parts21
  • 2 layers208.9 × 170.8 mm8-Bit CPU 32k, the printed circuit board in 3D

    8-Bit CPU 32k

    slu4coder/Minimal-UART-Computer-3

    Version 3 of my educational DIY TTL computer built around a UART serial interface - now with blinkenlights!

    207 parts54
  • 4 layers158.8 × 104.1 mm8-Bit CPU, the printed circuit board in 3D

    8-Bit CPU

    frenchie/8-Bit-Computer

    An 8-Bit Computer

    323 parts20
  • 2 layers178 × 711 mmMSAP-2 rev.A SMD, the printed circuit board in 3D

    MSAP-2 rev.A SMD

    mehrantsi/MSAP-2

    An 8-bit computer. Successor to MSAP-1

    658 parts13MIT
  • 2 layers110 × 110 mmCustom cpu, the printed circuit board in 3D

    Custom cpu

    axelo/custom-cpu

    Cutom CPU built from 7400-series integrated circuits (and FLASH roms)

    47 partsMIT
  • 2 layers191.8 × 121.3 mm8-Bit CPU 32k, the printed circuit board in 3D

    8-Bit CPU 32k

    slu4coder/Minimal-UART-Computer-1-2

    Legacy: Version 1 and 2 of my TTL-only CPU featuring UART I/O, an expansion port, 512KB SSD at up to 10MHz clock speed

    109 parts184