
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.

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.
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.
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.
ROM/microcode_rom_gen.py)kicad_files/sim_netlist.py)fab/8-bit-cpu-gerbers.zip),
BOM and pick-and-place files| Data path | 8-bit |
| Registers | R0–R3 (2 × 74HC670 register file), plus PC, MAR, IR, A, TEMP |
| Control unit | Microcoded: 2 × 28C256, addressed by opcode, 2-bit step, Z, C |
| ALU | Add, subtract (two's complement), Zero and Carry flags |
| Memory | Harvard: 256 B program EEPROM (28C64), 256 B data SRAM (6116) |
| Clock | 1 MHz canned oscillator (target 1–2 MHz), or external via jumper |
| IC count | 24 (+ oscillator) |
| Board | 2-layer, 160 × 140 mm, SMD logic; EEPROMs and SRAM in DIP sockets so they can be reprogrammed |
| Power | USB-C, 5 V, polyfuse |
| Opcode | Mnemonic | Bytes | Operation |
|---|---|---|---|
0000 | NOP | 1 | No operation |
0001 | LOAD Rd, addr | 2 | Rd ← RAM[addr] |
0010 | STORE Rd, addr | 2 | RAM[addr] ← Rd |
0011 | ADD Rd, Rs | 1 | Rd ← Rd + Rs (sets Z, C) |
0100 | SUB Rd, Rs | 1 | Rd ← Rd − Rs (sets Z, C; C=1 means no borrow) |
0101 | JMP addr | 2 | PC ← addr |
0110 | JZ addr | 2 | PC ← addr if Z |
0111 | JC addr | 2 | PC ← addr if C |
1000 | MOV Rd, Rs | 1 | Rd ← Rs |
1111 | HLT | 1 | Stop 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.
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.
cd ROM && python3 microcode_rom_gen.pyemulator.py runs programs against microcode_table.csv directly, and
includes a two-pass assembler (labels, hex/decimal, .byte, .ram addr, val).
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 onlykicad_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.
cd kicad_files
python3 gen_schematic.py # rewrite the schematic
python3 sim_netlist.py # run test_program.asm on the netlist itselfsim_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.
Upload fab/8-bit-cpu-gerbers.zip to JLCPCB, PCBWay, etc. with:
| Setting | Value |
|---|---|
| Layers | 2 |
| Size | 160 × 140 mm |
| Thickness | 1.6 mm |
| Copper | 1 oz |
| Min track / space | 0.187 mm / 0.2 mm (standard service) |
| Min hole | 0.3 mm (vias 0.6 / 0.3 mm) |
| Plated slots | Yes: 4 on the USB-C shell (0.6 × 1.2 mm) |
| Surface finish | Any (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:
To regenerate the outputs after a board change:
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"/WE and register-file /Ew, are
NAND(CLK, enable), so they only happen during that stable high phase.EXT_CLK for single-stepping from a button or microcontroller. HLT
can't stop an external clock.local 6116 symbol, and the intentionally single-pin EXT_CLK label.├── 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| Qty | Value | Footprint | References |
|---|---|---|---|
| 25 | 100nF | Capacitor_SMD:C_0603_1608Metric | C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25 +9 |
| 4 | M3 | MountingHole:MountingHole_3.2mm_M3 | H1, H2, H3, H4 |
| 2 | 10k | Resistor_SMD:R_0603_1608Metric | R1, R2 |
| 2 | 10k x4 | Resistor_SMD:R_Array_Convex_4x0603 | RN1, RN2 |
| 2 | 5.1k | Resistor_SMD:R_0603_1608Metric | R3, R4 |
| 2 | 74HC283 | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U18, U19 |
| 2 | 74HC86 | Package_SO:SOIC-14_3.9x8.7mm_P1.27mm | U16, U17 |
| 1 | 10uF | Capacitor_SMD:C_0805_2012Metric | C2 |
| 1 | 1MHz osc, tri-state OE | Oscillator:Oscillator_SMD_SeikoEpson_SG8002CA-4Pin_7.0x5.0mm | Y1 |
| 1 | 1k | Resistor_SMD:R_0603_1608Metric | R5 |
| 1 | 1uF | Capacitor_SMD:C_0603_1608Metric | C1 |
| 1 | 74HC00 | Package_SO:SOIC-14_3.9x8.7mm_P1.27mm | U23 |
| 1 | 74HC14 | Package_SO:SOIC-14_3.9x8.7mm_P1.27mm | U24 |
| 1 | 74HC157 | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U15 |
| 1 | 74HC161 | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U7 |
| 1 | 74HC161 (PC hi) | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U6 |
| 1 | 74HC161 (PC lo) | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U5 |
| 1 | 74HC173 (flags) | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U22 |
| 1 | 74HC245 (ALU out) | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U20 |
| 1 | 74HC377 | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U10 |
| 1 | 74HC377 (A) | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U11 |
| 1 | 74HC377 (IR) | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U9 |
| 1 | 74HC377 (MAR) | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U8 |
| 1 | 74HC377 (TEMP) | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U12 |
| 1 | 74HC670 (R0-R3 bits 0-3) | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U13 |
| 1 | 74HC670 (R0-R3 bits 4-7) | Package_SO:SOIC-16_3.9x9.9mm_P1.27mm | U14 |
| 1 | 74HC688 (zero detect) | Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm | U21 |
| 1 | 750mA hold | Fuse:Fuse_1206_3216Metric | F1 |
| 1 | AT28C256 (ctrl ROM 1) | Package_DIP:DIP-28_W15.24mm_Socket | U1 |
| 1 | AT28C256 (ctrl ROM 2) | Package_DIP:DIP-28_W15.24mm_Socket | U2 |
| 1 | AT28C64B (program ROM) | Package_DIP:DIP-28_W15.24mm_Socket | U3 |
| 1 | CLK SEL | Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical | J2 |
| 1 | DEBUG | Connector_PinHeader_2.54mm:PinHeader_1x10_P2.54mm_Vertical | J3 |
| 1 | HM6116 (data RAM) | Package_DIP:DIP-24_W15.24mm_Socket | U4 |
| 1 | PWR | LED_SMD:LED_0603_1608Metric | D1 |
| 1 | RESET | Button_Switch_SMD:SW_SPST_TL3342 | SW1 |
| 1 | USB-C 5V | Connector_USB:USB_C_Receptacle_GCT_USB4125-xx-x_6P_TopMnt_Horizontal | J1 |
It measures 160 × 140 mm and has 2 copper layers, 1.6 mm thick.
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.
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.
Its repository states no licence, so its author keeps all rights: ask otterbox901 before reusing the design.

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.



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



axelo/custom-cpu
Cutom CPU built from 7400-series integrated circuits (and FLASH roms)

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