The 4001 is the canonical ROM partner of the 4004/4040. 16-pin DIP, 256 bytes of mask-programmed ROM accessed over the 4-bit multiplexed nibble bus, plus 4 I/O port lines (WRR/RDR — not yet wired). Implementation: ~140 LOC clean-room from MCS-4 manual §V. The chip has its own timer at 1351 ns (matching the 4004's clock period), with a state machine that walks the 8-phase frame in lockstep with the 4004: S_IDLE → (SYNC↑) → S_SAMPLE_LOW (A1 nibble) → S_SAMPLE_MID (A2) → S_SAMPLE_HIGH (A3, addr complete) → S_DRIVE_HI (M1, drive opcode high nibble) → S_DRIVE_LO (M2, drive low nibble) → S_POST (X1..X3 idle) → wait for next SYNC. Timing trick: the 4001 must be added to the board BEFORE the 4004 so its tickTimers fires first per advanceNanos. The 4001 then runs one frame "behind" the 4004 — sampling what the 4004 drove last frame and driving what the 4004 will read this frame. Documented in the chip's source and the master plan. Integration test (`test_buses/4001-rom.test.js`) wires both chips on the same board and verifies the 4004 actually fetches and executes opcodes from the 4001 (PC walks 0, 1, 2 with the embedded NOP image). This is the first end-to-end test of the 4-bit multiplexed bus working between two real WASM chips on the canvas, not just JS helpers — proving the bus model scales. Deferred for the next Phase D iteration: 4002 RAM (similar shape + SRC chip-select latching), 4004 SRC/WRM/RDM wiring to exchange data with the 4002, and the Busicom 141-PF integration once both ROM and RAM chips are real. Tests: total test_intel 98 → 99 passing, 0 failed, 11 todo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| 4001-rom.c | ||
| 4001-rom.test.js | ||
| 8251-usart.c | ||
| 8251-usart.test.js | ||
| 8255-ppi.c | ||
| 8255-ppi.test.js | ||
| README.md | ||
| latch-8282.c | ||
| latch-8282.test.js | ||
| ram-64k.c | ||
| ram-64k.test.js | ||
| rom-1m.c | ||
| rom-1m.test.js | ||
| rom-32k.c | ||
| rom-32k.test.js | ||
README.md
test_buses — External memory chips for retro CPUs
Real PCBs from 1976 don't put RAM/ROM inside the CPU package. Faithful emulation requires the same separation: the CPU drives address pins, chip-select, and RD̅/WR̅; separate memory chips on the canvas listen.
These chips are reusable across all five Intel/Z80 CPU projects.
Chips planned
| Chip | Pins | Source file | Status |
|---|---|---|---|
rom-32k |
27 | rom-32k.c |
✅ Implemented — 6/6 tests passing |
ram-64k |
29 | ram-64k.c |
✅ Implemented — 7/7 tests passing |
latch-8282 |
20 | latch-8282.c |
📋 Spec only (only needed for 8086) |
Why we still test these C chips even though tests use installFakeRom
The BoardHarness.installFakeRom() and installFakeRam() helpers
emulate memory in JS for CPU unit tests. They are fast, flexible,
and don't require a per-test compile.
The real rom-32k.c / ram-64k.c chips are needed because:
- End users wire them on the canvas. A user dropping a Z80 into velxio expects a draggable ROM and RAM next to it. The C chips ARE that user-visible primitive.
- Integration tests need the real chip. Once a CPU is verified
in unit tests with a fake ROM, an integration test runs the same
CPU with the real
rom-32k.wasm, proving the on-canvas demo will work.
So the test split is:
*.unit.test.js→ usesinstallFakeRom/installFakeRam, tests instruction semantics and bus protocol*.integration.test.js→ uses real compiled bus chips, proves the user-visible demo works
For now we have rom-32k.test.js and ram-64k.test.js covering the
C chip behavior in isolation — pin contract + read/write protocol
with hand-crafted bus stimuli.
ROM image loading — the SDK constraint
The velxio chip SDK does not (yet) support arbitrary-length blob
attributes. vx_attr_register only takes a double. So a 32 KB ROM
image cannot be passed in via .chip.json properties.
Workaround for now: the C source contains
const uint8_t rom_image[32768] = { /* baked-in */ };. Each "ROM
variant" is a separate compiled chip. For shipping examples we will
generate one variant per demo program; for tests we use a small image
embedded directly in rom-32k.c.
A follow-up SDK proposal — adding vx_attr_register_blob() or an
"asset" import mechanism — is tracked in
../autosearch/05_open_questions.md.
ram-64k notes
The RAM chip is simpler — no embedded image, just a static uint8_t mem[65536] zero-initialized at chip_setup. No SDK extension required.