Ant64 Memory Architecture
Overview
The Ant64 family's memory architecture centres on the FireStorm FPGA, which hosts both the main CPU (a 64-bit RISC-V core) and the entire chipset (graphics, audio, blitter, copper, raycaster). Because CPU and chipset live in the same silicon, they share the same memory ports — but the architecture uses multiple physically-separate memory banks so that critical bandwidth consumers (instruction fetch, blitter, audio DSP, scratchpad-resident data) don't contend for the same bus.
There is no separate main-CPU DRAM — the FireStorm Execution Engine runs from the FPGA's DDR3 and the wide-mode SRAM bank, sharing the same physical buses with the chipset blocks but with bus arbiters tuned for predictable real-time behaviour.
On-Chip BSRAM
GoWin GW5AST-138: 340 BSRAM blocks × 18 Kbits = ~765KB total.
Dual-port, up to 380 MHz, 72-bit data width — ~3.4 GB/s per block at full speed. Used for:
- Sprite line buffers, tilemap data, clip tables, palette RAM
- CRT simulation LUTs, texture cache hot set
- Copper lists, command-list buffers
- FireStorm-specific structures: Xstack BSRAM stacks (U/S/M), Xctx hardware contexts, scratchpad for hot data structures, FireStorm prefetch buffers (no I-cache)
Hard RISC-V Coprocessor Local Memory
The hard RISC-V coprocessor embedded in the GW5AST-138 silicon (see Hard RISC-V Coprocessor) has its own memory hierarchy inside the silicon, separate from BSRAM and from FireStorm's memory subsystem:
Tightly-coupled local memory (private to the hard core):
- 64 KB ILM (Instruction Local Memory) — holds the hard-core debug / monitor firmware's hot path (interrupt handlers, debug-packet assembly, ring-buffer code); single-cycle fetch, deterministic latency
- 64 KB DLM (Data Local Memory) — working state (debug ring buffers, performance-counter accumulators, accumulated diagnostics); single-cycle access
ILM and DLM are private to the hard core — they do not appear in FireStorm's address space, and FireStorm cannot read or write them directly.
Cached wider memory access (also private):
- 32 KB I-cache + 32 KB D-cache with LRU replacement
- 256 MB instruction address space
- 2 GB data address space (32-bit address bus)
The cache hierarchy lets the hard core run firmware too large to fit in ILM and process diagnostic datasets too large to fit in DLM.
XIP from SPI flash:
The hard core supports XIP (eXecute In Place) from an attached SPI flash through its memory-mapped interface. This is the realistic home for a full firmware image: the FreeRTOS kernel + monitoring / debug / telemetry tasks live in cheap, dense SPI flash, are fetched on demand via the SPI interface, and the 32 KB I-cache absorbs SPI access latency to keep execution fluent. ILM stays available for the hottest code paths (ISRs, critical sections) and DLM for FreeRTOS task control blocks and working state.
This is what makes the hard core practical to use: it's not a fixed-firmware monitor that has to fit in 64 KB ILM, it's a real RTOS-hosted firmware target with caching, MMU, PMP, and proper task structure.
Shared DDR3 (configurable):
The GW5AST-138 silicon supports an optional Shared DDR3: Logic R/W Mode that lets both the hard core ("MCU side") and the FPGA fabric ("FireStorm side") read/write DDR3 concurrently through the same arbiter. The hard core's 32-bit data address space maps cleanly onto the low 4 GB of the DDR3.
When this option is enabled in the bitstream configuration:
- The hard core can inspect FireStorm's DDR3-resident state in place — sample buffers, voice state tables, large diagnostic snapshots — without round-tripping through QSPI
- FireStorm and the hard core can share regions by convention — FireStorm writes a debug buffer, the hard core reads and analyses it (or vice versa) — no IPC protocol needed beyond the agreed-on memory layout
- The hard core's firmware can grow beyond 64 KB ILM by being placed in DDR3 and cached through its L1s
The option is disabled by default and must be explicitly turned on in the GoWin IP configurator. When disabled, DDR3 belongs exclusively to FireStorm and the hard core is confined to ILM/DLM + cached BSRAM/flash. Shared mode introduces some bus contention with FireStorm's DDR3 accesses, but the hard core's bandwidth use is light (occasional reads for inspection), so the impact is minimal in practice.
Diagnostic data still flows primarily outward — the hard core observes FireStorm's chipset registers from inside the FPGA, accumulates state in DLM, and writes debug packets out over the dedicated internal channel to DeMon. Shared DDR3 is an additional capability for richer inspection, not a replacement for that primary path.
Wide-Mode SRAM — 1M × 36-bit
A single bank of pipeline-synchronous fast SRAM, mapped as 1M × 36-bit (~4.5MB) on its own dedicated bus, for FireStorm wide-mode code and data:
| Parameter | Total |
|---|---|
| Organisation | 1M × 36-bit |
| Capacity | ~4.5MB |
| Clock speed | 200 MHz |
| Bandwidth | ~900 MB/s |
| Access mode | Pipeline — 1-cycle latency, burst |
| Wait states | None |
Pipeline mode: address on cycle N, data valid on cycle N+1. Burst mode: sequential addresses stream at full 200 MHz clock rate after the initial pipeline fill — ideal for sequential instruction streaming. No wait states, no refresh, no page boundaries, no bus turnaround penalty.
The 36-bit word width is matched to FireStorm's wide-mode instruction format exactly. 32 bits encode a standard RV64 instruction; the extra 4-bit nibble provides the register-extension prefix that doubles the CPU's architectural register file from 32 to 64 GPRs and 32 to 64 FPRs (see FireStorm EE §7). On a data access those same four bits per word are instead per-byte watch bits — the bank is no longer code-only.
This bus is exclusively FireStorm's. No other device shares it, so FireStorm fetches wide-mode code — and reaches any wide-mode data placed here — at full burst bandwidth regardless of what the blitter, audio DSP, or any other subsystem is doing.
The 36-bit wide-mode SRAM bank backs wide mode and its wide-mode-only features (Xcond predication, wide register file, indexed loads).
FireStorm DDR3
The main DDR3 bank is shared between the FireStorm EE and the chipset blocks (blitter, audio DSP). Every model uses the same 72-bit SODIMM slot at the same speed grade — a 1Rx8 module, 2.25 GB on the Ant64, 4.5 GB on the Ant64C, and 1.125 GB on the entry Ant64S (each user-upgradable to 4.5 GB):
- DDR3-800 (800 MT/s, 400 MHz I/O clock with double-data-rate transfer — the maximum supported rate)
| Model | Capacity | Bus width | Peak bandwidth | Sustained |
|---|---|---|---|---|
| Ant64S | 1.125 GB (→4.5 GB) | 72-bit | 7.2 GB/s | ~4.5–5.6 GB/s |
| Ant64 | 2.25 GB (→4.5 GB) | 72-bit | 7.2 GB/s | ~4.5–5.6 GB/s |
| Ant64C | 4.5 GB | 72-bit | 7.2 GB/s | ~4.5–5.6 GB/s |
DDR3 is a 72-bit bus at 7.2 GB/s peak — wide enough to carry FireStorm's wide-mode instructions directly (two 36-bit wide instructions per 72-bit word), so wide-mode code executes from DDR3 as well as from the 36-bit SRAM bank. Every model uses the same 72-bit SODIMM slot, bus, SRAM bank, and instruction-fetch path; the only memory difference is the shipped module — the Ant64 carries 2.25 GB and the Ant64C 4.5 GB, while the entry Ant64S ships 1.125 GB and is user-upgradable to 4.5 GB by swapping the SODIMM. The controller and bitstream are identical either way; capacity is detected at boot. 4.5 GB is the single-rank ceiling for the controller's addressing — 16 row bits, 10 column bits, and 8 banks (BA0–BA2) across the 72-bit bus.
DDR3-800 (800 Mbps) is the maximum supported data rate — the controller's ceiling on this part, not a conservative derate — so the 7.2 GB/s figure is fixed. Faster SODIMMs still work: the module itself is a commodity DDR3-1600 SODIMM — the dominant retail grade — which runs perfectly underclocked at DDR3-800. A typical DDR3-1600 stick's 11-11-11 timing (13.75 ns absolute) maps to ~6 controller cycles at the 400 MHz clock — a low, tractable count whose absolute latency is at worst equal to premium native DDR3-800 (5-5-5 = 12.5 ns) and better than budget DDR3-800 (6-6-6 = 15 ns). So the guidance is simply buy any cheap 1Rx8 DDR3-1600 SODIMM: cheaper, and no worse on timing, than sourcing native DDR3-800 parts. Single-rank (1Rx8) is required today — the controller currently drives one chip-select, so it only addresses rank 0; a 2-rank (2Rx8) module leaves its second rank unaddressed and presents half its capacity (a 2Rx8 4 GB stick comes up as 2 GB), so confirm 1Rx8 from the part number or SPD before buying. The second chip-select is wired on the board but not yet enabled in the controller — when dual-rank support lands, a common 2Rx8 8 GB ECC SODIMM will come up at its full 8 GB, i.e. 9 GB of 9-bit-byte storage across the 72-bit bus, doubling the single-rank ceiling. Until then the ceiling is the 4 GB single-rank stick (4.5 GB), and the only single-rank 8 GB option is the rare 1Rx8 8 Gbit module. A single 16 GB stick (which would give 18 GB) is not a realistic DDR3 target: 16 GB DDR3 modules exist only as registered server DIMMs, not unbuffered SODIMMs, and the 72-bit scheme needs an unbuffered ECC SODIMM for its ninth byte — so 9 GB is the practical dual-rank maximum.
7.2 GB/s peak gives substantial headroom — even pathological mixed workloads (heavy rasteriser + large sample streaming + dense CPU working set) stay well below saturation. Typical mixed workloads run at 1.5–2 GB/s, leaving most of the budget unused, and the BSRAM scratchpad and wide-mode SRAM absorb the hottest accesses on top of that.
Used for:
- FireStorm wide-mode code —
.text.widesections, two 36-bit wide instructions per 72-bit word (narrow RV64GC runs from the HyperRAM narrow region instead) - FireStorm data — heap, stack overflow, application memory, file system cache
- Art library, audio sample banks, streamed audio, bitmap framebuffers
- Cartridge / SD-streamed assets
Both wide buses are addressed as a sequence of 9-bit bytes — location N is the Nth 9-bit byte (8 data bits plus one extra bit). The 72-bit DDR3 word is 8 of these bytes; the 36-bit SRAM word is 4. On a FireStorm instruction fetch the extra bits form the wide-mode encoding (the 72-bit word holds two 36-bit wide instructions); on a FireStorm data load/store they are per-byte watch bits, so the debugger can mark any location to fire a watchpoint — no comparator, no cycle cost. The FPGA audio and graphics blocks (blitter, audio DSP, rasteriser) read the bank as plain 72-bit-wide data and ignore the watch bits, so the per-model capacities (1.125 / 2.25 / 4.5 GB) are the full 9-bit-byte figures. Because every location is 9 bits, an X-GB ECC stick presents exactly X·2³⁰ addressable bytes — a clean power of two — holding X·9/8 GB of raw storage.
A simple 8 KB direct-mapped write-through D-cache covers DDR3 data accesses for FireStorm, catching the patterns the BSRAM scratchpad can't predict (pointer chasing, hash buckets, dynamically-allocated data). Streaming code uses cache-bypass via bit 63 of the address to avoid polluting the cache.
Arbitration between FireStorm code/data fetches, blitter texture reads, and audio DSP DMA is handled by the FireStorm DDR3 arbiter. The arbiter prioritises:
- FireStorm EE instruction fetch (narrow-mode, or wide-mode misses not served by the SRAM bank)
- FireStorm D-cache fills
- Audio DSP DMA (real-time priority)
- Blitter sequential reads (burst-friendly)
- Background DMA from Xcrisp DMACPY operations
FPGA Flash + HyperRAM — Third Memory Bus
FireStorm's third external memory bus carries two devices that share their lower data lines and clock but have separate chip-select lines: the configuration / asset flash and a 16MB HyperRAM (a HyperBus device, covered below). The flash and the HyperRAM share the clock and the lower four IO lines (IO0–3) — the lines the FPGA boots from; the HyperRAM adds its own upper four IO lines (IO4–7) plus an RWDS strobe for full x8 operation, and each device has its own CS#. Only one device is selected at any instant.
The flash is a read-only asset store for built-in system data that never changes at runtime:
- Built-in wavetables — standard waveforms (sine, square, saw, triangle, noise variants)
- FM voice data — operator configurations, envelope presets, algorithm tables
- Standard font bitmaps — the system font and built-in character sets
- Default palette data — factory palettes, CRT profile LUTs
- Boot graphics — splash screen, AntOS boot assets
Flash read bandwidth is lower than SRAM but adequate for these workloads — font data and FM tables are small enough to be copied to BSRAM or DDR3 at boot time for faster runtime access if needed. The key advantage is that none of this consumes DDR3 capacity: static assets that never change live in flash; the fast RAM is reserved for scene data that does.
DeMon has access to the FPGA flash via the FPGA's JTAG chain — it can reprogram flash contents without the FPGA bitstream being involved.
FPGA HyperRAM 1 — 16 MB (shares the boot-flash bus)
On that bus is a 16MB HyperRAM (a 3 V HyperBus device — see below). It shares the clock and the lower four IO lines with the flash — the same lines the FPGA uses to read its configuration at power-up — and brings its own upper four IO lines (IO4–7) and RWDS strobe for full x8 operation; the two devices are distinguished purely by their separate CS# lines. The arrangement is safe across boot because the HyperRAM's CS# is held deasserted at power-on: while the FPGA configures itself from the flash over the shared lower lines, the HyperRAM stays off the bus and the flash wins the cold boot uncontested. Once configuration completes, the GoWin MSPI pins revert to fabric I/O, FireStorm drives both CS# lines itself, and the HyperRAM runs as a full HyperBus device.
Unlike the read-only flash, the HyperRAM is read/write volatile store, on the third bus independently of the DDR3 and 36-bit SRAM buses. Its primary role is holding ROM data for simulated systems — OS / firmware images, game-cartridge contents, disk and tape images, and the fixed asset sets a personality core needs. The supervisor loads these images into the HyperRAM; the personality core then reads them as the simulated machine's ROM/cartridge address space (swapping a cartridge or disk is just the host rewriting that HyperRAM region).
Keeping that data in the HyperRAM is a deliberate bus-isolation choice. Because the HyperRAM is on its own bus — shared only with the config flash, which is essentially idle at runtime — a personality core streams cartridge and ROM bytes from it in parallel with FireStorm's wide-mode instruction fetch on the SRAM bus and its working data on the DDR3 bus, without contending for either. The simulated machine's ROM traffic stays off the two buses the host CPU depends on for throughput, so adding a faithful personality doesn't steal bandwidth from code fetch or working memory.
This is also what makes faithful compatibility cheap: a personality reproduces its machine's memory map simply by loading the right ROM sets, cartridge contents, and disk/tape images into the HyperRAM — served from a bus independent of the code and working-memory buses, with period-correct timing layered on top.
In native Ant64 mode the 16MB is available as general-purpose working store — staging, caching, scratch — which likewise keeps that load off DDR3 and SRAM. (The native-mode allocation is left to system software; the hardware just provides the 16MB on its own bus.)
The trade-off is first-access latency: even at 400 MB/s streaming, the HyperRAM's first-access read latency (~70 ns before a burst begins — the 128 Mb part's fixed 2× latency, detailed below) is higher than the parallel SRAM or DDR3. The win is high bulk bandwidth on a contention-free bus, not single-access latency — so latency-critical bytes can still be staged from the HyperRAM into BSRAM, SRAM, or DDR3 at load time, while bulk ROM and cartridge images live in the HyperRAM and stream from it during execution.
Part and performance. The device is the Infineon S70KL1282 — a 16MB (128 Mb) 3 V HyperRAM on the HyperBus interface (the S70KL family is the 3.0 V grade, in the 200 MHz GA speed bin), chosen so it sits directly on the 3.3 V flash bus with no level-shifting. At a 200 MHz DDR clock it moves 8 bits × 2 edges × 200 MHz = 3200 Mbit/s ≈ 400 MB/s, with the RWDS strobe for read capture. The 128 Mb part is a stacked dual-die (two 64 Mb dice) that runs fixed 2× latency only, so although the row-open access time tACC is 35 ns, the effective first-access latency is ~70 ns (two latency periods) before a burst streams; streaming throughput is unaffected.
That is far more than any simulated ROM requires. The 8/16-bit targets clock their ROM at the CPU bus rate:
| System | ROM access cadence | Peak ROM bandwidth |
|---|---|---|
| Amiga 500 (68000 @ 7.16 MHz, 16-bit) | word / ~558 ns | ~3.6 MB/s |
| Atari ST (68000 @ 8 MHz, 16-bit) | word / 500 ns | ~4.0 MB/s |
| Mega Drive (68000 @ 7.67 MHz, 16-bit) | word / ~521 ns | ~3.8 MB/s |
| SNES (65816 @ 3.58 MHz FastROM, 8-bit) | byte / ~280 ns | ~3.6 MB/s |
The HyperRAM out-runs every one by ~100×, and even a worst-case cold random read — its ~70 ns first-access latency plus the command/address phase, ~90 ns in total — lands well inside the 68000's ~500 ns bus cycle, so the simulated machine never stalls on it. A faithful personality throttles its CPU to the original clock regardless, so the HyperRAM is never the limiting factor — and period-correct wait states are reproduced deliberately.
Why HyperRAM at 3 V. A 3 V HyperBus part reaches 400 MB/s at 200 MHz while sitting directly on the 3.3 V flash lines with no level-shifter — so the third bus gets full 200 MHz throughput without splitting off a separate 1.8 V rail for the memory. Its first-access latency, paid once per burst, is dwarfed by the simulated ROMs it serves — slower by nearly two orders of magnitude — so bandwidth is never the constraint.
DeMon reaches the HyperRAM over the same JTAG-chain path it uses for the flash bus. The HyperRAM sits on the boot bus, which (with its flash + HyperRAM pair) is common to every FireStorm board.
FPGA HyperRAM 2 — a second, private 16 MB bank
Where HyperRAM 1 shares the boot-flash MSPI bus, HyperRAM 2 is a fully independent HyperBus on dedicated fabric I/O — its own clock, its own RWDS, its own CS, sharing nothing with the flash or configuration logic. It is an identical S70KL1282 (16 MB, 3 V, 200 MHz DDR), so the two banks are matched, but electrically HyperRAM 2 is the cleaner of the pair: no flash contention, no config traffic, full-rate on its own bus.
It occupies eleven general I/O in the 3.3 V right-island banks (2/3) of the FPGA pinout — CS G19, CLK E17 (SGCLK1), RWDS on F18 (DQS23), D0–7 — with RWDS landing on a real DQS pin, the resource the second bank needs and the config bank could not provide.
CPU-visible mapping
In native Ant64 mode the two banks are directly CPU-visible as contiguous narrow-memory windows: HyperRAM 1 occupies 0x0000_0000–0x00FF_FFFF and HyperRAM 2 occupies 0x0100_0000–0x01FF_FFFF. The remainder of the low address region, 0x0200_0000–0x7FFF_FFFF, is reserved. There is no bank-select register or aliasing between the windows; the physical bank is selected by the address decode. Both windows are uncached, byte-addressed, readable, writable, and executable only in narrow mode. Personality firmware may still assign ROM/cartridge roles independently of these native-mode addresses.
Two banks → 32 MB, ~800 MB/s. Both banks are standard on every FireStorm machine (Ant64 and eZX), giving 32 MB of HyperRAM across two non-contending buses (~400 MB/s each, ~800 MB/s aggregate). The intended split follows their electrical character: put the latency-sensitive, constantly-read stream — a personality's live ROM — on the private HyperRAM 2, and the burstier or occasional stream — disk/tape image staging — on HyperRAM 1, whose throughput a personality must treat as shared with the boot flash, not a clean full-rate lane. A personality can then stream ROM from one bank while pulling disk images from the other, neither stealing bandwidth from the SRAM (code) or DDR3 (working) buses.
Independent clear. Each bank's RESET# is driven separately by DeMon's I/O expander — HyperRAM 1 on PA2, HyperRAM 2 on PA4 (both active-low, carrier pull-ups so they release out of reset before DeMon is up; see DeMon). So the host can wipe and reload one bank — swap the disk image on HyperRAM 2 — while the other bank's ROM stays live and the personality keeps running.
The eZX's memory map. The eZX Spectrum reproduces its machine's memory map from these two banks — live ROM served from the private HyperRAM 2 (so ROM reads never contend with the config/asset flash or the eZX's flash-mapped mini-OS), with Classic-mode image staging and tape/disk buffering on HyperRAM 1. Everything lands where the eZX expects it, on the same S70KL1282 parts the rest of the family carries.
The Register-Window Model — FireStorm Chipset Registers as Memory-Mapped Peripherals
From the perspective of the external chips — Pulse and DeMon — the FireStorm chipset is simply a block of memory-mapped addresses accessible over their register windows (OPI for Pulse, PCIe for DeMon). There is no special protocol, no command layer, no driver handshake. Writing to an address updates a FireStorm chipset register. Reading from an address returns a register value. It is exactly the same programming model as any other memory-mapped peripheral on an embedded system — the FPGA just has a very large and very capable register file.
From the perspective of the FireStorm EE itself, chipset registers live in the standard MMIO region (0xFxxx_xxxx, see FireStorm EE §5.4) and are accessed with ordinary load/store instructions. No external bus needed — the CPU and chipset share the same internal address fabric.
This means:
- The FireStorm EE writes a palette entry by storing a 32-bit value to the palette RAM address. The palette updates on the next scanline. No IPC, no kernel call, no DMA setup.
- DeMon writes a display mode register to force a specific CRT profile at boot — one 16-bit write over its PCIe link.
- Pulse writes audio parameter registers — volume, pitch, envelope — as ordinary memory writes, timed by its own PIO logic.
- Any chip can read back status registers, scanline counters, blitter job IDs, or completion flags as simple memory reads.
The FPGA controls what address ranges are visible in each external chip's register window and what they map to internally. A window can expose palette RAM, sprite attribute tables, layer registers, the Copper list, audio registers, blitter job queues, or any region of DDR3 (within addressable bounds). Each supervisor's register interface (Pulse over OPI, DeMon over PCIe) is independent — they can have different mappings, different access permissions, and never contend with each other.
If you wrote games or demos in the 80s or 90s, you already know this feeling. POKE $D000 on the C64 and a sprite moved. Write to $DFF180 on the Amiga and a colour changed on the next scanline. The machine did what you told it, immediately, because you spoke to it directly. This register-window model gives external chips that feeling on the Ant64 — and the FireStorm EE has it natively, since chipset registers are just MMIO from its perspective.
Inter-Subsystem Data Paths
DeMon → FireStorm (AntOS UI + bulk data in + SID and SAM audio): DeMon (the CM5) drives FireStorm over HDMI — 2× HDMI into the fabric (a 720p ImGui overlay plus a data channel). Traffic is frame-locked by FireStorm's system vsync: on each pulse DeMon bursts the next frame's layer descriptions (an index-per-cell text grid plus a sprite display list — a few KB, not a framebuffer) and a per-frame audio chunk, and the link is idle between bursts — so the peak figure is headroom, not the steady-state load. DeMon composes the AntOS UI, sprite and tilemap layers as descriptions and FireStorm renders them at scanout (Composer); the supervisor never pushes finished pixels. The same physical link also carries audio data from DeMon's Triple SID engine (L/C/R, 9 SID voices) to the Tempest mixer, plus lower-priority network and storage data for the FireStorm application — packets, file/DBFS reads, asset and OTA payloads, debug captures — into FireStorm DDR3 at HDMI / PCIe speeds, orders of magnitude faster than the register window for large transfers. The frame description owns the vblank deadline and is sent first; this bulk traffic fills the spare bandwidth beneath it and never delays a frame.
Pulse → FireStorm (sequencer UI + sprite/tilemap layers + bulk audio): Pulse's ESP32-P4 MIPI TX drives FireStorm's MIPI RX — a 2-lane D-PHY link at 1.5 Gbps per lane, 3 Gbps total (~375 MB/s peak). Same frame-locked cadence as the DeMon link: a vsync pulse from FireStorm triggers Pulse to burst the next frame's layer descriptions plus audio over MIPI; idle between pulses. Pulse composes its sequencer / mixer / sample-browser UI and its sprite and tilemap layers as descriptions (Composer), which FireStorm renders at scanout; the link also carries AMY synth output, classic-emulator audio, sample data, and lower-priority controller data (aggregated jog-dial and joypad state) into FireStorm — all beneath the frame description, which is sent first against the vblank deadline. Pulse retains a OPI register window for low-latency control writes and small packets in parallel with MIPI (note-on / note-off / parameter updates, latency-critical input) where the MIPI link's framing is not appropriate.
FireStorm → DeMon and FireStorm → Pulse (return paths): The two supervisors take different return paths.
- DeMon return — PCIe. DeMon's return rides its PCIe ×1 link to the CM's PCIe hard IP — the same bidirectional link that carries its commands, so the return needs no extra wires. Bandwidth and latency are set by the Gowin PCIe endpoint (bring-up figures pending).
- Pulse return — OPI. Pulse's return rides an OPI link (8-bit SPI) with a Tempest data-ready interrupt — FireStorm signals, Pulse clocks the payload out.
Both replace the earlier per-supervisor LVDS-to-MIPI CSI bridge (the Lontium LT9211) — no bridge chip, no FPGA LVDS TX pins — at lower bandwidth than the old 1-lane MIPI return (~190 MB/s). The DeMon return carries chipset telemetry, audio buffers from the Tempest mixer (e.g. for OTA stream encoding via the ESP32-C5), compressed or reduced-resolution video readback for capture / streaming / recording, and bulk transfers from FireStorm DDR3 into AntOS memory. The Pulse return carries Tempest mixer output for resampling / recording / sample capture into the sequencer, plus telemetry and bulk transfers. Raw full-resolution frame readback no longer fits either return budget — capture paths compress or downscale on the way out.
On-die / CM offload: heavy compute is no longer a bolt-on board — DeMon is a quad-core CM5. FireStorm can offload latency-sensitive kernels to the on-die A25 hard core (over AXI) or bulk work to the CM (over PCIe) via the provisional Xaccel path; results return into FireStorm's register file or shared memory.
DeMon ↔ FireStorm / FPGA flash: DeMon's PCIe link gives it register-level access to FireStorm for system control, monitoring, and configuration. DeMon's JTAG connection gives it programming and debug access to the FPGA bitstream and — via the FPGA's internal JTAG chain — the FPGA flash. DeMon can reprogram the entire FPGA contents (bitstream + flash) from one supervisor chip over JTAG.
Supervisor Links as a Data Fabric, Not Video Transport
The supervisor links into FireStorm — Pulse's MIPI and DeMon's HDMI — are treated as general-purpose high-bandwidth pipes, not as video transport in any meaningful sense. The endpoints move bytes from one side to the other regardless of what those bytes represent. A "frame" is just a chunk of memory transferred under D-PHY framing rules; the receiver decides what to do with the contents.
In practice this means the inbound links from DeMon and Pulse carry interleaved payload types — composited UI layers, sprite/tilemap data, audio buffers (SID, SAM, AMY, sample playback), command lists for the FireStorm blitter, asset uploads, OTA payloads, debug captures. The transmitter packs a header indicating type, the receiver dispatches. Real video frames and audio buffers and arbitrary bulk data all share the supervisor links (Pulse's MIPI at ~375 MB/s, DeMon's HDMI far more; the return is separate — PCIe for DeMon, OPI for Pulse), with the register windows — OPI for Pulse, PCIe for DeMon — reserved for low-latency single-register writes and small packets where the bulk links' burst-oriented nature would add too much latency.
The return paths (FireStorm → DeMon and FireStorm → Pulse) use their own links — DeMon's PCIe, Pulse's OPI. FireStorm packs whatever data it wants into the return transfers using the same type-header convention, and the receiving supervisor dispatches by header type. The physical layer differs from the inbound feeds (and between the two supervisors), but the data-fabric framing — typed payloads over a general-purpose pipe — is identical.
This framing turns each FireStorm ↔ supervisor connection into a clean asymmetric peer link: an outbound feed — Pulse's MIPI (frame-locked at ~375 MB/s), DeMon's HDMI (far more) — for vsync-aligned UI + audio flow, and a separate return channel — PCIe for DeMon, OPI for Pulse — for telemetry / readback / bulk. Either way the inbound feed dominates the pair's bandwidth, the highest of any inter-chip path in the system.
The AntOS text and videotext layer is one specific consumer of this fabric on the DeMon side — see the AntOS Text Architecture document for the cell format, font system, three logical display modes (Terminal, System, Videotext), and the VT100/ANSI parser that produces the rendered pixel layer. At 640×360 RGB888 / 60 Hz the text layer occupies ~40 MB/s — a small fraction of DeMon's HDMI bandwidth, leaving the rest free for the other data types that share the link.
Memory Map Summary
| Memory / Bus | Capacity | Bandwidth | Ant64S | Ant64 | Ant64C | Accessible to |
|---|---|---|---|---|---|---|
| BSRAM (on-chip) | ~765KB | ~3.4GB/s/block | ✓ | ✓ | ✓ | FireStorm EE (Xstack/Xctx/scratchpad), chipset (line buffers, palette, copper, audio voice state) |
| Wide-mode SRAM | ~4.5MB | ~900MB/s | ✓ | ✓ | ✓ | FireStorm EE instruction fetch (wide mode only) |
| FPGA flash | varies | read-only | ✓ | ✓ | ✓ | All FireStorm subsystems; DeMon via JTAG. Shares the third (boot) bus with the HyperRAM (separate CS) |
| FPGA HyperRAM 1 | 16MB | HyperBus (S70KL1282, 3 V, 200 MHz DDR, ~400 MB/s, ~70 ns first access) | ✓ | ✓ | ✓ | ROM / cartridge / disk images. Shares the boot-flash bus (lower IO + clock, separate CS) — contends with flash/config. Reset via DeMon PA2. |
| FPGA HyperRAM 2 | 16MB | HyperBus (S70KL1282) — private bus, FPGA banks 2/3 (CS G19, CLK E17, RWDS F18/DQS23) | ✓ | ✓ | ✓ | Second, independent HyperRAM — no flash/config contention. 32MB total, ~800MB/s aggregate; probed at boot (16MB is the floor). Reset via DeMon PA4. |
| FireStorm DDR3 | 4.5 GB (C) / 2.25 GB (Ant64) / 1.125 GB (S); SODIMM-upgradable to 4.5 GB | DDR3-800; 7.2 GB/s peak (72-bit) | ✓ | ✓ | ✓ | FireStorm EE code/data; blitter; audio DSP |
| DeMon CM RAM | 2 GB (→8 GB) | CM5 LPDDR | ✓ | ✓ | ✓ | DeMon / AntOS (Linux) — the CM5's private RAM; bridged to FireStorm over PCIe / HDMI |
| Pulse PSRAM | 32 MB | ESP32-P4 OctSPI (memory-mapped) | ✓ | ✓ | ✓ | Pulse — sample libraries, AMY patch banks, sequencer state (private to Pulse) |
| Register window (Pulse) | window | OPI speed | ✓ | ✓ | ✓ | Pulse ↔ FireStorm mapped window |
| Register window (DeMon) | window | PCIe | ✓ | ✓ | ✓ | DeMon ↔ FireStorm mapped window (over PCIe) |
| HDMI (from DeMon) | — | 2× HDMI | ✓ | ✓ | ✓ | DeMon → FireStorm AntOS UI overlay + data channel |
| MIPI RX (from Pulse) | — | 3 Gbps (2-lane) | ✓ | ✓ | ✓ | Pulse → FireStorm sequencer UI + bulk audio data |
| PCIe return (FireStorm → DeMon) | — | PCIe ×1 | ✓ | ✓ | ✓ | FireStorm → DeMon return path: telemetry, audio/OTA readback, compressed video capture, bulk data into AntOS memory |
| OPI return (FireStorm → Pulse) | — | 8-bit SPI + IRQ | ✓ | ✓ | ✓ | FireStorm → Pulse return path: mixer-output resampling / recording / sample capture, telemetry, bulk data |
A Note on the Previous Architecture
Earlier Ant64 prototypes used a separate RISC-V SoC as the main CPU, with FireStorm acting as a chipset accessed over QSPI. That arrangement has been superseded: FireStorm now hosts the CPU directly. The benefits of the integration:
- No bus crossing between CPU and chipset — the CPU's writes hit chipset registers in the same FPGA clock cycle.
- Shared scratchpad BSRAM — the same on-chip memory holds CPU stacks (Xstack), task contexts (Xctx), and chipset structures (line buffers, palette, copper).
- Unified timing domain — no skew between CPU dispatch and chipset response.
- Simpler memory map — no separate "CPU DRAM" and "chipset DRAM"; one DDR3 with arbitrated access.
- Lower BOM cost — one large chip instead of a large chip + a substantial RISC-V SoC.
The trade-off is a slightly more demanding FPGA design and lower theoretical CPU peak performance than a hardened RISC-V SoC could deliver. In practice the integration wins because Ant64's workloads are dominated by CPU↔chipset interaction patterns where the previous separate-CPU-plus-chipset architecture spent most of its time crossing buses.