Skip to content

Repository files navigation

 

Tomato - 32b Discrete Computer

32-bit Computer. The oddest machine built in a dorm.

Status Architecture License Logic

ALU ISA Microcode PCB

Before Tomato, there was the transistor board. Same story, same narrative—but this time, it had to be smarter.

By Tyrone Marhguy · Computer Engineering ’28

Before Tomato, there was an 8-bit ALU built from roughly 3,488 discrete CMOS transistors across a massive 270×270 mm board. It was a beast in its own right: capable of 19 operations, sporting 5 flags, and power hungry.

But for a solo dorm-room project, the manufacturing costs ballooned exponentially, so I needed a pivot. Same story, same narrative—but this time, it had to be smarter. Welcome to Tomato!

The paper: tomato.tmarhguy.com · the site: web/README · the vault: docs/log/.

Tomato 07_alu — Dual-LUT slice in the round Tomato 07_alu — first population, next to Digital

Lot 07 in the round & on the iron · Dual-LUT slice · playground

Tomato grew as a revolution: a 65k operational space (~3,500× operation increase than the earlier 8bit board for less area) from a dual-LUT3 fused into an adder, built for linear scale. The ALU is two independent 3-input LUTs plus a ripple adder per 4-bit nibble: out = f(a,b,c) + g(a,b,c) + cin. A 512-row opcode ROM fans out into modular control boards that sit next to the hardware they actually drive. The design journal is where the arguments live; this README is the map.

The dual-LUT slice is on the iron — muxes and adders down on one 07_alu board.

See log: First Phase of Assembly

Metric Transistor Board (Previous) Tomato ALU (Current) Optimization Achieved
Architecture 8-bit 32-bit 4× datapath width
Logic Base ~3,488 discrete CMOS transistors Dual-LUT3 + Ripple Adder Massive density increase
Ops Space 19 operations ~65k combinations ~3,500× expansion
Footprint Single massive 270×270 mm PCB Modular 4-bit slice boards Better routing, linear cost
Control Fixed decode logic 512-row microcode ROM Programmable ISA overlay

Why Tomato

Tomato is intentionally a build log machine. Every odd choice is documented somewhere in docs/log/ — what was tried, what broke routing, what was too slow on the bench, what got deleted to recover PCB area. If you love computers because you like how they are built, not just what they run, that journal is the real entry point. Start with Welcome to Tomato 32.

The ALU is the center. Most CPUs hide a small ALU behind a conventional encoding. Tomato flipped it: the bit-slice is a programmable logic plane — half a million theoretical (lutA, lutB, csel) programs per slice — with an adder wired through it. The opcode ROM names a practical subset. Matching every LUT pair to its own instruction was never the goal; dark silicon stays in the catalogs until a program actually needs it.

Building beats spreadsheets. Instruction width, bank counts, and profile matrices are fun to expand. Copper, EEPROMs, and weeks at the wire wrap are not. When a wider word width doubled the explanation burden without doubling silicon on the bench, the answer was to fall back to 32b and ship what already routes.

Decode travels with the datapath. One central microcode blob is elegant in simulation and miserable on a breadboard — shift controls leaving the ALU board, flag writes leaving memory control, PC fields split across ROM bytes. Tomato split decode into small boards with local EEPROMs so ribbons stay short and each slice can be brought up alone.

Clever, but only at the right scale. Naïve shift → add multiply is easy and takes forever — “slower than I am when half-asleep.” A Wallace tree is fast and eats the board. The answer was a priority-encoder loop that jumps over zero bits. Same story for the display: K-map gates were correct and physically absurd; one shared ROM plus latches made sharing invisible (segment display log).

ISA as a wire. Tomato is a parametric datapath: the overlay word, immediate box, and dual-LUT absorb a foreign encoding as a map onto muxes — not an emulator. A casual family count sits around ~37 (profiles.csv has more rows because variants are listed separately). The integer is not a ceiling; it moves as the datapath does.


Table of Contents

The paper is tomato.tmarhguy.com. Site notes: web/README.


Architecture at a glance

32-bit instruction word

Fetch, IR, ALU datapath, and register operands are 32-bit. The instruction layout is tight: 9-bit opcode, four 5-bit register indices, and a 3-bit bank select fill the word — with low bits often double-booked as immediate or branch/jump mode overlay depending on the mnemonic.

Typical field packing (ALU register ops):

Field Bits Slice Role
Opcode 9 [31:23] Indexes microcode ROM (512 rows)
rd 5 [22:18] Destination (5-bit index within bank)
rA 5 [17:13] ALU operand A
rB 5 [12:8] ALU operand B
rC 5 [7:3] ALU operand C
BANK 3 [2:0] Bank select (8 banks → 32 GPR × 8 = 256 regs)

Each operand is 5 + 3b bank in address terms: a 5-bit GPR index within the bank selected by BANK[2:0].

