Context
I am pushing to design the remaining boards.
I had assumed that the most complicated one to design was the main board — the ALU — which is done and routed (07_alu). The next thing is everything else: register file, memory, PC/stack, data bus, shift/mul-div. The ALU was the deep combinational problem; what is left is mostly 32-bit plumbing — mux trees, decode fanout, and connectors that do not fight the floor plan.
That is the plan from last week: while the ALU fab runs, design slices that ship in the final machine instead of a throwaway FSM.
Starting with multiplexers
The first slice I am tackling is the multiplexers on the data path — writeback mux, bus arbitration, and the glue that ties ALU, memory, and register ports onto one 32-bit highway.
A naïve 32-bit mux bank (one huge 74257 tree per source, every bit routed independently) costs hundreds of millimetres of trace and real estate. The approach for Tomato:
- Bus drivers (
74AC125/ tri-state family) on each contributor — ALU result, memory read, PC+1, shift/mul, etc. - Matched decode enables from the modular control boards — only one driver active per phase, same idea as the ALU display scan chain (one hot index, shared bus).
- KiCad target: 06_data_bus —
wb_mux.kicad_sch,bus_arbitration.kicad_sch, tied to Digitalwb_mux.digandbus-arbitration.dig.
Digital already has the behavior; the board work is making the 32-bit fanout physically tolerable.
Contention and timing
Contention is a real issue on a shared tri-state bus — two drivers fighting the same line is not theoretical.
But I am not running at GHz. At breadboard / bring-up clock rates, the window where two enables overlap badly is small. From earlier calculations, the chance of meaningful contention during switching is ~1%, or more accurately under 5% of transitions — acceptable for lab bring-up if decode is one-hot and enables are never deliberately stacked.
Heat from brief overlap at these speeds should be ok. Production hygiene still matters: one active driver per bus, decode timed to the sequencer phases documented in Load Store Pipeline Analysis.
Board queue (after ALU)
| Board | KiCad | Digital anchor | Notes |
|---|---|---|---|
| 06 data bus | 06_data_bus/ | wb_mux, bus-arbitration | Current focus — mux + drivers |
| 04 register | 04_register/ | register.dig, ir.dig | 3R1W, 32 GPR × 8 banks |
| 05 PC / SP | 05_program_counter/ | program-counter.dig, sp.dig | Fetch address source |
| 03 memory | 03_memory/ | memory.dig, byte-lane-decoder | Load/store path |
| 02 shift / mul-div | 02_shift_encoder/ | ||
| 08 display / FSM | 08_display/, 08_alu_fsm | alu-display-control | Bench debug |
Control ROM boards (microcode modularization) ride with their datapath slices — not a separate queue item.
Open questions
- One consolidated 06_data_bus PCB vs split wb_mux and arbitration across connectors?
- Which
74xxdriver family on the 32-bit backplane —AC125vsHC125vs registered enables for cleaner turn-off? - Order after mux: register file (loopback tests) vs memory (load/store integration)?
- Re-run contention estimate at target max clock once sequencer timing is nailed down.
Lean recommendation (today)
Finish the mux + driver plan on 06_data_bus in KiCad first — it unblocks every other board that needs to read or write the shared 32-bit word. Keep enables decode-driven and one-hot; do not sprawl a discrete 32-bit mux forest across the whole CPU footprint.
The ALU was the hard part. The rest is wiring Tomato's existing simulation into boards that fit the bench.