Am 7. September 2026 stellte nand2mario zSST vor, eine in SystemVerilog geschriebene Implementierung der 3dfx Voodoo Graphics, auch SST-1 genannt. Das Projekt entstand nach einem Monat Arbeit an z486_MiSTer und aus dem Interesse an den 3D-Karten, die auf die erste Hälfte der 1990er folgten. Need for Speed II SE lieferte den ursprünglichen Anstoß, mit texturierten Bildern, Nebel und flüssiger Darstellung.

Glide triangle API
void grDrawTriangle(const GrVertex *a, const GrVertex *b, const GrVertex *c);

zSST ist mit der z486-CPU und den übrigen PC-Komponenten in z486 XL verbunden. So entsteht ein DOS-PC mit Voodoo-Grafik in der programmierbaren Logik eines Xilinx-KV260-Boards. Tomb Raider läuft mit seinem originalen 3dfx-Renderer. zSST unterstützt vorbereitete Dreiecke, Texturfilterung, Mipmapping, Tiefen- und Alpha-Tests, Nebel, Blending, Dithering, Framebuffer-Zugriffe und Buffer-Wechsel. Die Implementierung akzeptiert Fixed-Point- und Floating-Point-Setup-Schnittstellen. Die Hardwaretests konzentrieren sich derzeit auf Tomb Raider. Eine breitere Kompatibilität und spätere Voodoo-Generationen sind noch offen.

CPU und Renderer laufen auf dem KV260 mit 100 MHz. Logik, DSP-Blöcke, On-Chip-Speicher und DDR-Bandbreite des Boards reichen für das Gesamtdesign. Das DE10-Nano bietet keinen ausreichenden Platz für die Grafikerweiterung. Das KV260 verwendet sein integriertes DDR und benötigt kein externes SDRAM-Modul.

Als Verhaltensvorlage dienen der 1999 veröffentlichte Glide-Quellcode von 3dfx und die SST-1-Spezifikation. 3dfx veröffentlichte Glide vor der Übernahme seiner zentralen Grafik-Assets durch NVIDIA im Dezember 2000. Der erhaltene Glide-Code, die Spezifikation, 86Box, ältere Voodoo-Arbeiten in MAME und Traces aus SpinalVoodoo lieferten Referenzen und Testdaten. Die Spezifikation beschreibt Registerverhalten und Ausgabe, legt den ursprünglichen Schaltungsaufbau jedoch nicht fest.

Der Beschleuniger besitzt fünf zentrale Kommando-Register. triangleCMD startet ein vorbereitetes Dreieck, ftriangleCMD nutzt die Floating-Point-Setup-Schnittstelle, nopCMD leert die Pipeline und kann Statistikzähler zurücksetzen, fastfillCMD löscht ein begrenztes Farb- oder Tiefenrechteck und swapbufferCMD wechselt den angezeigten Buffer sofort oder beim vertikalen Retrace. Weitere Register enthalten Koordinaten, Gradienten und den Renderzustand. Speicherbereiche übernehmen Textur-Uploads und direkten Framebuffer-Zugriff.

Der Glide-Aufruf grDrawTriangle erhält drei Vertices, nachdem die Host-CPU die Geometrie transformiert, die Beleuchtung berechnet, das Ergebnis geclippt und auf den Bildschirm projiziert hat. Die SST-1 besitzt keine Hardware für Transform und Lighting. Der Rasterizer bestimmt die Pixel innerhalb des Dreiecks und interpoliert Farbe, Tiefe und Texturkoordinaten. Die Textureinheit liest und filtert Texel. Der Framebuffer-Pfad führt Sichtbarkeitstests, Nebel und Blending aus und schreibt das Ergebnis.

Die originale Voodoo teilt diese Arbeit zwischen Frame Buffer Interface, kurz FBI, und Texture Mapping Unit, kurz TMU. Bei 50 MHz liegt die angegebene Spitzenleistung bei einem texturierten, tiefengeprüften Ausgabepixel pro Takt, also 50 Millionen Pixeln pro Sekunde. Mehrere Pixel durchlaufen gleichzeitig verschiedene Stufen. Ein einzelnes Pixel braucht mehrere Stufen bis zum Abschluss. Bei gefüllter Pipeline kann pro Takt ein Pixel angenommen werden, sofern der Speicher nachkommt. Das trug zu Voodoo-Spielen mit 30 FPS oder mehr bei.

Software kann Gleitkommawerte übergeben, während der größte Teil der Renderstrecke Fixed-Point-Arithmetik nutzt. Die internen Formate sind 12.4 für Bildschirm-X und -Y, 12.12 für Rot, Grün, Blau und Alpha, 20.12 für die Tiefe Z, 14.18 für Textur-S/W und T/W sowie 2.30 für das reziproke W. Die Register fvertex, fstart und die Floating-Point-Gradienten akzeptieren IEEE-Single-Precision-Werte. SST-1 wandelt sie in diese Fixed-Point-Formate um. Die Interpolation arbeitet danach überwiegend mit vorab berechneten Additionsschritten.

Für perspektivisch korrekte Texturen interpoliert die TMU S/W, T/W und 1/W und dividiert die ersten beiden Werte durch den dritten. Sie wählt eine Mipmap-Stufe und führt bilineare Filterung mit vier benachbarten Texeln aus. zSST nutzt für Perspektive und Level of Detail eine Frontend-Pipeline mit vier Stufen. Adressberechnung, Cache-Zugriff, Formatdekodierung und Texture Combining unterstützen palettenbasierte und NCC-kodierte Texturen.

