Was sind FPGA? Wie gehe ich als Entwickler damit um? Field Programmable Gate Arrays haben ihren Namen daher, dass sie “im Feld”, also im Einsatz, fest verbaut im Gerät programmiert werden können; oder umgekehrt gesagt: Ohne Löschgerät und ohne spezielle Programmierspannungen. Sie gehören zu den PLD, und ähneln sie PALs oder GALs; sind aber komplexer und können umfangreichere Aufgaben übernehmen. Entsprechend programmiert können sie Aufgaben von Prozessoren und ihrer Peripherie übernehmen. Ihre Größe wird typischerweise in logischen Einheiten bzw. logical Units LU angegeben. Um eine Vorstellung davon zu bekommen, was diese leisten, kann man schätzungsweise annehmen, dass 20.000 LU ausreichen, um eine 16-Bit-CPU mit Peripherie abzubilden. Man könnte damit also beispielsweise einen klassischen Homecomputer nachbauen. Das wird hier beschrieben:
Vortrag auf dem 38C3 2024 in Hamburg
Hier ein kleines Tutorial für den Einstieg:
Man besorgt sich so einen FPGA auf einem Entwicklungsboard. In meinem Fall ist es ein SiPeed Tang Primer 20k auf dem Lite-Board. Neben dem eigentlichen FPGA, einem GoWin GW2A, erhält man noch RAM und EEPROM und einen Taktgeber und dazu noch Pin-Header wie man sie vom Arduino oder Raspberry gewohnt ist.
Auf dem eigentlichen FPGA-Board, welches wie ein RAM-Riegel aussieht, ist eine kleine weiße Buchse. Dazu bekommt man passend einen Stecker mit Kabeln. Diese werden passend zur Beschriftung auf den Platinen in die Pin-Header eines kleinen Boards namens RV Debugger Plus mit USB-Buchse gesteckt. RX und TX werden über Kreuz verbunden, die anderen 1:1. Danach steckt man die RAM-artige Platine in die größere Lite-Platine mit den Pin-Headern.
Steckt man nun das USB-Kabel am Rechner an, wird das Board laut lsusb wie folgt erkannt:
$ lsusb
…
Bus 002 Device 005: ID 0403:6010 Future Technology Devices International, Ltd FT2232C/D/H Dual UART/FIFO IC
…
Der Hersteller liefert dazu eine IDE, die auch für Linux verfügbar ist. Man kann ein kleines Tutorial vom Hersteller durcharbeiten, um eine LED zum Blinken zu bringen. Dazu wird von Pin L14 an einem der PMOD-Interface eine LED gegen Masse geschaltet. Die LED blinkt auch ohne Programmierung, weil das schon im herstellerseitigen Test-Programm so hinterlegt ist. Hier ist ein kleiner Film, wie das Ganze dann ausschaut.
Das Tutorial arbeitet man durch, bis die sogenannte Synthese den eigentlichen Code für das FPGA erzeugt hat. Ein Entwickler würde vielleicht lieber Compilieren sagen, aber der Begriff Synthese hat sich bei FPGA eingebürgert; vermutlich auch um deutlich zu machen, dass hier eben kein Programm erzeugt wurde, sondern eine Art Netzliste zur “Verdrahtung” von Logik-Bausteinen.
Nun braucht man noch ein externes Programm, um den Code auf das FPGA zu kopieren. Die IDE bietet die Funktion zwar an, aber der Hersteller sagt selbst, dass das unter Linux nicht zuverlässig funktioniert. Stattdessen wird der openFPGALoader empfohlen, den es als Paket bei Debian gibt
https://packages.debian.org/trixie/openfpgaloader
Im Verzeichnis des Projekts findet man im Unterverzeichnis impl/pnr eine .fs-Datei, die man mit openFPGALoader auf das FPGA kopiert.
$ openFPGALoader -b tangprimer20k LED.fs
Jtag frequency : requested 6.00MHz -> real 6.00MHz
Parse file Parse LED.fs:
Done
DONE
Jtag frequency : requested 2.50MHz -> real 2.00MHz
erase SRAM Done
Flash SRAM: [==================================================] 100.00%
Done
Beschreibt man das FPGA auf diese Weise, wird nur die Logik selbst programmiert. Diese verhält sich wie RAM. Das hat den Vorteil, dass es sich nicht “abnutzt”. Es gibt keine maximale Anzahl von Schreibvorgängen, nach denen der Chip kaputt ist. Man kann also nach Belieben damit testen. Mit der Option -f wie flash kann man auch das EEPROM beschreiben. Das übersteht dann auch einen Neustart der Stromversorgung, hat aber eben umgekehrt nur eine bestimmte “Lebensdauer” an Schreibvorgängen.
Nun kann man in der IDE ein paar Dinge ausprobieren, um die LED anders blinken zu lassen, sodass man auch sieht, dass das eigene Programm etwas gegenüber dem Default bewirkt hat. Bei der Programmierung von FPGA muss man beachten, dass wir hier eine Ebene abstrakter sind als bei der Programmierung einer CPU. Wir programmieren hier die Logikbausteine, die der CPU sagen, was sie tun soll. Ein Vorteil der freien Konfiguration der FPGA ist beispielsweise, dass man die Größe von Registern auf das Bit genau festlegen kann. Wenn mir die 24 Bit aus dem Tutorial für meinen Teiler nicht reichen, schreibe ich da einfach eine andere Zahl rein. Mit einem Aufbau in Hardware wäre das wohl nicht so einfach.
Genau wie auch beim “normalen” Programmieren muss man nicht alles selbst machen. Es gibt große Bibliotheken, in denen viele Dinge bis hin zu kompletten CPUs angeboten werden; auch andere Logik-Bausteine wie die ULA des Sinclair Spectrum sind erhältlich. Zu beachten ist dabei, dass FPGA sehr unterschiedlich sind, nicht nur bezüglich der Größe in LU. Die meisten modernen FPGA bieten viele spezielle Logikbausteine wie fertige PLL oder DSP an, deren Benutzung nicht ohne weiteres von einem Typ auf einen anderen übertragen werden kann.
Zusammengefasst sind FPGA eine großartige Möglichkeit, digitale Signale sehr flexibel zu verarbeiten.