Diese Seite ist die vierte in einer Reihe von fünf Seiten darüber, wie du ein professioneller FPGA-Designer wirst. Diesmal gehe ich einige Fähigkeiten durch, die für den Anfang weniger wichtig sind. Ich beginne damit zu erklären, warum es überhaupt Sinn ergibt, das zu tun.
Warum etwas Unwichtiges erwähnen?
Es mag etwas seltsam erscheinen, eine Seite über Fähigkeiten zu schreiben und gleichzeitig zu sagen: „Nun ja, das ist nicht so wichtig.“ Aber in dieser Reihe geht es nicht darum, dass ich dir sage, was du tun sollst. Vielmehr versuche ich zu erklären, warum jedes Thema wichtig ist (oder nicht so wichtig). Es ergibt also Sinn, dasselbe auch für die weniger wichtigen Themen zu tun.
Manche praktischen Fähigkeiten sind oft nützlich, aber überbewertet. Das sind Fähigkeiten, die du irgendwann einmal erwerben musst, aber es besteht auch die Chance, dass du sie nie brauchen wirst. Der Grund, warum ein Thema überbewertet sein kann, ist, dass es oft in Beispielprojekten für Platinen auftaucht. Nicht weil es wichtig ist, sondern weil es relativ einfach ist, mit einer bestimmten Technik eine schöne und beeindruckende Demo zu machen.
Um es klarzustellen: Alle unten genannten Fähigkeiten sind nützlich. Es ist nur so, dass sie oft nach Bedarf erworben werden, um an einem Projekt zu arbeiten, zusammen mit einer ganzen Reihe anderer technischer Themen, die für die Anforderungen dieses Projekts spezifisch sind.
I2C und SPI
Du kannst dein ganzes Leben als FPGA-Designer arbeiten, ohne etwas über diese beiden zu wissen. Aber realistisch gesehen besteht eine gute Chance, dass du ihnen in deiner praktischen Arbeit recht bald begegnest.
I2C (IIC, Inter-Integrated Circuit), Protokolle, die ihm sehr ähnlich sind, und SPI (Serial Peripheral Interface) sind mit Abstand die gebräuchlichsten Standards, um Daten zu und von einer elektrischen Komponente auf einer Platine zu übertragen. Sie basieren auf einer Master-/Slave-Konfiguration, bei der der Master eine Lese- oder Schreiboperation einleitet und der Slave möglicherweise darauf antwortet. In den meisten Fällen ist der Master ein Prozessor oder eine relativ anspruchsvolle Komponente, und der Slave ist eine einfachere Komponente mit einer peripheren Funktion im elektronischen Design.
I2C und davon abgeleitete Protokolle haben eine sehr niedrige Datenrate (üblicherweise um 100 kbit/s) und werden hauptsächlich zum Konfigurieren der Parameter einer Komponente verwendet. Wenn die Komponente zum Beispiel ein A/D-Wandler ist, kann I2C verwendet werden, um auszuwählen, welche Spannungsreferenz die Komponente verwenden soll und ob ihre Ausgabe als Ganzzahl mit oder ohne Vorzeichen ausgegeben werden soll. Der Hauptvorteil dieses Protokolls ist, dass die Verbindung nur aus zwei Drähten besteht: Takt (SCL) und Daten (SDA). Es gibt auch eine Verbindung zu Masse (GND), aber das geschieht üblicherweise über die gemeinsame Masse der Platine und erfordert praktisch nie einen separaten Draht.
Das Protokoll ist tatsächlich ein Bus, sodass jeder Datenaustauschzyklus eine 7-Bit-Adresse enthält. Folglich können mehrere Komponenten parallel an dieses Drahtpaar angeschlossen werden. Jede Komponente muss in diesem Fall eine andere Adresse haben.
Der I2C-Standard wurde ursprünglich von Philips patentiert. Weil er so nützlich war, werden häufig eine Reihe verblüffend ähnlicher Varianten verwendet, zum Beispiel SMBus, PMBus und DDC2. Diese Standards übernehmen die Grundideen von I2C, haben aber leicht abweichende Parameter (insbesondere Datenraten) und Hauptanwendungsszenarien. Zum Beispiel haben alle heute verkauften Computermonitore einen kleinen Flash-Speicher, der Informationen darüber enthält, welche Grafikmodi sie unterstützen. Das Kabel zwischen der Grafikkarte im Computer und dem Monitor hat zwei Drähte, die mit diesem Flash-Speicher verbunden sind. Dadurch kann die Grafikkarte die Daten in diesem Speicher mit dem DDC2-Protokoll lesen, das im Wesentlichen dasselbe ist wie I2C.
Wenn du also I2C verstehst, weißt du, wie eine Menge verschiedener Komponenten miteinander kommunizieren.
Kommen wir zu SPI. Dieses Protokoll erfordert üblicherweise vier Drähte zwischen den Master- und Slave-Komponenten (SCLK, MOSI, MISO, SSn). Manchmal wird dieses Protokoll zum Konfigurieren einer Komponente verwendet, genau wie I2C und seine Varianten. Der Hauptverwendungszweck von SPI ist jedoch die Übertragung von Daten mit höheren Datenraten. Es ist nicht ungewöhnlich, dass Komponenten eine SCLK-Frequenz von 20–50 MHz unterstützen, sodass es ein praktisches Protokoll zur Übertragung von Anwendungsdaten ist. Ein A/D-Wandler für zwei Audiokanäle erzeugt zum Beispiel 48.000 Hz × 2 × 16 Bit = 1,536 Mbit/s. Diese Datenrate ist für SPI kinderleicht. Und tatsächlich gibt es mehrere Audio-Chips, die SPI zur Übertragung von Samples verwenden.
Erwähnenswert ist auch, dass die Verbindung zwischen dem FPGA und dem Flash-Speicher, aus dem es seinen Bitstrom (bitstream) liest, oft QSPI ist. Diese Schnittstelle ist genau wie normales SPI, aber mit vier Datenleitungen statt einer, wodurch die Datenübertragung schneller wird.
Also zur abschließenden Frage: Solltest du I2C und SPI als Teil davon, ein FPGA-Designer zu werden, lernen? Meine Meinung ist, dass sie für sich genommen nichts mit FPGA-Design zu tun haben. Aber wenn du in einem kleinen Team an der Entwicklung eines elektronischen Produkts arbeitest, ist die Wahrscheinlichkeit hoch, dass du eine der Komponenten mit I2C konfigurieren musst. Oder eine der mit dem FPGA verbundenen Komponenten verwendet SPI zur Kommunikation. Oder du verwendest vielleicht den Flash-Speicher, der den Bitstrom des FPGA enthält, direkt aus deiner eigenen Logik.
Es gibt viele Anwendungsfälle für diese beiden Protokolle, aber das Wichtigste ist, sie und ihre Varianten zu erkennen, wenn sie in Datenblättern auftauchen. Oft verwendet eine Komponente eines dieser Protokolle, nennt aber seinen Namen nicht ausdrücklich. Wenn du die Prinzipien hinter I2C kennst, kannst du es nicht übersehen, wenn das Datenblatt eine ähnliche Schnittstelle beschreibt. Dasselbe gilt für SPI.
Und wenn du in einem Bewerbungsgespräch sitzt und behauptest, ein erfahrener FPGA-Designer zu sein, aber nichts über diese beiden Protokolle weißt, ist das vielleicht nicht so beeindruckend.
Und hier noch ein Vorschlag für ein Projekt, um etwas Erfahrung zu sammeln: Es ist ziemlich einfach, einen günstigen Temperatursensor oder eine andere Art einfacher Komponente zu finden, die I2C oder eine seiner Varianten verwendet. Kaufe so eine Komponente und verbinde sie mit Dupont-Kabeln oder einer anderen gebastelten Methode mit deiner FPGA-Platine. Schreibe dann alles von Grund auf selbst, was nötig ist, um über I2C mit ihr zu kommunizieren. Wenn du ein Oszilloskop hast, nutze es, um die Signale zu beobachten. Das könnte dein erstes Do-it-yourself-Projekt sein.
Block Design
Die meisten FPGA-Design-Werkzeuge bieten die Möglichkeit, Logikdesign-Blöcke über eine grafische Oberfläche zu verbinden. Im Prinzip ist die Verwendung dieser Oberfläche ziemlich gleichbedeutend mit dem Instanziieren (instantiation) von Modulen in Verilog. Die grafisch gezeichneten Drähte sind wie Portverbindungen in Verilog. Ein Block-Design-Werkzeug bietet oft noch ein paar weitere Möglichkeiten, zum Beispiel das automatische Einfügen kleiner Logikstücke, die sicherstellen, dass die in der GUI hergestellten Verbindungen das tun, was der Benutzer beabsichtigt hat.
Die Block-Design-Methode ist am besten, wenn alle oder die meisten Blöcke vom FPGA-Hersteller geliefert werden (in Form von IP-Blöcken, IP cores). Insbesondere wenn ein Prozessor beteiligt ist, ist ein Block Design üblicherweise die natürliche Art, ihn mit IP-Blöcken zu verbinden, die periphere Funktionen umsetzen: Interrupt-Controller, DMA-Controller, Bus-Arbiter usw. Es gibt auch eher „klassische“ Peripheriegeräte, zum Beispiel Ethernet-Controller.
Abgesehen von den offensichtlichen prozessorbezogenen Blöcken gibt es auch eine große Auswahl an IP-Blöcken, die eine breite Palette von Funktionen umsetzen, die üblicherweise in einem FPGA implementiert werden. Diese reichen von FPGA-Elementen wie Taktressourcen und Logik neben I/O-Pins über einfache arithmetische Einheiten bis hin zu digitalen Filtern und noch komplexerer Logik. Es sieht so aus, als wäre die Idee gewesen, es möglich zu machen, ein komplettes FPGA-Design nur mit einem Block Design zu erstellen.
Trotzdem habe ich noch nie von jemandem gehört, der mit diesen vorgefertigten IP-Blöcken allein ein sinnvoll nutzbares FPGA-Projekt gebaut hätte. Außer einem Projekt, das nur aus einem Prozessor und seiner Peripherie besteht, aber wenn du nur einen Prozessor willst, warum verwendest du dann ein FPGA? Das ist viel teurer und komplizierter.
Aber ein komplettes Block Design kann, und wird üblicherweise, in einem Verilog-Modul instanziiert (instantiation), genau wie jedes andere Verilog-Modul oder IP. Dementsprechend ist das Block Design üblicherweise Teil eines größeren, Verilog-basierten Projekts. In diesem Zusammenhang ergibt ein Block Design, das nur einen Prozessor und seine Peripherie enthält, Sinn: Es ist einfach ein Modul innerhalb eines größeren Projekts.
Was bedeutet das also im Hinblick auf Fähigkeiten, die du lernen solltest oder vielleicht besser nicht?
Die einfachste Fähigkeit ist, Block Designs zu erstellen, Blöcke hinzuzufügen und sie zu verbinden. Es gibt reichlich Tutorials, die dir sagen, wann du was anklicken musst. Da diese Tutorials so leicht zu befolgen und abzuschließen sind, warum nicht ein oder zwei davon durchlaufen? Und wenn du das tust, mach dir nicht die Mühe, jeden Schritt und jede Auswahl, die im Laufe des Prozesses getroffen wird, zu verstehen. Der Punkt ist, ein Gefühl dafür zu bekommen, wie Block Design gemacht wird. Tauche in die Details ein, wenn und falls das relevant wird.
Die nächste Fähigkeit ist, ein Block Design in ein Projekt einzubinden und es in einem Verilog-Modul zu instanziieren (instantiation). Das ist ebenfalls recht einfach, und es gibt viele Beispiele dafür. Es unterscheidet sich nicht davon, irgendein IP in deinem Projekt zu verwenden. Wenn du weißt, wie man ein FIFO-IP in seinem Verilog-Projekt verwendet, weißt du auch, wie man dasselbe mit einem Block Design macht.
Die bedeutendste Fähigkeit ist, etwas, das du in Verilog geschrieben hast, in einen Block zu verwandeln, der in einem Block Design verwendet werden kann. Und noch bedeutender: diesen Block mit Vivados eigener GUI konfigurierbar zu machen (oder mit welcher Entwicklungssuite du auch immer arbeitest). Ich würde nicht empfehlen, das zu lernen, es sei denn, es gibt einen direkten Zweck dafür. Die meisten FPGA-Designer müssen nie etwas dieser Art tun.
Was ist also die Quintessenz? Wie bei jedem GUI-Werkzeug: Spiele ein bisschen damit herum und lerne dann schrittweise so viel, wie du brauchst, um eine Aufgabe zu erledigen. Erwarte insbesondere nicht, alles mit einem Block Design machen zu können, selbst wenn die Menge der verfügbaren Blöcke dich zu der Annahme verleiten kann, dass das der richtige Weg ist.
Arbeiten mit Prozessoren im FPGA
Viele Projekte, insbesondere eigenständige elektronische Produkte, haben etwas Software laufen, und beinhalten daher einen Prozessor. Dieser Prozessor kann ein Block im FPGA sein oder eine separate physische Komponente außerhalb davon. Die Herausforderungen sind in jedem Fall völlig unterschiedlich.
Ich beginne mit dem Szenario des Prozessors im FPGA. Das kann ein „Hard-Prozessor“ sein, wie die in AMDs Zynq-Familie, die einen ARM-Prozessor direkt im Silizium eingebaut haben. Ein „Hard-Prozessor“ ist genau wie jedes andere Logikelement im FPGA, vergleichbar mit arithmetischen Einheiten, PLLs und Block-Speichern. Nur dass ein Prozessorblock relativ groß ist und eine ganze Menge Pins hat.
Wenn ein FPGA keinen „Hard-Prozessor“ hat, kann es trotzdem Software auf einem „Soft-Prozessor“ laufen lassen. Zum Beispiel AMDs MicroBlaze- und Alteras Nios-Prozessoren. Der Unterschied ist, dass der Prozessor mit den regulären Logikelementen des FPGA (dem „Logik-Fabric“, logic fabric) implementiert wird. Diese Methode ist langsamer, verbraucht mehr Energie und belegt Logikressourcen, aber oft ist sie gut genug und eine kosteneffiziente Wahl.
Sowohl „Hard-Prozessoren“ als auch „Soft-Prozessoren“ sind im Prinzip wie jedes Verilog-Modul, das sich genau wie jedes andere IP mit der Logik des FPGA verbindet. Es ist daher ganz natürlich, sie als Teil des FPGA zu betrachten und daher den FPGA-Designer für sie verantwortlich zu machen.
Das Einrichten des Prozessors im Logikdesign ist üblicherweise die relativ einfache Aufgabe, denn es gibt viele Beispiele und Vorlagen dafür. Aber es endet selten dort. Der Prozessor braucht bestimmte Peripheriegeräte, und diese sollten für die Software an bekannten Adressen im Speicherraum des Prozessors verfügbar sein. Die Peripheriegeräte haben oft Interrupt-Request-Ausgänge, die richtig mit dem Prozessor verbunden und korrekt konfiguriert werden müssen.
Das Softwareteam erwartet üblicherweise, dass sich jemand anderes um das Stück Software kümmert, das läuft, wenn der Prozessor hochfährt oder ein Reset-Signal bekommt. Diese Software besteht aus Routinen, die unter anderem in die eigenen Hardwareregister des Prozessors schreiben, damit er wie konfiguriert funktioniert. Das ist nicht so schwierig, wie es klingen mag, denn die Entwicklungswerkzeuge erzeugen zu diesem Zweck C-Code zur Einbindung in das größere Softwareprojekt. Aber wer ist dafür verantwortlich, diese Dateien zu erzeugen und sicherzustellen, dass sie mit dem Rest des FPGA-Designs synchron sind? In einem kleinen Entwicklungsteam ist das der FPGA-Designer.
Und wenn das nicht genug ist, kann vom FPGA-Designer verlangt werden, Peripheriegeräte für den Prozessor zu erstellen, die Logik umsetzen, die für das entwickelte Produkt spezifisch ist. Die Treiber für diese Logik in C zu schreiben, ist üblicherweise mehr als willkommen.
Also – ist das etwas, das man als Teil davon, ein FPGA-Designer zu werden, zu lernen anfangen sollte? Wenn du in der Schnittmenge zwischen Software und Hardware arbeiten willst, würde ich sagen: möglicherweise ja. Wenn du bereits ein C-Programmierer bist und Low-Level-Programmierung magst, kann das etwas für dich sein. Und insbesondere, wenn es dir nichts ausmacht, ab und zu das sehr dicke Benutzerhandbuch des Prozessors zu lesen. Hier findest du die Antwort auf „Wie kann ich zwei Einheiten von Peripherie X und drei von Peripherie Y haben?“
Welche Themen solltest du also lernen? Ich würde sagen, ein grundlegendes Verständnis davon zu erlangen, wie Prozessoren Software ausführen, wie sie auf Speicher zugreifen, wie Interrupts funktionieren und wie Prozessoren beim Einschalten starten. Sieh dir die Adressmap eines Prozessors an, schau, wie die Speicherbereiche in verschiedene Segmente unterteilt sind (On-Chip-RAM, externes RAM, interne Register, externe Bus-Zugriffssegmente usw.), und verstehe, wie das Ganze funktioniert.
Ich schlage außerdem vor, die Prinzipien der AMBA-Protokolle (AXI3, AXI4, AXI4 Lite usw.) zu verstehen, insbesondere den VALID-/READY-Handshake. Wenn du jemals ein Peripheriegerät entwirfst, ist die Wahrscheinlichkeit hoch, dass du einen AXI-Slave implementieren musst. Und selbst wenn du mit einem Prozessor arbeitest, der AXI nicht nativ verwendet (zum Beispiel Alteras Prozessoren), werden die Prinzipien dieselben sein.
Du wirst wahrscheinlich auch für die Software verantwortlich sein, die beim Hochfahren und Zurücksetzen des Prozessors läuft. Sich damit vertraut zu machen, wie diese Software erstellt wird und wie sie mit den eigenen Hardwareregistern des Prozessors zusammenhängt, könnte daher helfen. Und es ist einfacher, wenn du die Treiberroutinen für den Zugriff auf alle Peripheriegeräte schreibst, die du möglicherweise entwerfen musst. Aus diesen Gründen wirst du nicht sehr weit kommen, wenn du nicht gut in der C-Programmierung bist. Selbst wenn du die KI benutzt, um den Code für dich zu schreiben, musst du genau verstehen, was dieser Code tut.
Aber über allem: Sei dir bewusst, dass du nicht viel lernen wirst, wenn du ein langes Beispielprojekt durchläufst, in dem du einen Prozessor konfiguriert und geklickt, geklickt, geklickt hast und am Ende etwas sehr Beeindruckendes auf deiner Platine passiert ist. Alles Wertvolle, was es zu lernen gäbe, wurde bereits für dich erledigt, und du hast die wichtigen Teile übersprungen, während du dich zur letzten Zeile geklickt hast. Wenn in einem solchen Beispielprojekt irgendetwas Wertvolles steckt, dann ist es das, was danach passiert: Was hast du aus dem Beispiel verstanden? Was kannst du im Projekt ändern? Was kannst du selbst ausprobieren?
Arbeiten mit Prozessoren außerhalb des FPGA
Ziemlich oft ist der Prozessor eine eigenständige Komponente oder Teil einer separaten Platine in einem Projekt mit einem FPGA. Es ist nicht ungewöhnlich, dass ein vollwertiger PC, entweder ein normaler Desktop oder ein industrielles x86-basiertes Mainboard, der zentrale Teil eines Produkts ist. In solchen Umgebungen ist es üblich, das FPGA als Peripheriegerät zu betrachten. Auch wenn der Zweck des FPGA von einem Projekt zum anderen variiert, wird der Prozessor (oder PC) üblicherweise als das Zentrum des Projekts betrachtet und das FPGA (und die Elektronik darum herum) als ein Teil, der von Software gesteuert und verwaltet wird.
Da der Prozessor ein separates physisches Teil ist, gibt es üblicherweise ein separates Team, das sich um alles an ihm kümmert, einschließlich der Software. Die Aufgaben des FPGA-Designers im Zusammenhang mit dem Prozessor bestehen hauptsächlich darin, mit ihm zu kommunizieren. Wenn der Prozessor nur das Verhalten des FPGA steuern soll, kann die Kommunikation nur aus Kommandos bestehen, möglicherweise durch Lesen oder Schreiben von Registern. In diesem Fall werden oft einfachere Protokolle verwendet, insbesondere I2C und SPI. Diese beiden habe ich oben bereits behandelt. SPI kann auch für den Datenaustausch mit relativ niedrigen Datenraten gewählt werden.
Erwähnenswert ist, dass I2C und SPI üblicherweise nur mit eingebetteten Prozessoren verwendet werden. Diese Protokolle sind bei projektspezifischen Peripheriegeräten weniger verbreitet, wenn ein PC-Mainboard beteiligt ist. Auch wenn SMBus oft verwendet wird, um Lüfter zu steuern und Temperaturwerte zu erhalten, ist es weniger üblich, Protokolle dieser Art mit deinen eigenen Peripheriegeräten zu verwenden.
Bei eingebetteten Prozessoren (und DSPs) kommt es auch vor, dass die Schnittstelle zum FPGA über eine Schnittstelle erfolgt, die für den Prozessor (oder eine Prozessorfamilie eines bestimmten Herstellers) spezifisch ist. Zum Beispiel kann der Prozessor viele physische Pins haben, die mit dem FPGA verbunden sind, um über eine Adress-/Datenbus-Schnittstelle darauf zuzugreifen. Die Implementierung der Logik, die mit diesem Bus kommuniziert, erfordert ein genaues Verständnis des (nicht immer klug entworfenen) Protokolls, das vom Hersteller des Prozessors definiert wurde. Es gibt auch Timing-Anforderungen, die eingehalten werden müssen. Es hat jedoch keinen Sinn, sich auf eine solche Aufgabe vorzubereiten, da sie sich nicht von der Kommunikation mit jeder anderen externen Komponente mit einem komplizierten I/O-Protokoll unterscheidet.
Die Kommunikation mit PCs und High-End-eingebetteten Prozessoren erfolgt üblicherweise über die PCIe-Schnittstelle (PCI Express). Das ist ein robuster und gut unterstützter Kommunikationskanal, der in seiner einfachsten Konfiguration eine Datenrate von 200 MB/s (Nutzlastdaten) ermöglicht, aber nach oben ist kaum eine Grenze gesetzt: Neue Versionen des PCIe-Protokolls erscheinen in regelmäßigen Abständen, und die Datenrate wird mit jeder neuen Version höher. Die tatsächliche Grenze der Datenrate ist oft das, was der Prozessor selbst bewältigen kann.
Der Nachteil von PCIe ist, dass es ein kompliziertes Protokoll ist, das in erster Linie für Computer-Peripheriechips gedacht ist. Es wird implizit angenommen, dass du, wenn du etwas für PCIe implementierst, spezifische Arbeitskraft für die Entwicklung der Logik für die Kommunikation mit dem Computer eingeplant hast und ebenso ein Softwareteam für die Entwicklung des Treibers. Diese Aufgabe wird deutlich einfacher, wenn Xillybus verwendet wird, da diese Lösung die Komplikation auf beiden Seiten bewältigt.
Welche Fähigkeiten solltest du also lernen, um dich auf ein Szenario mit einem externen Prozessor vorzubereiten? Vor allem anderen kann es viel helfen, wenn du gut in C-Programmierung bist, damit du die Treiberroutinen für den Zugriff auf das FPGA vom Prozessor aus schreiben kannst oder zumindest Beispielcode anbieten kannst. Die KI kann diesen Code für dich schreiben, aber wenn du kein genaues Verständnis davon hast, was der Code tut, könnte am Ende ein Bug in C herauskommen, der aussieht, als käme er vom FPGA.
Abgesehen davon gibt es nicht viel, was ich im Voraus zu lernen empfehlen würde. Die erforderlichen technischen Fähigkeiten hängen stark davon ab, wie der Prozessor und das FPGA verbunden sind, was von einem Projekt zum anderen unterschiedlich ist.
Weitere Schnittstellenstandards
Wenn du dir verschiedene verfügbare FPGA-Entwicklungsplatinen ansiehst, wirst du feststellen, dass bestimmte Komponenten und Steckverbinder tendenziell häufiger vorkommen als andere. Das kann als Hinweis darauf interpretiert werden, welche Technologien oft in einem FPGA-Projekt verwendet werden. Das ist teilweise wahr, und ich gehe ein paar davon durch.
HDMI
Ein HDMI-Steckverbinder ist oft auf FPGA-Platinen vorhanden. Der Zweck ist üblicherweise, dem FPGA zu ermöglichen, eine Videoausgabe zur Anzeige auf einem Computermonitor zu erzeugen. Die Drähte des Steckverbinders gehen oft direkt zum FPGA, da es mit Hilfe des SERDES des I/O-Blocks in der Lage ist, die erforderlichen Hochgeschwindigkeitssignale zu erzeugen. Auf manchen Platinen gibt es eine separate Komponente („Video-Encoder“) zwischen dem FPGA und dem HDMI-Steckverbinder.
Die Allgegenwart dieses Steckverbinders spiegelt tatsächlich die Realität wider: Viele FPGA-Projekte umfassen irgendeine Art von Videoverarbeitung und -ausgabe. Die FPGA-Platine mit einem Computermonitor zu verbinden und mit dieser Anordnung zu experimentieren, kann in Zukunft helfen. Lerne insbesondere die Grundlagen von VGA, wie der Bildschirm horizontal und vertikal abgetastet wird, und die verschiedenen Standard-Anzeigemodi, die es gibt. Wenn der HDMI-Steckverbinder direkt mit dem FPGA verbunden ist, kannst du versuchen, Logik zu implementieren, die die Signale erzeugt, aber ich bin nicht sicher, ob sich der Aufwand lohnt. Es ist kein einfaches Protokoll zu lernen, und wenn es nicht funktioniert, ist so ein Projekt schwer zu debuggen: Die Datenrate auf den Drähten ist sehr hoch, und der Computermonitor wird dir nicht sagen, was falsch ist, wenn er sich weigert, auf die Ausgabe des FPGA zu reagieren. Für diesen Zweck gibt es fertige IP-Blöcke. Ich schlage vor, sie zu verwenden und dich stattdessen darauf zu konzentrieren, Videodaten zu erzeugen.
Und ein kleiner Tipp: Du willst wahrscheinlich RGB-Pixel an den Monitor senden. Folge in diesem Fall dem DVI-Protokoll (das mit VGA verwandt ist), und nicht HDMI. Die Signale von DVI und HDMI sind austauschbar. Aber HDMI ist ein strengeres Protokoll, das für Standard-High-Definition-TV gedacht ist und nur eine enge Auswahl an Anzeigemodi hat. Die Pixel der üblicherweise verwendeten Anzeigemodi werden im YCbCr-Format dargestellt, was eine unnötige Schwierigkeit ist. Der HDMI-Steckverbinder wird verwendet, weil der DVI-Steckverbinder und sein Kabel groß und klobig sind. Aber die Signale zu einem Computermonitor folgen fast immer dem DVI-Standard, nicht HDMI.
Wenn du ein Videoausgabeprojekt ausprobierst, wirst du bald feststellen, dass die eigenen Block-RAMs des FPGA oft nicht ausreichen, um ein Einzelbild unterzubringen. Das bringt mich zum nächsten Thema.
DDR-Speicher
Das eigene RAM des FPGA ist eine relativ knappe Ressource. Wenn das Projekt den Umgang mit Megabytes und Gigabytes erfordert, ist externer Speicher nötig. Das ist oft bei Projekten mit Video der Fall, aber auch bei anderen Anwendungen wie Coprocessing / Hardwarebeschleunigung, Netzwerk-Switching und mehr.
Mit Abstand die am häufigsten verwendeten externen RAMs sind DDR-SDRAMs, die dieselbe Art sind wie die in Computern verwendeten. Deshalb erscheinen sie oft auf FPGA-Entwicklungsplatinen, manchmal als SODIMMs und häufiger direkt auf die Platine gelötet. Sie haben einen niedrigen Preis und eine ausgezeichnete Bandbreite, aber sie sind mit Blick auf Computer entwickelt. Dementsprechend sind sie bandbreiteneffizient, wenn die Zugriffsanforderungen lange Bursts zusammenhängender Adressbereiche sind. Die weniger bekannte Tatsache über sie ist, dass ihre Leistung wirklich miserabel ist, wenn das Zugriffsmuster weniger diszipliniert ist: Auch wenn sie „Random Access Memory“ (RAM) heißen, sinkt ihre Bandbreitenleistung bei anderen Zugriffsmustern dramatisch. Wenn zum Beispiel jeweils ein Datenelement benötigt wird und jedes Mal von einer Adresse, die nichts mit der vorherigen zu tun hat, schneiden diese Speicher extrem schlecht ab.
Das Schnittstellenprotokoll zu DDR-Speichern ist sehr kompliziert, jedoch müssen FPGA-Designer selten viel darüber wissen: Jeder seriöse FPGA-Hersteller liefert einen zuverlässigen und ziemlich effizienten DDR-Speichercontroller als kostenlosen IP-Block (IP core) zur Verwendung mit seinen FPGAs. Vom FPGA-Designer wird daher nur verlangt, mit diesem IP zu kommunizieren, und zwar über AXI4 oder ein ähnliches Protokoll.
Sind DDR-Speicher ein Thema, das es wert ist, gelernt zu werden? Ich würde sagen, es gibt einen relativ guten Grund dafür, denn sie werden in FPGA-Projekten in verschiedenen Bereichen oft verwendet. Ein Projekt, das DDR-Speicher umfasst und vielleicht eine Videoausgabe erzeugt, kann eine gute Übung sein. Es ist auch empfehlenswert, das Datenblatt eines DDR-Speichers durchzulesen, um die Array-Struktur des Speichers und die Notwendigkeit zu verstehen, Zeilen auszuwählen, bevor auf ihre Daten zugegriffen wird. Es lohnt sich auch, sich die Verzögerungsanforderungen zwischen verschiedenen Operationen (CAS, RAS, Refresh usw.) anzusehen, um zu begreifen, wie sie die Bandbreiteneffizienz verringern können. Das Wichtigste, was man über diese Speicher wissen sollte, ist, wann sie nicht verwendet werden sollten.
SFP+-Cage
Viele Entwicklungsplatinen, insbesondere die offiziellen Platinen der Hersteller, haben eine SFP+-Cage. Dieses Teil fällt optisch auf, da es ein relativ großes Metallteil am Rand der Platine ist. Dieser Steckverbinder ist nur vorhanden, wenn das FPGA Multi-Gigabit Transceivers (MGTs, auf AMD FPGAs GTX, GTH, GTY usw. genannt) hat. Im Inneren der Cage stellt ein Steckverbinder eine direkte Verbindung zu einem oder mehreren der MGTs des FPGA her.
Ein MGT ist eine Funktionseinheit, die bidirektionale Kommunikation mit Gigabit-Raten ermöglicht, üblicherweise 1 Gbit/s und darüber. Das ist das Arbeitstier hinter mehreren bekannten Protokollen, insbesondere PCIe, SuperSpeed USB, SATA, Gigabit-/10G-Ethernet und DisplayPort. Es gibt eine ganze Seitenreihe über MGTs auf dieser Website, beginnend mit einer Seite, die MGTs allgemein erklärt.
Der Hauptzweck der SFP+-Cage ist, ein Glasfaser-Modul einzustecken. Dadurch ist es möglich, zwei FPGA-Platinen mit einem Glasfaserkabel zu verbinden oder die FPGA-Platine mit einer anderen Einheit mit ähnlicher Schnittstelle zu verbinden, zum Beispiel einem Glasfaser-Netzwerkrouter. Das Glasfaser-Modul ist üblicherweise nicht im Kit der FPGA-Entwicklungsplatine enthalten, aber diese sind nicht sehr teuer. Es gibt auch Kabel, mit denen du zwei SFP+-Steckverbinder direkt ohne Glasfaser verbinden kannst.
Bedeutet die Tatsache, dass SFP+-Cages auf FPGA-Platinen so verbreitet sind, dass du so bald wie möglich ein MGT-Experte werden solltest? Das würde ich nicht sagen. Sie erscheinen oft auf Platinen, unter anderem weil die Komponente auf der Platine günstig ist und keine zusätzlichen Komponenten oder viel Verbindungsmöglichkeiten erfordert. Es ist außerdem eine elegante Art, zwei FPGA-Platinen zu verbinden, verglichen mit den Alternativen (die üblicherweise aus vier HF-Kabeln bestehen, die an jedes MGT angeschlossen werden).
Und MGTs sind nicht einfach zu handhaben: Sie ähneln in gewisser Weise digitalen Funkkanälen. Es gibt Bitfehler auf der Verbindung, die Taktfrequenz des Senders ist oft nicht exakt dieselbe wie die des Empfängers, der Empfänger muss den Anfang von Datenrahmen im Datenkanal finden, und die Liste geht weiter.
Es ist daher üblich, dass MGTs zusammen mit einem IP-Block (IP core) verwendet werden, der das Kommunikationsprotokoll handhabt. Insbesondere haben praktisch alle FPGAs mit MGTs auch einen Hard-IP-Block, der das PCIe-Protokoll umsetzt. Es gibt auch IP-Blöcke für mehrere andere bekannte Protokolle, die mit Computern verwendet werden. Für eine Verbindung zwischen zwei FPGAs bietet Xillyp2p eine einfache Schnittstelle.
Auch wenn MGTs also überall sind, ist dieses Thema nicht unbedingt das Erste, was man lernen sollte.
Ethernet
Viele FPGA-Entwicklungsplatinen haben einen Ethernet-Steckverbinder. Der Grund dahinter hängt von der Art des FPGA ab.
Der einfachste Fall zu erklären ist, wenn das FPGA einen Prozessor integriert hat, zum Beispiel AMDs Zynq-Bauteile. Auf diesen Platinen ist der Ethernet-Steckverbinder fast immer mit den dafür vorgesehenen Pins des Prozessors verbunden. Das ist genau wie der Ethernet-Steckverbinder auf jeder Platine mit einem eingebetteten Prozessor.
Was ist mit Platinen mit FPGAs ohne Prozessor? Zunächst einmal kann selbst so ein FPGA einen „Soft-Prozessor“ enthalten (z. B. MicroBlaze oder Nios). So ein Prozessor kann denselben guten Nutzen aus einem Ethernet-Steckverbinder ziehen wie jeder andere. Das ist nicht unbedingt ein häufiges Anwendungsszenario, aber lange Zeit haben FPGA-Hersteller versucht, die Idee zu fördern, FPGAs in Rechenzentren einzusetzen. Sie wollten wirklich eine gedankliche Verbindung zwischen FPGAs und Computern herstellen. Der Ethernet-Steckverbinder ist Teil davon.
Wenn überhaupt kein Prozessor im FPGA ist, kann der Ethernet-Steckverbinder verwendet werden, um mit einem Computer zu kommunizieren. TCP/IP ist vielleicht das Erste, woran man denkt, jedoch ist dieses Protokoll für die Implementierung in Software zugeschnitten. Dieses Protokoll in Logik zu implementieren ist kompliziert und führt zu eingeschränkter Funktionalität. Der Protokollstapel muss außerdem auf ARP-Anfragen und vorzugsweise auch auf ICMP-Pakete antworten.
Deshalb ist die einzige praktische Art, Ethernet zum Verbinden einer FPGA-Platine (ohne Prozessor) mit einem Computer zu nutzen, die Verwendung von Broadcast-Paketen: Die FPGA-Platine und der Computer sind Punkt-zu-Punkt verbunden. Die auf dem Kabel übertragenen Ethernet-Frames haben alle die Broadcast-MAC-Adresse. Das wird oft durch die Verwendung von Broadcast-UDP/IP-Paketen erreicht. Das ist also meilenweit von der Art entfernt, wie wir normalerweise einen Computer mit einem Ethernet-Netzwerk verbinden.
Abgesehen davon, dass es nicht elegant ist, hat diese Lösung einen erheblichen Nachteil: Das Ethernet-Protokoll garantiert nicht die Zustellung von Paketen. Wenn es einen Bitfehler in einem Ethernet-Paket gibt, wird es still und leise verworfen. Die Netzwerkkarte des Computers kann auch ohne jeden Grund zufällig ein Paket verwerfen. Das bleibt im normalen Gebrauch unbemerkt.
Wenn Datenverlust also nicht erlaubt ist, muss das FPGA alle Daten, die es überträgt, in einem Puffer halten, um Neuübertragungen machen zu können. Ein Protokoll mit einem Fehlererkennungsmechanismus muss angewendet werden, um solche Neuübertragungen anzufordern. Es richtig über Ethernet zu machen, wird wirklich kompliziert.
Alternativ wird die Möglichkeit von Datenverlust akzeptiert. Oder, wie es in Studenten- und Hobbyprojekten oft passiert, diese Möglichkeit wird ignoriert, weil sie beim Testen des Systems nicht auftritt. Was gut genug ist, wenn das Projekt nicht professionell ist.
Fazit: Verwende den Ethernet-Steckverbinder auf jeden Fall, wenn ein Prozessor auf deiner Platine läuft, insbesondere wenn er Linux ausführt. Aber ich würde nicht vorschlagen, tiefer zu gehen als das.
Das ist das Ende der vierten Seite in dieser Reihe, und damit ist auch die Diskussion der professionellen Fähigkeiten abgeschlossen. Die nächste Seite geht in eine völlig andere Richtung: Welche Art von Persönlichkeit ist für diesen Beruf bevorzugt?