[31:23]  opcode
[22:18]  rd
[17:13]  rA
[12: 8]  rB
[ 7: 3]  rC
[ 2: 0]  BANK (+ mode bits for branches/jumps)

Overlay encodings (same slices reinterpreted by microcode):

Mnemonic class Overlay Notes
Branches [2:0] = COND Taken when selected flag is set
Jumps / calls [0] abs vs PC-rel 0 = absolute target in low bits; 1 = PC + offset
ADDI / imm12 [12:8] imm-high Immediate high nibble; low pieces in other fields
Load / store offset [12:8] imm-high Address =rA + sign-extended immediate

Native ALU syntax (conceptual):

opcode  rd, rA, rB, rC    ; rd = f(a,b,c) + g(a,b,c) + cin

See opcode-map.csv for mnemonic layout and Load Store Pipeline Analysis for the 48-bit microcode control fields.

Register file

32 GPR × 8 banks = 256 addressable registers. Not the full theoretical address space the LUT catalog could name — enough for real programs and modular board bring-up without widening the datapath.

Datapath and control

Program Counter ──► Memory ──► Instruction Register (32b)
                                      │
          ┌───────────────────────────┼───────────────────────────┐
          │                           │                           │
          ▼                           ▼                           ▼
   Register File 3R1W            alu-control              mem-io / mem-bus
          │                           │                           │
          ▼                           ▼                           ▼
   Dual-LUT ALU 32b ◄──────── (drives)                   Memory ◄── pc-control ──► PC
          │
          ▼
   Writeback Mux ─────────────────► Register File

   IR ──► shift-mul-control ──► ALU

Control is split into small boards (each with a local EEPROM) that decode the same opcode from the IR. See Microcode Control Modularization. For Mermaid diagrams in Cursor, install extension bierner.markdown-mermaid (listed in .vscode/extensions.json).

ALU bit-slice

alu_out = adder( f(a, b, c), g(a, b, c), carry_in )

Per bit-slice there are 524,288 theoretical (lutA, lutB, csel) combinations; the 512-row opcode ROM exposes what programs need today. The LUT3 feeds the adder directly — no mode mux at the end of the slice — logic rides the arithmetic path instead of racing it. Carry select uses 74251 muxes where 74151 cost routing and drive strength (74251 note). Authority: docs/isa/tomato.v1.csv.


Source of truth

