65 6502 SBC FPGA
← Overview
Overview / Component 03
Audio

SID-compatible sound chip $D400–$D418

A fairly complete MOS 6581 model in logic — complete enough to play original .sid files together with their 6502 player code, with only light conversion, straight on the hardware.

What it is

The active Tang Primer 20K bitstream instantiates sid6581.vhd — a VHDL recreation of the MOS 6581 (SID) from the Commodore 64. It exposes the standard 6581 register window at $D400–$D418, so SID players address the chip exactly as they would on a real C64.

The chip is more or less SID-compatible: most of the 6581 behavior is modelled, with a few analog quirks deliberately approximated (see below). On the Tang build it replaces the older four-voice synthesizer — running both at once exhausted the device's global clock networks and destabilized DDR3 PHY calibration.

Model
MOS 6581 (SID)
Voices
3 · 24-bit phase accumulators
Oscillator clock
~985 kHz PAL φ2
Filter
2-pole multimode (LP/BP/HP)

Modelled 6581 features

FeatureDetail
Oscillators3 voices, 24-bit phase accumulators, ~985 kHz PAL φ2 rate
Waveforms12-bit triangle, sawtooth, pulse (12-bit width), noise (23-bit LFSR)
Combinedmultiple waveform bits wire-ANDed (the classic 6581 approximation)
ADSRcycle-accurate: reSID rate-counter periods, linear attack, exponential decay/release divider
Filter2-pole state-variable multimode (LP/BP/HP), per-voice routing ($D417), 11-bit cutoff
Cutoff curvenon-linear "dark 6581" approximation — mid values stay low, the bass sounds rounded
Resonancedeliberately weak Q (~0.7…2), like the 6581, avoiding limiter clipping
Hard syncoscillator reset when the previous voice's MSB rises (CONTROL bit 1)
Ring modulationtriangle fold bit XORed with the previous voice's MSB (CONTROL bit 2)
Master volume$D418 low nibble; voice-3 disconnect ($D418 bit 7) honoured

The filter runs once per SID tick over a 3-step internal pipeline (one multiply per clock), so the two serial coefficient multiplies never share a single 54 MHz path; the filter states saturate to keep the SVF from blowing up.

Not yet modelled: the 6581's analog DAC non-linearity / DC "warmth" and the sample-ROM-exact combined-waveform tables (the wire-AND is an approximation). The cutoff and resonance mappings are tunable in sid6581.vhd for a brighter/darker voicing.

Playing original SID files

This is the centerpiece of the demo. tools/build_native_sid_rom.py turns a PSID/RSID file into a runnable ROM — and crucially without a lossy 50 Hz register conversion. Instead it:

  • embeds the original 6502 payload of the SID file unchanged,
  • copies it to its native load address,
  • calls the tune's init routine once,
  • and runs the play routine every 20 ms (50 Hz).

As a result every write — frequency, pulse width, control, ADSR and filter — reaches the hardware exactly as the original player produces it. Real C64 player code runs on the real 6502 core, driving a real SID recreation.

What a tune needs

  • a real play address (not an IRQ/CIA-driven RSID),
  • it loads into linear RAM $0200–$5FFF,
  • its payload fits the 12 KB ROM window at $A000,
  • single-speed PAL (50 Hz play).

Bundled examples

ROMTuneNote
soundsid.romWorld_Record_2.sidno filter/sync/ring
sound_commando.romCommando.sidleans on the low-pass filter
# wrap one tune and play it
python tools/build_native_sid_rom.py path/to/tune.sid sw/<name>.s
make -C sw upload-sound-commando      # build + upload in one step

# or wrap a whole collection at once
python tools/build_all_sid_roms.py    # builds playable ROMs + .bat files

The bulk builder also runs each tune through the bare-metal 6502 SID emulator and skips silent tunes — players that produce no sound without a CIA/VIC/KERNAL to rely on.

SID registers ($D400)

Standard 6581 layout: three voices of 7 registers each, plus global filter/volume registers:

AddressRegister
$D400–$D406Voice 1: freq, pulse width, control, ADSR
$D407–$D40DVoice 2 (same layout)
$D40E–$D414Voice 3 (same layout)
$D415–$D416Filter cutoff (11-bit)
$D417Resonance & per-voice filter routing
$D418Filter mode & master volume

Hardware output

The signed 16-bit sample is shifted out through the I²S serializer in pt8211_dac.vhd to the dock's PT8211 (TM8211) DAC (~47 kHz). The power-amp enable pin (PA_EN, R16) is held high, otherwise the headphone amplifier stays silent.

Alternative synthesizers

The repository keeps two other register-compatible sound sources for other targets:

  • Large 4-voice chip (sound_chip4.vhd) — 4 voices, five waveforms (sine, square, sawtooth, triangle, noise), full ADSR, note duration and a mixer; the full C-emulator model.
  • Bring-up single voice (sound_voice.vhd) — one voice, square + noise, no envelope; the minimal variant.

Verification

GHDL testbenches confirm the SID core produces audio (filter off, backward-compatible level), the filter stays bounded and a low cutoff attenuates, and that combined waveforms, ring modulation and hard sync are wired, bounded and non-silent.