MAD-65
Contents

MAD-65 — Bill of Materials#

Per-board IC list for the three MAD-65 boards — PCB1 (CPU board), PCB2 (GPU board) and PCB3 (ping-pong shared-RAM board) — so each board can be sourced independently.

Scope: ICs only — active silicon (CPU, RAM/ROM/VRAM, sound chips, GALs/CPLD, 74xx logic). Passives, crystals, connectors, the reset supervisor and the analog audio/VGA stage are not listed here; see MAD65_architecture.md §15 and MAD65_video_circuit.md §12–13 for those.

Counting rule: strict per-board — every part is counted only on the board it physically sits on.

Source of truth: the chip instances in ../rtl/pcb1/pcb1.sv, ../rtl/pcb2/pcb2.sv and ../rtl/pcb3/pcb3.sv (the structural RTL is "chip instances + wires only"), cross-checked against the architecture doc §15. There are no KiCad / netlist / schematic files in the repo — the RTL is authoritative.


PCB1 — CPU board#

Part Qty Instance(s) Function
WDC W65C02S 1 u_cpu CPU1 — main / game logic, 14.318 MHz
ATF1508AS-10JU84 CPLD 1 u_cpld_cpu1 v11: the whole board's decode + glue — address decode, R/W-gated glue (memory /OE, upper-RAM /OE, joystick /OE), SHADOW_MODE register, SHADOW_MODE-gated EPROM /CE, 3-wait-state RDY generator, cartridge bank register, ÷4 audio clock, LED_STRB, and v16 the PHI2-qualified /WE (~47/64 pins, ~35/128 macrocells)
CY7C199-15PC (32K×8 SRAM) 2 u_ram_lo, u_ram_hi 64 KB system RAM (lower + upper). v10: u_ram_hi doubles as the shadow code-RAM — its $C000–$FFFF cells hold the OS image and serve it once SHADOW_MODE is set
27C256 / AT28C256 (32K×8 ROM) 1 u_rom_cpu1 16 KB system ROM ($C000–$FFFF)
SN76489 2 u_snd1, u_snd2 PSG sound generators (CLK = the CPLD's 3.5795 MHz ÷4 output)
YM2413 (OPLL) 1 u_ym FM sound generator (XIN = the same ÷4 output; XOUT open)
74HC244 2 u_joy1, u_joy2 Joystick port buffers (one per DE-9)

PCB1 IC total: 10 packages.

v11 change — one CPLD replaces five packages. PCB1 goes 14 → 10 ICs:

-2 ATF22V10 (u_gal, u_ctrl) -1 74HC273 (cartridge bank register) -2 74HC74 (CART_EN half + the audio ÷4 divider) +1 ATF1508AS-10JU84 (u_cpld_cpu1)

Why: after v10 both GALs were 10/10 macrocells and the decoder was 12/12 input pins, leaving PCB1 with no room for any future decode change. The ATF1508AS is the part already used ×2 on PCB2 and ×1 on PCB3, so it adds no new part number — and it leaves ~14 spare I/O and ~90 spare macrocells.

The u_ctrl speed-grade warning is gone. It existed because RDY was combinational across two GALs in series on the cartridge path (30 ns tADS + 15 + 15 = 60 ns of a 69.8 ns cycle, leaving only ~10 ns for the W65C02S RDY setup). Inside one CPLD the whole path is 30 + 10 = 40 ns, ~30 ns of margin, with no cross-chip feedback anywhere.

PCB1 now needs a JTAG header and a PLCC84 socket. The ATF1508AS is a JTAG part (ATMISP + USB-Blaster), not a TL866/Xgpro DIP part. PCB2 and PCB3 already require this, so it is no new tooling — but it is new to PCB1's layout.

v10 change — CPU1 shadow code-RAM costs no IC. Unlike PCB2 (which needed a 6th CY7C199 for its shadow), u_ram_hi already spans $8000–$FFFF via /CE = A15 and already latched writes at $C000–$FFFF; those cells were simply never read back, because RAM_RD_REGION excluded the ROM region. v10 just stops gating the RAM's /OE there once SHADOW_MODE is set. The EPROM (u_rom_cpu1) stays fitted — it is still the boot source.

Cartridge ROM (u_rom_cart, up to 1 MB banked into an 8 KB window at $8000–$9FFF) is an external plug-in cartridge card, not an on-board IC — it is intentionally excluded from the board count.

LED diagnostic module (optional, external): LED_STRB now comes out of the CPLD, so the module's 74HC133 (13-input NAND) is no longer needed — it is down to a single 74HC374 + LEDs. It was never counted in the board totals above. PCB1 only: PCB2's equivalent is populated on the board (v15, a 74HC574) and is counted there.

Shared clock buffer: the 14.318 MHz CPU crystal is shared with PCB2 and buffered through a 74HC04; the docs do not pin down which board that buffer sits on, so it is noted here but not assigned to a board count.


PCB2 — GPU board#

Part Qty Instance(s) Function
WDC W65C02S 1 u_cpu CPU2 — GPU / graphics processor
ATF1508AS-10JU84 CPLD 3 u_cpld_v, u_cpld_c, u_cpld_x Video engine, split across three chips: cpld_video (clk_pix) = H/V counters, sync/blank, VRAM address-gen, SEL, pixel path; cpld_ctrl (clk_14318) = the GPU address decoder (v13, was the ATF22V10), VIDEO_REG, GPU decode, VRAM /OE//WE//CE steering, GPU-data 245 control, the VSYNC→PHI2 synchroniser that drives vsync_cpu_n (v14) LED_STRB (v15) and the PHI2-qualified /WE (v16, ≈52/64 I/O); cpld_xbar (v12) = the VRAM address crossbar (CPU2 addr + cpld_video's video_addr → both VRAM addrs), lifted out of cpld_video to give it I/O margin
27C256 / AT28C256 (32K×8 ROM) 1 u_rom_gpu 16 KB GPU boot ROM ($C000–$FFFF, read in boot mode)
CY7C199-15PC (32K×8 SRAM) 6 u_ram_lo, u_shadow, u_img_a, u_bg_a, u_img_b, u_bg_b 1× system RAM + 1× shadow code-RAM (low 16 KB at $C000–$FFFF) + 4× VRAM (128 KB, double-buffered image + background)
74HC245 2 u_245_a, u_245_b VRAM data transceivers (CPU2 bus ↔ buffer)
74HC166 2 u_166_a, u_166_b Pixel serialisers, one per VRAM buffer (cpld_video picks front buffer by SEL)
74HC574 1 u_led_574 v15: LED_GPU_REG ($BFC0–$BFDF, write-only) — 8 diagnostic LEDs, clocked by LED_STRB from cpld_ctrl. A '574 rather than a '374 for its straight-through pinout (D one side, Q the other), which routes cleanly to the LED array. Plus 8× LED + 8× 330 Ω (not ICs)

PCB2 IC total: 16 packages.

v15 change: the GPU diagnostic LED register is populated on this board — one 74HC574 clocked by LED_STRB, which cpld_ctrl now emits (≈50 → ≈51/64 I/O). The 74HC133 the original design called for is retired unbuilt: it existed only because the pre-v13 ATF22V10 had no macrocell to spare, and cpld_ctrl already had a15..a5 and the BF_PAGE term after the v13 fold. gpu_os has driven LED_GPU_REG since it was written (four boot POST stages plus the GPU_LED opcode) — until now nothing latched those writes. 15 → 16 ICs.

v13 change: the GPU address decoder — the last ATF22V10 GAL (u_gal) — folded into cpld_ctrl. The CPU2 address bus (a15..a5) now enters that chip, which emits the memory/PCB3 chip selects directly; cpld_ctrl goes 37 → ~48/64. This retires the last GAL and the final dual-source .pld — ATF1508AS-10JU84 is now the system's only programmable part. PCB2 16 → 15 ICs. Mirrors the v11 PCB1 GAL→CPLD consolidation.

v12 change: the VRAM address crossbar was lifted out of cpld_video into its own ATF1508AS-10JU84 (u_cpld_x / cpld_xbar). cpld_video had reached ~59/60 usable I/O — the 42-pin crossbar (gpu_addr in, a_addr+b_addr out) alone was two-thirds of its budget. Moving it drops cpld_video to ~33/64 and puts the crossbar at ~57/64, at the cost of one package and one new inter-chip bus (video_addr[13:0]). The alternative — reverting to the discrete 8× 74HC157 crossbar — was rejected as unroutable.

v10 change: cpld_ctrl's wait-state generator widened from one wait state to three per boot-ROM read (~239 ns of access time — ample for any EPROM grade). Free, because cs_rom_n is SHADOW_MODE-gated, so ROM is only read during the boot copy.

v9 change: added the shadow code-RAM (u_shadow, a 6th CY7C199) at $C000–$FFFF so GPU code runs from fast SRAM at full 14.318 MHz. VIDEO_REG bit 3 (SHADOW_MODE) picks the overlay: boot = read ROM / write shadow (GPU copies ROM→shadow), run = read shadow / write VRAM-background. cpld_ctrl also inserts wait states per (slow-ROM) read; the decoder GAL gains a shadow_mode input and a cs_shadow_n output. Fast-SRAM part note: the shadow (and every other single-cycle read) must beat the ~30 ns read window at 14.318 MHz, which is why the system SRAM is the 15 ns CY7C199-15PC and not a 55 ns part — see MAD65_architecture.md memory-timing notes.

v8 change: the ping-pong shared RAM moved to PCB3 — PCB2 lost its 2× 2 KB SRAM, 6× 74HC157 and 4× ping-pong 74HC245 (26 → 14 ICs). cpld_ctrl sheds SWAP_SEL/IRQ/ping-pong-enables; the decoder GAL now emits a single cs_sram_gpu_n. The analog VGA output stage (75 Ω / 270 Ω resistor network, no DAC chip) stays on PCB2 (outside the ICs-only scope here).


PCB3 — ping-pong shared-RAM board (v14)#

Part Qty Instance(s) Function
ATF1508AS-10JU84 CPLD 1 u_cpld_ppr Ping-pong engine: SWAP_SEL (edge-detected from PCB2's /IRQ), the address//WE crossbar (both CPU addresses in → both SRAM addresses out), per-chip /CE, 4× 245 enables (≈59/64 I/O)
2 KB×8 async SRAM (HM6116-class, DIP-24) 2 u_sram_a, u_sram_b Ping-pong shared RAM ($7800–$7FFF), swapped each VSYNC
74HC245 4 u_245_ca, u_245_ga, u_245_cb, u_245_gb Data transceivers, per master (CPU1 / GPU) per chip

PCB3 IC total: 7 packages.

Folding the 6× 74HC157 ping-pong crossbar into cpld_ppr (the CPLD had to exist for the swap logic anyway) is why PCB3 is 7 ICs, not 13. PCB1 and PCB2 each cable into their own PCB3 port; clk_cpu, rst_n and the frame /IRQ are shared.

v14 change: the VSYNC→CPU-clock synchroniser left cpld_ppr for PCB2's cpld_ctrl, the board that generates VSYNC. PCB3 now takes the already-synchronous /IRQ and edge-detects it for SWAP_SEL, so raw VSYNC is no longer a backplane signal and PCB2 can raise its own frame interrupt with no other board present. cpld_ppr 60 → ≈59/64 I/O, cpld_ctrl 48 → ≈50/64. No IC count changes on any board.


System roll-up#

Part PCB1 PCB2 PCB3 Total
WDC W65C02S 1 1 2
ATF1508AS-10JU84 CPLD 1 3 1 5
CY7C199-15PC 2 6 8
2 KB×8 SRAM 2 2
27C256 / AT28C256 1 1 2
SN76489 2 2
YM2413 1 1
74HC245 2 4 6
74HC244 2 2
74HC166 2 2
74HC574 1 1
Per-board IC total 10 16 7 33

v13: the last ATF22V10 (PCB2's GPU address decoder) folded into cpld_ctrl (33 → 32 ICs system-wide). No GAL remains — ATF1508AS-10JU84 is now the system's only programmable part, in five places. The ATF22V10 line disappears from the BOM entirely.

v12: the PCB2 video engine gained a third ATF1508AS (cpld_xbar) holding just the VRAM address crossbar, to relieve cpld_video's I/O pressure (32 → 33 ICs system-wide).

v11: PCB1's 2× ATF22V10 + 74HC273 + 2× 74HC74 collapsed into a single ATF1508AS (36 → 32 ICs system-wide). The ATF1508AS-10JU84 became the system's main programmable-logic part; the 74HC273 and 74HC74 lines disappear from the BOM entirely. (One ATF22V10 survived on PCB2 until v13.)