Der FBI-Pixelpfad besitzt sechs registrierte Stufen. F0 wählt Quellen aus, prüft den Chroma-Key und bereitet Z/W-Werte vor. F1 führt Farb- und Alpha-Combine-Funktionen aus. F2a testet Alpha und Tiefe und liest den Nebelfaktor nach. F2b wendet den Nebel an. F3 rekonstruiert die Zielfarbe und führt Alpha-Blending aus. F4 wandelt in die Framebuffer-Präzision um, dithert und setzt Schreibmasken. Die Aufteilung erfüllt das FPGA-Timing und erhält den Durchsatz von einem Pixel pro Takt.

Der Speicherzugriff war die zentrale Implementierungsarbeit. Die originale Voodoo gibt FBI und TMU eigene 64-Bit-Speicherpfade. Eine vierfache Interleaving-Struktur verteilt Texturen nach der geraden oder ungeraden Parität von Spalte und Zeile. Dadurch gelangen die vier Texel eines 2x2-Fensters parallel aus den vier Bänken. Der FBI verwendet eine ähnliche Anordnung für Farb- und Tiefen- oder Alpha-Daten. Der Spitzenwert liegt bei einem gerenderten Pixel pro Takt und bei zwei Pixeln pro Takt für Löschvorgänge. Bei 50 MHz bietet jeder 64-Bit-Pfad theoretisch 400 MB/s, zusammen 800 MB/s. Beide Pfade bleiben ihren jeweiligen Aufgaben zugeordnet.

Beim KV260 liegt DDR-Speicher hinter AXI-Ports. Linux, der FPGA-PC und die Display-Ausgabe greifen auf denselben Speicher zu. Ein 128-Bit-Port mit 100 MHz bietet theoretisch 1,6 GB/s. Messungen ergaben bei einer ausstehenden Anfrage 1.370 MiB/s für einen 4-KiB-Lesezugriff und 189 MiB/s für 64 Byte. Die ersten Daten trafen typischerweise nach etwa 280 ns ein, also nach rund 28 Takten bei 100 MHz. Gelegentlich dauerte es länger.

zSST verwendet einen 8-KiB-Texturcache mit 64-Byte-Lines. Bis zu acht Cache-Line-Ladevorgänge können gleichzeitig offen sein. Fehlende Daten landen in einer Replay-Warteschlange. Ein Reorder Buffer mit 64 Einträgen gibt fertige Samples in ihrer ursprünglichen Reihenfolge weiter. Für den Framebuffer gibt es getrennte 4-KiB-Caches für Farbe und Tiefe oder Alpha. Write Combiners bündeln benachbarte 16-Bit-Änderungen zu 128-Bit-Anfragen. Forwarding erhält Abhängigkeiten, wenn ein späterer Tiefen- oder Blend-Vorgang einen von einem früheren Pixel geänderten Wert benötigt. FBI und TMU teilen den Renderer-Port HP2. Der PC nutzt HP0, die Display-Ausgabe HP3.

Die Simulation bildet DDR-Timing, TMU, FBI, gemeinsame Arbitration und das Frontend ab. Lesedaten kommen frühestens nach 26 Takten, Schreibvorgänge sind begrenzt, und die vollständigen Render-Tests erlauben 32 ausstehende Lesezugriffe. Bei 100 MHz erreicht zSST 78,5 MPix/s bei texturierten Dreiecken und 72,8 MPix/s mit Tiefentest und Blending. Veröffentlichten Schätzungen für Voodoo 1 bei 50 MHz zufolge sind es bei vergleichbaren Funktionsgruppen 43 beziehungsweise 37 MPix/s. Die Workloads unterscheiden sich. Die Werte zeigen daher eine ungefähre Größenordnung und keinen gemessenen Geschwindigkeitsvorteil.

Auf dem Board erzeugte Tomb Raider Level 2 in etwa 20 Sekunden 237 angezeigte Buffer-Wechsel, also ungefähr 12 pro Sekunde. Gezählt wurden Buffer-Wechsel, kein FPS-Zähler der Engine. Erste Messungen deuten auf die CPU als Hauptlimit hin. Auch die gemeinsame DDR-Nutzung kann beitragen. Das 100-MHz-z486-XL erreicht Doom mit maximalen Details bei 38,5 FPS und Quake 1.06 bei 8,1 FPS. Das liegt ungefähr 20 Prozent über dem 85-MHz-Build für DE10-Nano. Die Zuwächse betragen bei Doom etwa 23 Prozent und bei Quake 19 Prozent. Ein 512-KiB-Write-Back-L2-Cache in UltraRAM unterstützt die CPU beim DDR-Zugriff.

Im integrierten XCK26-Build belegt zSST etwa 29.500 LUTs, 28.100 Flip-Flops, 14 RAMB36-Blöcke, 8 RAMB18-Blöcke und 97 DSP-Slices. Das kombinierte PC- und Grafikdesign erreicht bei 100 MHz das Timing. zSST und z486 XL sind Open Source. Das Release z486_XL_20260906 von z486 XL enthält Linux-Unterstützung und die Anwendung zum Starten eigener DOS-Disk-Images auf einem KV260. Für Glide-Traces und Referenzbilder nennt das Projekt SpinalVoodoo als Quelle, für Implementierungsreferenzen 86Box. Fabien Sanglards Analyse des Voodoo-1-Speichers dient als zusätzliche Einführung.