DINO

hardware / status: active

D.I.N.O., Discrete Integrated NISC Operator, is an 8-bit CPU I built from 77 discrete 74-series chips on breadboards, designed in KiCad. Three AT28C64B EEPROMs hold a 24-bit microcode word; program ROM is an AT28C256, RAM a 32K MCM60256. It started as a 25-instruction machine that could add two numbers and has grown, phase by phase, into a 174-instruction ISA with a 16-bit stack pointer, CALL/RET, execute-from-RAM, a 16K memory-mapped I/O window with eight card slots, a 16550 serial card, and a ROM monitor that loads hex over the wire and runs it. Most of the hard faults turned out to be analog stuff, not logic. The breadboard is at the end of what it can do at 1.024 MHz and the next phase is a PCB, power first.

The machine, top-down, 2026-09-10. Microcode and T-state decode on the left, the program counter across the top, RAM, program ROM and the MDR board in the centre, registers and the ALU on the right, the LED and DIP switch board at the far right.
The machine, top-down, 2026-09-10. Microcode and T-state decode on the left, the program counter across the top, RAM, program ROM and the MDR board in the centre, registers and the ALU on the right, the LED and DIP switch board at the far right.

Current state

As of 2026-09-10: The machine is complete and runs the whole ISA from ROM at 1.024 MHz. PROG_isa reads 0xB4 (147 subtests pass) and PROG_isasoak read 0x00 on 50 consecutive runs, 470,400 subtest executions, zero miscompares, after GND and VCC were starred to every board on 2026-09-01.

Phases B through G are on silicon: stack (B), CALL/RET (C), execute-from-RAM (D), the 16K I/O window at 0x4000-0x7FFF with the DIP switch as card zero (E), the 174-instruction ISA (F), the 16550 serial card at 9600 8N1 (G), and the ROM monitor with D/W/O/L/G commands (G_0). All 32K of RAM, 0x8000-0xFFFF, is proven for data and for fetch.

RAM-resident programs run. The monitor’s L command loads hex over serial with dinoload.py pacing one character per echo, and G runs it. The 2233-byte bigxfer transfer has gone in and streamed itself back clean several times, sometimes back to back; what stops it is mechanical, a table bump or a wire out of line, and I think every error on this breadboard has been noise. The one pinned timing fault is OUT immediately before a fetch from RAM: it halts at 1.024 MHz and returns at 500 kHz. A microcode settle row was burned and did not fix it. It’s setup margin lost to breadboard bus capacitance.

Decision 2026-09-08: the breadboard phase is over. Next is one 2-layer mainboard with the phase E slots as its only connectors, and power gets designed first. The machine draws 1.25 A to 1.34 A at 5 V on the bench supply ammeter. The supply itself is an open item, old ATX unit or PicoPSU, not dug into yet.

Architecture

Horizontal microcode, no instruction pipeline. Each opcode is a table of rows in a 24-bit control word held in three AT28C64B EEPROMs (U9, U15, U23); T0 is the universal fetch and a 74LS163 T-counter steps the rows until END. Every state-changing load is clock-qualified and commits on CLK low; bus output enables are ungated. The machine is fully static, so the clock can stop.

Two buses. MDR0-7 is the internal bus (ROM, RAM, registers A/B/C, stack pointer halves, PC halves all drive it through ‘245s). W is the ALU and destination side. A ‘245 bridge (U25) joins them whenever any source is active, so a destination can latch from either side: MAR and IR latch from W, registers from MDR. The ALU is a pair of 74F382s with ripple carry; all four flags latch in a ‘273 and update only when the ALU is the source.

Memory map: ROM at 0x0000-0x3FFF, the I/O window at 0x4000-0x7FFF decoded into eight 2K card slots on M11-M13, RAM at 0x8000-0xFFFF. Card zero is the DIP switch at 0x4000. Card one is the serial card at 0x4800. Cards see the address bus as an input only; there is no DMA by construction.

ISA: 174 instructions. Immediate and register ALU ops, absolute and memory-indirect loads and stores (LDAM/STAM parks a pointer through C and MDR), conditional branches on C and Z, PUSH/POP, CALL/RET, OUT to an 8-LED latch that latches MDR. CALL pushes PC+1 and RET steps over the two operand bytes with trailing PC_UP states. The high nibble of an opcode is its family so a byte is hand-disassemblable at the bench.

Tooling is all generated from the KiCad schematics: the netlist oracle extracts gate equations, kicad_contracts.py emits landing and change lists for the copper, microcode_gen.py emits the ROM images with pinned CRCs, and a Python oracle in progrom_gen.py interprets the real microcode rows to compute what OB should read for every coverage image.

The I/O corner. The last two things to go onto the breadboard: the DIP switch as card zero at 0x4000 and the serial card, a PC16550D with its 3.6864 MHz can and the FTDI breakout, at 0x4800. Both are just memory to the CPU. The stack pointer '169s (U63-U68) sit below them.
The I/O corner. The last two things to go onto the breadboard: the DIP switch as card zero at 0x4000 and the serial card, a PC16550D with its 3.6864 MHz can and the FTDI breakout, at 0x4800. Both are just memory to the CPU. The stack pointer ‘169s (U63-U68) sit below them.

The DIP switch and the serial card are both just memory. Adding a peripheral is a ‘138 decoding its 2K slot on M11-M13 plus whatever chip does the work; the core doesn’t change. That part’s easy now. The breadboard is what’s in the way.

Hardware

77 ICs on the core, ten breadboards, plus a 3-IC serial card. Netlist count 2026-09-08:

17  74LS245      11  74LS373     9  74LS138
 8  74LS02        4  74LS169     4  74LS193      3  74LS08
 3  AT28C64B      2  74LS163     2  7400         2  74LS157
 2  74F382N       2  74LS244N    2  74LS00       1  74LS74
 1  74LS14        1  74LS273     1  74LS32       1  74LS04
 1  MCM60256AP    1  AT28C256    1  PC16550D
 8  LED (330R)    2  oscillators (4 MHz can, 3.6864 MHz can)

Single +5 V rail. The core clock is the 4 MHz can divided down to 1.024 MHz; a 500 kHz option exists for timing discrimination. The serial card runs the 16550 off the 3.6864 MHz can and an FTDI TTL cable.

Analog fixes that are now part of the design: a 100R series resistor (R2) in the stack pointer board’s CLK branch, without which the ‘169s double-clock; a 10uF reset capacitor (C1) after a 1uF was found in the socket and gave a 0.8 ms runt instead of a power-on reset; GND and VCC starred to every board after the ground pins measured 142 mV to 460 mV above the supply terminal; and the RESET wire pulled out of the bundle with CLK and the buses, where it picked up 1.5 V runts.

Instruments: DSLogic LA (20 MHz max), Siglent SDS1204X-E, DMM, TL866 programmer. The ATmega2560 test rig and the FPGA twin are both retired.

Where it started. Dino v0.0.1, schematic dated 2025-06-15: an 8-bit logic sequencer, a 555 timer and a binary counter stepping an EEPROM into an LED bus. One breadboard and a logic analyser.
Where it started. Dino v0.0.1, schematic dated 2025-06-15: an 8-bit logic sequencer, a 555 timer and a binary counter stepping an EEPROM into an LED bus. One breadboard and a logic analyser.

Gateware and firmware

Decisions

Open problems

Build logs

Dated working notes for this project, newest first. Corrections land as new entries.