Layer Authority Consumers
Logic / timing hardware/digital/modules/*.dig KiCad bring-up, Verilog export
Opcode mnemonics docs/opcode-map.csv Assembly reference, ROM programming
Microcode fields docs/isa/tomato.v1.csv Single ISA / ROM authority
LUT programs docs/isa/lut.csv ALU primitive catalog
Control ROM images microcode/*.hex Digital control boards
Physical PCB hardware/kicad/boards/ Fab / assembly
ALU sign-off verification/ Digital export →rtl/*.v → formal + directed + UVM

Policy: Digital .dig schematics are editable source. Exported Verilog in verification/rtl/ is read-only — copy from Digital, then run sign-off.


Repository map

tomato/
├── docs/
│   ├── isa/              # opcodes, alu8 catalog, profiles
│   ├── log/              # Design journal (Obsidian vault)
│   └── alu/              # LaTeX ALU reference docs
├── hardware/
│   ├── digital/modules/  # Digital schematics (.dig) — logic source of truth
│   ├── kicad/boards/     # Numbered PCB designs (01_alu … 08_display)
│   ├── fpga/             # Vivado projects (FSM, hex display)
│   └── verilog/          # Export policy (read-only netlists)
├── microcode/            # Per-board control ROM hex images
├── verification/         # ALU harness: formal, directed, UVM
├── firmware/             # Stub — not started
├── software/             # Stub — not started
├── web/                  # Broadsheet — tomato.tmarhguy.com
└── media/                # Screenshots, PCB photos, schematic exports

Key hardware modules

Digital schematics

Module Role
main.dig Top-level CPU integration
alu-32b-final.dig 32-bit ALU
alu-control.dig, ir-reg-control.dig, mem-bus-control.dig, mem-io-control.dig, pc-control.dig, shift-mul-control.dig Modular decode ROM boards
register.dig, program-counter.dig, mul-div.dig Datapath slices
alu-display-control.dig 32-digit hex display for bring-up

ALU verification ladder: alu-1b-final → 2x alu-4b → 4x alu-8balu-32b-final.

KiCad boards

Board Path Role Status
01 01_alu/ Early ALU experiments Historical
02 02_shift_encoder/ Shift encoder + mul-div control In design
03 03_memory/ Memory, byte-lane decoder, VGA In design
04 04_register/ Register file, IR In design
05 05_program_counter/ PC, stack pointer In design
06 06_data_bus/ Data bus, wb_mux, bus arbitration In design
07 07_alu/ Dual-LUT ALU PCB —board doc + figures Populating
08 08_alu_fsm/, 08_display/ FSM bring-up, display In design

Tomato ALU PCB — board render Tomato ALU PCB — top-layer layout

Lot 07 · left: board render · right: routed top copper · two 4-bit cells, flag logic, opcode/operand LED bring-up (full ALU board doc)


ISA and opcodes

512-row opcode ROM — enough for native ALU ops, load/store, branches, shifts, and mul/div without empty decode fanout. See ISA as a Wire.

Resource Path Role
Mnemonic cheat sheet docs/opcode-map.csv 32-bit encoding, syntax, groups
Microcode catalog docs/isa/tomato.v1.csv Source of truth — burn opcodes + ROM map
ALU programs docs/isa/lut.csv LUT primitive catalog
ISA maps docs/isa/profiles.csv Parametric maps onto native opcodes.~37 families; CSV rows are the sweep database

An ISA is a mapping from an external encoding onto the overlay word, immediate box, and dual-LUT — not a separate hardware ISA, and not an interpreter.


Run in Digital

  1. Install Digital by Heinrich Hneemann — download Digital.zip from Releases, unpack, run Digital.jar (Java required).
  2. In Digital: File → Openhardware/digital/modules/main.dig.
  3. Press Run (or single-step with the clock controls).

Other entry points: alu-32b-final.dig (ALU only), alu-display-control.dig (display bring-up). ALU sign-off: verification/README.md.


Project status

As of July 2026

Area Status Notes
Architecture 32-bit SeeFalling back to 32b
ALU PCB (07_alu) Populating First phase of assembly
Opcode ROM 512 rows (planned) Down from 1024-row budget
Register file 32 GPR × 8 banks 256 addressable registers
main.dig + control boards In progress Modular decode on bench
ALU verification Passing on 32b export verification/
ALU ASIC characterization Sky130 HD mapped 6531 µm², 512 cells, ~210 MHz est.
Peripheral PCBs In design Register, memory, PC, data bus
Firmware / software Not started README stubs only

Bring-up direction: Build peripherals and modular control boards — not a throwaway FSM that becomes Tomato anyway. The ALU PCB can be exercised through alu-display-control and simulation vectors while fab runs (lingering catch).


Documentation index

Architecture decisions

Log Topic
Web Optimization What actually ships in the paper’s 3D
ISA as a Wire Parametric datapath — ISA is a first-class input
Falling back to 32b Revert to 32-bit — current direction
The lingering catch FSM vs full control unit bring-up
Microcode Control Modularization Split decode boards
Elimination of Mode Multiplexers LUT3 pass-through into adder

Datapath deep dives

Log Topic
Multiplication and Division Priority-encoder mul/div
Load Store Pipeline Analysis Microcode bit fields, cycle timing
ALU segment display design 32-digit multiplexed display
ALU — Redesign with 74251 Carry mux routing tradeoff

Subsystem READMEs

README Content
verification/README.md ALU sign-off harness
hardware/kicad/README.md KiCad overview
07_alu board doc Dual-LUT ALU PCB — schematics, layout, pinout
hardware/digital/README.md Digital simulation
microcode/README.md Control ROM packing

Full design journal

docs/log/ — build log from discrete gates through the parametric datapath. Origin: Welcome to Tomato 32. The paper: web/README.


Conventions

Change type Workflow
Architecture / tradeoff New entry indocs/log/ — the default way decisions get made
Opcode / mnemonic Updateopcode-map.csv and microcode hex
Microcode fields Editdocs/isa/tomato.v1.csv, then python3 tools/gen_microcode_v1.py --pack-rom
Logic / timing Edit Digital.dig → export Verilog → make signoff
Physical board KiCad inhardware/kicad/boards/

License

Tomato is licensed under Solderpad Hardware License 2.1 (SHL-2.1, Apache-2.0 WITH SHL-2.1) — open hardware + RTL + scripts + docs. You may study, build, fork, and commercialize with attribution; do not strip copyright or present the dual-LUT architecture as unrelated work.

LICENSE LICENSE-APACHE NOTICE THIRD_PARTY_NOTICES.md

Architecture credit: Tomato dual-LUT bit-slice datapath — Tyrone Marhguy / Tomato project.


Author

Tyrone Marhguy — Computer Engineering '28, University of Pennsylvania

Tomato is a solo hardware architecture project: discrete-logic CPU design, KiCad PCBs, Digital simulation, and a public build log. Questions, collabs, or “why did you route it that way?” — reach out.

Email Edu EmailTwitter

Instagram Substack Paper GitHub

University of Pennsylvania Class of 2028 Verification

About

Discrete 32-bit Polymorphic Dual-LUT3 CPU; Implemeted in PCB (KiCad)

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Contributors

Languages