You Never Forgot What It Felt Like
That moment when you first saw the Amiga's copper bars rippling down the screen. The way a game's parallax layers scrolled past each other with that impossible smoothness. The warm glow of a Trinitron monitor, scanlines and all. The feeling that the machine was alive — that you could reach inside and bend it to your will in ways a PC never let you.
You didn't imagine it. That was real. And it's been missing ever since.
Introducing FireStorm
The display heart of the Ant64 is FireStorm — a GoWin GW5AST-138 FPGA with 138,000 logic cells, 340 block RAM modules, and 298 DSP units, running at up to 380MHz. It doesn't emulate classic hardware. It is classic hardware — rebuilt from first principles, freed from every constraint that held the originals back.
This is what happens when someone who shipped games on the Amiga in the 90s gets to design the display chip they always wished existed.
The Outputs
Two simultaneous display outputs — each independently configurable, each rendering from the same source data in real time.
Main HDMI — the primary modern display path. 4K @ 60 Hz, HDMI 2.0 with HDCP support, CEC, EDID-driven mode selection. Drop the resolution and the link rate gives back its budget as refresh rate — 1080p@120 Hz with 3D formats, 1440p at high refresh, etc.
The implementation: the FPGA emits DisplayPort over four SerDes lanes (HBR2, 5.4 Gbps each) into a Parade PS176 DP→HDMI 2.0 protocol converter chip on the PCB, which drives a standard HDMI Type A connector on the back panel. The DP lanes are dedicated transceiver pads, not general I/O, so this path costs the FPGA ~11 pins of SerDes/GPIO allocation and nothing from the fabric I/O budget. The PS176 brings the HDMI 2.0 spec compliance (HDCP 1.4/2.3, SCDC, deep colour, audio packet handling) without it having to live in FPGA logic. See Main HDMI output for the full chip / pinout / BOM detail.
Retro VGA + audio — the analogue retro path. Standard DE-15 VGA socket plus a 3.5 mm stereo TRS audio jack adjacent on the back panel. Native VGA resolutions (31 kHz horizontal), 1080p60 maximum, and — the interesting bit — "240p superresolution" modes for genuine 15 kHz CRT output via off-the-shelf SCART adapters. The CM8833 in the garage works. The PVM-20M2MDU in the corner works. Any SCART adapter you already own works.
The implementation: a second HDMI TX from the FPGA — built from regular fabric-pin LVDS (4 TMDS pairs) — feeds an AG6201 HDMI→VGA bridge chip on the PCB. The AG6201 extracts the RGB analog signal (its own 8-bit-per-channel DAC) to the DE-15 socket and decodes the HDMI audio-island packets through its embedded stereo DAC to the 3.5 mm jack. Audio is inherently synchronised to video because both come from the same HDMI stream, clocked off the same pixel-clock domain — no drift, no resync logic, no separate audio path on the host side. DDC/EDID is wired through so the system can read the connected monitor's capabilities and auto-configure modelines. ~11–12 FPGA fabric pins total. See Retro VGA output for the full detail; the same chip is used by MiSTer Direct Video, so community cables and SCART adapters are drop-in compatible.
Both outputs carry independent content at independent modelines and independent refresh rates — the FPGA's two display pipelines are separate inside the chipset, with the Copper, layer registers, and CRT simulation running independently per output. Modern HDMI for the living-room TV, retro VGA + audio for the CRT in the corner — both simultaneously, both showing whatever you want.
Auxiliary Displays (outside the FPGA path)
Two additional displays live outside the FPGA's pixel pipeline entirely:
- Keyboard touchscreen — a capacitive TFT panel on the keyboard, driven by DeMon's ESP32-P4 over SPI. It has its own framebuffer in DeMon's PSRAM and its own controller; the FPGA is not involved. AntOS uses it as a secondary display for status, recovery, soft keys, debug info, and file management. It stays visible at all times, including during the brief blackout windows when the FPGA is reconfiguring (a fraction of a second for the native chipset on power-on; up to ~1 second for a personality cartridge load).
- Circular display on the case — a small round TFT mounted at the far left of the case, just above the keyboard. Driven by Pulse's ESP32-P4 over SPI, also independent of the FPGA. Shows jog-dial labels, per-knob state, sequencer status, or any UI Pulse chooses.
These two displays mean the machine always has visible UI, even when the FPGA is mid-reconfigure and the main display is dark. That is a deliberate design choice — the system never goes "headless" from the user's perspective.
The Inputs
FireStorm doesn't just push pixels out. It receives content in — from the Colony network, and from DeMon's ESP32-P4 — and composites it into the layer stack like any other layer. The Copper controls it per scanline. It appears on all outputs simultaneously.
Colony video (Ant64 and Ant64C — not Ant64S) — connect one or two HDMI frame grabbers to the Colony RX ports and FireStorm receives live video from any HDMI source as standard compositor layers. Console output, PC footage, a camera feed — any HDMI source, arriving over the network, composited in hardware over your generated content. Two grabbers means two simultaneous streams. Picture-in-picture. Chroma key. Copper-driven transitions between them. FireStorm sprites flying over live footage from a PlayStation. The frame grabbers can sit anywhere in the Colony string — they don't need to be physically attached to the machine.
Supervisor MIPI layer — DeMon's ESP32-P4 has its own MIPI display output (2 lanes + clock, 3 Gbps), and FireStorm has two hardware MIPI RX inputs. DeMon pushes its CPU-generated content — the AntOS UI, recovery screens, OS overlays, debug panels — directly into FireStorm's compositor as a layer. Pulse occupies the second MIPI RX with its sequencer / mixer / sample-browser UI. From FireStorm's perspective each is just another layer: priority register, colour key, Copper-controllable per scanline, visible on all outputs. AntOS lives on DeMon, so the OS UI is always there as a MIPI layer once the FPGA is configured. These MIPI feeds are not limited to flat UI surfaces: each supervisor's 2D-PPA blits sprites and tile-grid backgrounds into its MIPI output, so AntOS file-browser grids and Pulse step-sequencer matrices reach FireStorm as composed tilemap content — complementing the FPGA's own hardware tilemap layers rather than competing with them. The cadence is frame-locked: FireStorm fires a system vsync pulse at the end of every frame, and DeMon and Pulse use that pulse to push their next framebuffer plus the next frame's audio over MIPI in one burst — the supervisor renders into local PSRAM during the frame and ships the result on the next pulse, so the link is idle between frames rather than continuously streaming. The FPGA's native chipset auto-loads from its own flash on power-on in a fraction of a second; only when a personality cartridge replaces it does that blackout extend to ~1 second.
The Philosophy: Render Small, Output Big
The Ant64 has two primary native resolutions. Standard at 480×270 closely matches the pixel size of the Amiga's low res mode — that classic chunky pixel feel, exactly as you remember it. Hires at 960×540 is exactly double in both axes, the same relationship the Amiga had between low res and high res. Except the Ant64 doesn't need interlace to get there, and it doesn't flicker.
At Standard, every native pixel becomes a perfect 8×8 block on the 4K output. At Hires, a 4×4 block. No interpolation. No blur. Pure integer scaling, pixel-perfect, exactly as intended.
These aren't the only options — horizontal and vertical axes are fully independent, and any valid combination from the resolution tables works. Run 320 wide for Mega Drive vibes, 640 wide for Amiga hires, mix different resolutions on different layers simultaneously. The hardware doesn't care. Standard and Hires are named reference points, not constraints.
The Layers
FireStorm composites multiple independent layers in hardware on every scanline. No CPU cost for the final mix. No frame buffer round-trip. Just the beam and the data.
Each layer has its own independent native resolution. Not a shared global resolution that everything must fit — each layer picks its own, and the blender composites them all to the output resolution simultaneously. A game background at 320 wide. Sprites at 480. A UI overlay at 960 for sharp text. A Colony video stream at whatever resolution it carries. All on screen at once, blended in hardware, at the output pixel clock.
Each layer also has its own position. An X offset and Y offset place it anywhere on the output. A width and height clip its active rectangle. Outside those bounds, the layer is transparent and the layer below shows through.
A concrete example. You want a game with a sharp high-resolution score panel at the top and a rich high-colour lo-res tilemap game underneath. On the Amiga this was a genuine problem — hi-res for the status bar meant hi-res for everything, burning bitplane DMA bandwidth on the game area. Lo-res for the game meant a lo-res status bar. HAM gave you colour but killed sprites in that region. Every choice was a compromise the hardware forced on you.
On the Ant64:
- Score panel — a 960×60 Hires layer, Y_offset = 0, sharp pixel-perfect text and numbers at the top of the screen
- Game tilemap — a 320×210 Standard layer behind it, 256-colour palette, full Mega Drive-style per-column vertical scroll, sprites in their own layer on top
- The two layers overlap freely — the tilemap scrolls underneath the score panel, the panel stays fixed, zero compromise on either
The score panel only needs updating when the score changes. It isn't part of the game framebuffer. It doesn't share bitplane bandwidth with the game. It just sits in its own BRAM, composited in hardware, costing nothing at runtime. The hardware does what you always wanted it to do.
The Amiga used the Copper to drag screens of different resolutions up and down the display. Those regions were vertically exclusive — lo-res and hi-res content could be stacked but never overlap, always with a hard horizontal boundary between them. Move the boundary with the Copper, but never cross it.
The Ant64 has no such boundary. Any layer can overlap any other layer freely. A Hires UI strip docked to the bottom of a Standard game layer. A popup panel floating over both. A HAM24 photograph fading in over a tilemap via alpha blend where their rectangles intersect. The Copper can animate any layer's X or Y position every frame — layers sliding across the screen, no CPU rendering involved. It is the Amiga screen-drag mechanic generalised to every layer independently, extended to allow full overlap, with no remaining constraints.
Each layer also has its own palette, its own scroll registers. They composite in hardware priority order, with colour key transparency and per-palette alpha — and the Copper can change any of it at any pixel position on any scanline.
Tilemap layers support per-tile palette selection, H and V flip per tile, and a scroll system that shames the Mega Drive. Per-tile-row horizontal scroll is driven by the Copper — one register, updated at each tile row boundary, costing nothing in silicon. Per-tile-column vertical scroll uses a configurable register file with adjustable granularity: set the step count to fit your tile configuration, and the feature degrades gracefully rather than switching off. Variable tile sizes from 4×4 to 128×128, non-square supported, power-of-two for zero-cost address calculation.
Sprite layers use a double-buffered pipeline that sorts and fetches one native row ahead of the beam, giving the full vertical repeat window for prefetch. With the BSRAM running at 380MHz the sprite budget is in the hundreds per scanline — more than you will ever use. Sprites are split between a user region and a system region: DeMon owns the top of the table for the cursor and OS overlays, and that ownership is enforced in silicon. No software bug can steal your cursor.
Each layer also has its own clip table — a memory block of left/right boundary pairs, one per scanline, that defines exactly which pixels of the layer are visible. A single entry covering the full screen is no clip at all. A table with one entry per scanline can describe any shape — diagonal splits, curves, portals, anything expressible as a left and right edge per line. The FireStorm Execution Engine builds the table each frame for dynamic clips. The Copper swaps the pointer mid-frame to change clip regions instantly.
This is how you make a Lego-style dynamic split-screen. Each player's view is its own layer with its own clip table. The tables are complementary — one player's right boundary is the other's left. The join follows whatever geometry the game computes. When the players are close enough, swap both tables for single full-screen entries and the split disappears in one frame. No transition, no artefact — both layers always contain valid full-screen content.
Beyond the hardware tilemaps and sprites, the FireStorm Blitter can render bitmap layers — intermediate framebuffers filled with primitives before the scanline mixer composites them. Sprites with rotation and scaling. Mode 7-style floor planes. Textured triangles. Lines, shapes, flood fills, text. The blitter runs a job queue defined by the FireStorm EE, working through it while the CPU continues executing. Double and triple buffering keep the display fed while the blitter prepares the next frame. If nothing changed in a layer, the blitter skips it entirely — a static HUD costs nothing until it needs updating.
Texture data for any primitive — sprites, triangles, tilemap tiles — can come from on-chip BSRAM or from the wider DDR3 with the blitter streaming data via burst reads. Hot working sets (active sprite sheets, the current texture atlas) stay in BSRAM where access is single-cycle and predictable. The audio DSP shares BSRAM and DDR3 with the blitter alongside its own wavetables and FM voice data — the on-chip routing arbitrates these without bus stalls in the common burst-sequential case. Full details in the Memory Architecture reference.
A typical scene's sprite sheets, texture atlas, and intermediate buffers fit comfortably within the on-chip BSRAM and the wide-mode SRAM — meaning a full frame's hot data lives in fast memory. For assets beyond that, the FPGA's DDR3 backs the system with the full art library; the FireStorm EE shares that DDR3 with the blitter and audio DSP via the on-chip arbiter. Small data and register writes from external chips cross via the QSPI FRAM bridge; bulk asset uploads from DeMon use the MIPI link into FireStorm at up to 3 Gbps (2 lanes × 1.5 Gbps). The FireStorm EE itself accesses chipset registers directly as MMIO — no bridge, no driver, just a load or a store.
The FRAM bridge is worth understanding because it shapes how programming the Ant64 actually feels. From the perspective of Pulse, DeMon, and the optional Pi Zero 2W accelerator, FireStorm is simply a block of memory-mapped addresses. Writing to an address updates a palette entry, moves a sprite, changes a layer register, or queues a blitter job. Reading from an address returns the current scanline counter, blitter status, or a value from FireStorm memory. The FireStorm EE itself sees those same registers as native MMIO — no QSPI hop required.
There is no driver. No kernel call. No ioctl, no DMA descriptor ring, no abstraction layer negotiating on your behalf with hardware that doesn't trust you. Just a memory address and a value.
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. Prod the SID registers and sound came out. The machine did what you told it, immediately, because you spoke to it directly. There was nothing between you and the hardware.
That's what the FRAM model gives you on the Ant64. Poke a memory location to move a sprite. Poke another to fire a blitter job. Poke another to change the CRT simulation mode. The FPGA controls what each chip's window exposes and what it maps to internally, and each external interface — Pulse, DeMon, accelerator — is independent. Each chip reaches into FireStorm's register file through its own window without disturbing the others. And FireStorm's own CPU reaches the same registers natively, without going through any window at all.
Modern machines forgot this. The Ant64 remembers.
Pulse, the audio and sequencer subsystem, drives its own MIPI display feed to the FPGA alongside a QSPI register window — the ESP32-P4's MIPI engine carries Pulse's sequencer / mixer UI as a compositable display layer, while the QSPI window handles low-latency control writes. DeMon, the supervisor, holds a JTAG connection to the FPGA and via the FPGA's JTAG chain also the FPGA flash — giving it the ability to reprogram the entire system from one chip, including the bitstream and the flash contents, over a connection that survives even a completely dead OS. DeMon's ESP32-P4 also feeds the supervisor display layer via a second MIPI input (MIPI RX #0; Pulse uses MIPI RX #1), giving each supervisor a fully independent path to the screen.
The wide-mode SRAM — 1M × 36-bit, ~4.5MB on its own dedicated bus — is reserved exclusively for FireStorm's wide-mode instruction stream (see FireStorm EE §3). This bus belongs to the CPU alone. Code fetch from wide-mode SRAM and texture fetch from BSRAM/DDR3 are on physically separate buses with no arbitration between them. FireStorm streams its instruction prefetch while the blitter scans a texture line, simultaneously, at full speed. The throughput figures are what you actually get — not theoretical peaks that evaporate the moment two things happen at once.
The FireStorm also has a flash chip for read-only system assets — built-in wavetables, FM voice data, the standard system font, default palettes. These are available to any subsystem without consuming a byte of BSRAM, wide-mode SRAM, or DDR3. Static assets that never change live in flash; the fast RAM is reserved for scene data that does.
The blitter also has bloom lines and bloom particles — antialiased lines and point sprites with phosphor glow and additive blending, designed specifically for colour vector game aesthetics. Tempest. Asteroids. Star Wars. Each primitive has its own intensity and falloff. Line crossings get brighter. Particle clusters bloom together. The bitmap saturates at hot spots. It looks like a vector CRT because the maths is the same maths. Named presets for the classic arcade titles are built in. A full Tempest-style frame — web wireframe, enemy lines, shot particles, explosion burst — renders in well under 500 microseconds.
FireStorm also has dedicated hardware for ray casting, BSP rendering, and voxel rendering — the techniques behind Wolfenstein 3D, Doom, Quake, Comanche, and Minecraft. A pool of parallel ray DDA units casts all 480 screen columns simultaneously, each stepping through the grid at full clock rate and returning hit distance, wall face, and texture offset in one hardware pass. A BSP traversal engine walks the scene tree from the viewpoint and outputs visible sectors in front-to-back order to a FIFO the FireStorm EE drains. A fixed-point reciprocal unit converts distances to column heights in 2–4 cycles rather than the 16–32 a software divide costs.
FireStorm also supports a layered approach to shadows and lighting without full ray tracing. Shadow maps render the scene from the light's point of view into a depth buffer in Graphics SRAM — a standard blitter pass — then a depth comparator tests each pixel during the main render, adding directional shadows at minimal hardware cost. The same DDA units used for ray casting can march screen-space rays through the depth buffer for ambient occlusion, contact shadows, and reflections — zero additional silicon, high visual impact. A BVH traversal engine (a small generalisation of the SVO engine) and a cross product unit open the path to proper ray-tested shadows for polygon geometry. The combination of shadow maps and screen-space techniques produces results most people perceive as ray-traced without the cost of a full path tracer.
For voxel rendering there are three dedicated paths. A height-field mode (Comanche-style) adds a height map sampler that reads (x,y) height and colour from BSRAM or DDR3 in one pipeline cycle and a vertical span renderer that fills the column as higher voxels appear — the 2D DDA units and reciprocal unit handle the rest. For dense 3D voxel grids the DDA units extend to three axes. For sparse voxel octrees a dedicated SVO traversal engine walks the tree using a slab test unit — ray versus axis-aligned bounding box in 3–4 cycles — outputting hit voxels to a FIFO in front-to-back order without involving the FireStorm EE in the recursion. An SVO node packs exactly into one 36-bit wide-mode SRAM word.
The hardware handles the arithmetic. The FireStorm EE handles the scheduling. The blitter draws the textured spans. The scanline mixer composites hardware sprites on top at zero additional render cost. The 480×270 Standard resolution is what these engines actually ran at — pixel-perfect on the output.
FireStorm includes a complete isometric rendering system — the techniques behind Populous, Theme Hospital, and RollerCoaster Tycoon, done properly. An isometric scanline mapper and diamond span unit render tiles scanline by scanline rather than tile by tile, so the CPU has zero per-tile rendering cost. A hardware depth buffer eliminates painter's algorithm sorting entirely — tiles and sprites draw in any order and the depth buffer arbitrates occlusion per-pixel automatically. A character walking behind a building is correctly occluded without split-sprite calculations, stencil masks, or any of the tricks those games used on period hardware. The FireStorm EE spends its time on AI, pathfinding, and game logic — not pixel pushing. An RCT-scale scene of 50×50 visible tiles and 500 dynamic sprites runs comfortably within a single frame's blitter budget.
The Copper is a general register-write engine that fires at any beam position. Every FireStorm register is a valid Copper target. Palette entries, scroll offsets, layer positions, clip table pointers, layer enables, tile sets, simulation modes — all of it, per scanline, with no CPU involvement. If you wrote Copper lists on the Amiga, you already know how to use this. If you didn't — you're about to discover what all the fuss was about.
HAM. But Actually Good.
The Amiga's Hold-And-Modify mode was an act of desperation that accidentally produced something beautiful. By encoding each pixel as "modify one colour channel of the previous pixel," it delivered photographic images from hardware that had no business showing them. The fringing artefacts were the price.
FireStorm has HAM24. Same principle. 8-bit channel precision instead of 4 or 6. 1024-entry direct palette. And a colour space option that changes everything.
Switch to YCbCr mode and the modify operations target luminance, blue chroma, and red chroma separately — exactly the same separation that JPEG and H.264 use. Human vision is far less sensitive to chroma errors than luma errors. The fringing that defined the Amiga HAM aesthetic — the colour bleeding at transitions — drops to the point of invisibility. At 4K native, it simply isn't there.
HAM24 is a per-layer property. The Copper can switch it mid-frame. A HAM24 photograph in the top half of the screen, a tilemap game in the bottom half, exactly as Amiga coders split between HAM and normal modes with the Copper thirty years ago.
The Palette
256 palette descriptors. Each is a base offset into a flat 16,384-entry RGBA32 palette RAM. The address space is reserved for 65,536 entries when you need to expand.
A 2-colour sprite uses 2 palette entries. A 256-colour background uses 256. Two palettes can share entries — point two descriptors at the same base offset and they share colours. Overlap them deliberately for gradient windows, sprite recolouring, shared transparency. The hardware just does the addition. One adder. Essentially free.
The palette RAM has a second address window that presents the same data in HSV. Write hue, saturation, value — the hardware converts to RGB before storing. Read from the HSV window — the hardware converts back. The RAM always holds RGB. HSV is a view.
This means palette rotation, hue shifting, and brightness cycling are single-register writes. The Copper can shift the entire palette around the colour wheel every scanline. Raster bar effects, colour cycling, team colour swaps — all trivial.
The CRT Simulation
This is where it gets personal.
FireStorm applies CRT simulation in the output pipeline — after pixel replication, before the encoder — independently on each output. Main HDMI can run one mode, retro VGA another. Simultaneously.
The simulation pipeline has six stages: bloom pre-pass at native resolution, pixel replication, row brightness mask (scanlines), column brightness mask (pixel boundaries), phosphor aperture mask, and final blend. Every stage is configurable. Every stage can be bypassed.
Seven named monitor profiles are built in:
Commodore 1084S — warm shadow mask, thick scanlines, medium bloom. The C64 in your bedroom, 1987.
Philips CM8833 — tighter shadow mask, sharper scanlines, cooler colour temperature. The Amiga demo scene monitor. If you had one of these you were serious.
Sony Trinitron — aperture grille, vertical RGB stripes, thin damper wires at a third and two-thirds of screen height. Saturated, sharp, slightly clinical. The professional's choice.
Sony PVM/BVM — Trinitron technology, broadcast-grade electronics. Razor scanlines, minimal bloom, clinically accurate. The monitor that makes pixel art look like the artist intended. The one the retro gaming community obsesses over.
Mitsubishi Diamondtron — Trinitron's warmer rival. Slightly wider stripe pitch, slightly more glow. The monitor you had if you couldn't find a Trinitron and secretly liked it better anyway.
Generic SCART TV — wide shadow mask, heavy bloom, the warm fuzzy softness of a 28-inch Matsui in the front room. Not accurate. Not sharp. Exactly how most people actually experienced these games.
JAMMA Arcade — slot mask, seven-eighths fill, hard-driven phosphors, a whisper of green tint. The fish and chip shop at the end of the road.
Call display.setMode("pvm") from your application. That's it. DeMon handles the rest.
Tate Mode
One more thing. A single bit in the simulation register rotates the entire CRT pipeline 90°. The dark gaps between scanlines run vertically instead of horizontally. The phosphor mask transposes. The bloom is unaffected.
This is Tate mode — named from the Japanese 縦 (tate, vertical). It exists for vertical arcade games on a horizontal screen. A shoot-em-up, a platformer, Donkey Kong. Pillarboxed on a widescreen display, with rotated CRT simulation active, it looks like a real upright arcade cabinet rather than a game squeezed into a letterbox.
At 4K, two Tate mode games fit side by side in a perfect 50/50 split. The 270×480 native resolution — tall pixels, PAR 1:2 — gives exactly 1920 output pixels per half. Two completely independent vertical games, each with their own layers, sprites, palettes, and rotated scanline simulation, composited on one screen by one Ant64.
display.setMode("tate_arcade") — left game. display.setMode("tate_arcade") — right game. Different X offsets. That's it.
VGA — The Retro Crown
The retro VGA port is the output people don't see coming — a DE-15 socket and a 3.5 mm audio jack on a modern FPGA computer, and what comes out of them is sharper, cleaner, and more flexible than anything a 90s machine ever produced.
8-bit-per-channel analogue from a real DAC. The AG6201 bridge chip has an integrated 24-bit RGB DAC fed from the FPGA's HDMI stream. 0.7 Vpp into 75 Ω, properly back-terminated, AC-coupled at the chip — textbook VGA signal levels with modern signal integrity. None of the 4-bit / 5-bit / 6-bit-per-channel compromises retro machines were stuck with. Full 8-bit channel depth, every gradient as smooth as the source.
Audio in the same stream. The 3.5 mm jack carries stereo line-out decoded from HDMI audio-island packets by the AG6201's embedded audio DAC. ~1 Vrms into a 10 kΩ load. Because video and audio travel in the same HDMI stream clocked off the same pixel-clock domain, they're inherently locked together — no drift, no resync, no separate audio clock on the host side. A standard "VGA + 3.5 mm" combo cable carries both to a projector or capture card. SCART adapters carry both to a CRT TV.
Mode flexibility no native-VGA machine could match. The AG6201 happily accepts modelines from low-rate VGA standards (640×480p60 floor) up through 1080p60 ceiling, plus anything in between with reasonable pixel clocks. The output is whatever the FPGA's HDMI TX feeds it — including the modes a contemporary "retro" machine couldn't produce because their hardware was locked to fixed pixel clocks. You can run a 1024×768 productivity mode on this port to a Sun monitor. You can run a 1080p widescreen mode to a flat-panel VGA monitor. You can run 240p to a CRT TV. Same port, same chip, just different modelines from the FPGA.
240p superresolution to genuine 15 kHz CRTs. This is the killer feature, borrowed in spirit from MiSTer Direct Video. The AG6201 will faithfully reproduce a 1440×240p60 (or 1440×288p50) mode at ~27 MHz pixel clock, output through the DE-15 at 15.734 kHz horizontal / 59.94 Hz vertical — a signal a real PVM or BVM will lock to as 240p. Run it through a passive HDMI-to-SCART adapter and a SCART-input TV sees authentic 240p / 288p. Run it through component breakout and a component-input TV sees the same. The pixel grid the original consoles drew on, with none of the broadcast-monitor scarcity problems modern retro gamers face.
The whole VGA-plus-audio path costs the FPGA fabric about 12 pins (4 TMDS pairs + HPD + DDC I²C ± audio mute) and the BOM about £1.50 (AG6201 in volume, plus connectors and passives). For something that takes the system from "modern FPGA with HDMI" to "the kit that drives every retro CRT in your collection from the same connector," it's a remarkable cost.
There's no FPGA-side DAC, no 5-bit-per-channel quantisation trick, no temporal dithering pattern smearing the gradient over four frames. The DAC is a real 8-bit linear DAC inside the AG6201, the signal is a clean modern HDMI stream until it leaves that chip, and the analog path from there onwards is the cleanest in the device's history.
The Numbers
| Native resolutions | 480×270 Standard (Amiga low res equivalent), 960×540 Hires (Amiga hires equivalent), and many others — axes independent |
| Main HDMI | 4K @ 60 Hz HDMI 2.0 (DP→HDMI via Parade PS176); HDCP, CEC, deep colour |
| Retro VGA + audio | DE-15 VGA + 3.5 mm TRS stereo audio via AG6201 HDMI→VGA bridge; 480p–1080p60, 240p superresolution for genuine 15 kHz CRTs |
| Palette RAM | 16,384 RGBA32 entries, 256 descriptors |
| Palette access | Dual window: RGBA and HSV |
| HAM mode | HAM24 — 12bpp, 8-bit channel precision, RGB or YCbCr |
| Sprite budget | Hundreds per scanline at 380MHz BSRAM |
| Scroll system | Per-tile-row H (Copper), per-tile-column V (register file, configurable step) |
| CRT profiles | 7 named monitors, all parameters individually overridable |
| Copper | General register-write engine — any register, any beam position |
| CPU display cost | Zero — FireStorm handles all composition autonomously |
What the Amiga Taught Us
The Amiga was great not because of its specs — though those were remarkable for 1985 — but because of its philosophy. The hardware trusted the programmer. The Copper trusted you to know what you were doing. The custom chips did real work so the CPU didn't have to. You could feel the machine under your hands.
Modern machines have forgotten this. They hide their hardware behind seventeen layers of abstraction, drivers, APIs, and operating systems that get between you and the metal. The result is powerful and impenetrable.
The Ant64 remembers. It's not a retro machine. It runs a modern RISC-V CPU, a 138K-LUT FPGA, and AntOS — a real operating system with networking, scripting, and a proper filesystem. But it thinks the way the Amiga thought. The hardware works for you. The display system does the heavy lifting. The Copper is yours.
You write a Copper list. The beam follows your instructions. The screen does what you tell it.
Just like it used to.