DMG-CPU Research

APU suite - status (issue #398)

Snapshot of HDL/soc/icarus/apu. The suite drives the real APU netlist (apu_merged.v, HDL/soc/apu.v with the a/d bus aliases merged) inside the SoC context: real ClkGen + MMIO (mmio_weakbus) + Arbiter + Ser + behavioral WaveRAM, with a CPU bus master (same conventions as ../soc, issue #396).

Status per test

tb_apu_regs - PASS (35 checks)

Register file map of the real APU (measured; wiki/soc/apu.md):

Addr Register read-back semantics (measured)
$FF10 NR10 0x80 \| (v & 0x7F) (sweep period echo, bit7 hard-1)
$FF11 NR11 0x3F \| (v & 0xC0) (duty echo, length bits hard-1)
$FF12 NR12 v (8-bit envelope echo)
$FF13 NR13 no read-back (0xFF) - write-only (feeds the divider)
$FF14 NR14 0xBF \| (v & 0x40) (bit6 length-enable echo)
$FF16-$FF19 NR21-NR24 same pattern as NR11-NR14 (ch2)
$FF1A NR30 0x7F \| (v & 0x80) (DAC-enable echo, rest hard-1)
$FF1C NR32 0x9F \| (v & 0x60) (volume echo, rest hard-1)
$FF1E NR34 0xBF \| (v & 0x40)
$FF20-$FF23 NR41-NR44 NR41 no read-back; NR42/NR43 echo; NR44 0xBF\|(v&0x40)
$FF24 NR50 v (8-bit echo)
$FF25 NR51 v (8-bit echo)
$FF26 NR52 0x70 \| (power<<7) \| (ch-active bits 3:0); 0xF0 after
power-on, 0x70 powered off. Power-off write resets the channel registers.
$FF27-$FF2F - unmapped (0xFF, no read driver)
$FF30-$FF3F WaveRAM CPU write/read window decoded by the APU itself
(n_wave_wr/n_wave_rd + wave_a = a[3:0] while not playing; data on d
re-driven from wave_rd by the notif1 stage g1255..g1262)

Write decode map (verified): w695 = $FF30-$FF3F window; n_wave_wr = ~(soc_wr & w695); n_wave_rd = ~(ch3_active ? : (soc_rd & w695)).

tb_apu_ch1 + check_ch1.py - PASS

Channel 1 verified end-to-end on the real netlist:

tb_apu_ch2 + check_ch2.py - PASS

The same check set for channel 2 (no sweep). Only possible after the w548 bus-model fix (see below) - previously the divider preset captured x from write-bus contention and the channel never played.

tb_apu_ch3 + check_ch3.py - PASS

Channel 3 (wave) with a known wave-RAM image:

tb_apu_ch4 + check_ch4.py - PASS

Channel 4 (noise): with NR42 vol F the output toggles at level F while running; the toggle rate drops as the NR43 divisor r grows (measured: 15-bit r0/r7 ~ 50x over 500us windows; the exact divider ratio vs the pan-docs formula is an open cross-check - the LFSR output-run statistics depend on the polynomial, so rate ratios are measured, not assumed).

Open research items (author checklist)

Tooling notes