01signal.com

Theoretische Fähigkeiten für einen FPGA-Designer

Diese Seite ist die zweite in einer Reihe von fünf Seiten darüber, wie du ein professioneller FPGA-Designer wirst. Auf dieser Seite gehe ich die verschiedenen theoretischen Themen durch, die meiner Meinung nach jeder FPGA-Designer beherrschen sollte, und versuche außerdem zu erklären, warum ich jedes einzelne für wichtig halte.

Logiktheorie

Die Theorie zu kennen ist kein Luxus. Sie ist das Fundament, auf dem alles andere aufbaut – auch wenn es sich nicht immer so anfühlt, während du mit einem Entwicklungswerkzeug kämpfst, das nicht kooperieren will, oder wenn die Elektronik ihren eigenen Kopf zu haben scheint.

Ein FPGA-Ingenieur muss sich vorstellen können, wie das Verilog, das er schreibt, als Logikelemente umgesetzt wird. Nicht in allen Einzelheiten, aber gut genug, um sagen zu können, welche Teile das Design verlangsamen und die Taktfrequenz begrenzen und welche Teile jede Menge Logikressourcen verschlingen werden. Das ist entscheidend, zum Beispiel um zu wissen, wann eine Aufgabe durch das Hinzufügen von Registern in eine Pipeline (pipeline) gebracht werden muss. Pipelining verkompliziert das Design meist, aber es ist oft der einzige Weg, die erforderliche Geschwindigkeit zu erreichen. Andere wichtige Designentscheidungen hängen von dieser Fähigkeit ab.

Es ist auch entscheidend, um nachzuvollziehen, was der Synthesizer (synthesizer) getan hat und warum. Wenn du zum Beispiel weißt, was der Synthesizer dazu neigt wegzuoptimieren, kannst du Verilog-Code schreiben, der sowohl lesbar als auch effizient ist. Wenn du nicht weißt, was der Synthesizer mit deinem Code machen wird, schreibst du blind.

Welche Themen sind also relevant? Ich schlage vor, mit dieser Checkliste anzufangen. Ich behaupte nicht, dass sie alles abdeckt.

Logikparadigmen und -techniken

Neben der reinen Logiktheorie gibt es ein paar Themen, die nötig sind, um Code zu schreiben, der zuverlässig und effizient funktioniert und sich in der Hardware genauso verhält wie in der Simulation. In der Softwarewelt ist das fast selbstverständlich, aber FPGA-Designer bewegen sich in einem anderen Gebiet. Jeder FPGA-Designer muss diese Themen ständig im Kopf haben.

Das RTL-Paradigma, Register Transfer Level, ist die zentrale Idee. Kurz gesagt bedeutet es, dass alles, was einen Wert speichert, diesen Wert nur als Reaktion auf eine Taktflanke ändert. Ein asynchroner Reset (asynchronous reset) kann die eine sorgfältig kontrollierte Ausnahme sein. Wenn du diese Denkweise verinnerlicht hast, hast du gute Chancen, es richtig zu machen.

Reset ist ein Thema für sich. Synchrone gegenüber asynchronen Resets (synchronous reset, asynchronous reset) und die Reset-Synchronisierung sind Dinge, die du in jedem Design klären musst, an dem du arbeitest. Wenn nicht, funktioniert dein Design die meiste Zeit einwandfrei, mit sporadischen Aussetzern hier und da. Du hast dann ein funktionierendes System zum Ausliefern, aber du wirst es wegen dieser sporadischen Fehler nicht freigeben können. Dein Projekt wird immer später, und du hast keine Ahnung, was falsch ist. Ein schlechter Reset ist nicht das, woran man in solchen Situationen denkt. Du willst dieses Thema wirklich in die Tiefe verstehen. Es gibt eine kurze Seitenreihe zu diesem Thema auf dieser Website.

Eng damit verwandt ist die Frage nach Taktfreigaben (clock enable) gegenüber getakteten Takten (gated clocks). Im Wesentlichen sind das zwei verschiedene Techniken, damit das Logikdesign nicht in jedem Taktzyklus rechnet. Das FPGA hat eigene Ressourcen für Clock Gating, aber es falsch zu machen ist ein prima Weg, mysteriöse Probleme zu erzeugen. Die sichere Angewohnheit ist, in deiner Logik Clock Enables zu verwenden, aber wenn du die niedrigere effektive Taktfrequenz nutzen willst, um die Timing-Vorgaben (timing constraints) zu entspannen, kannst du ebenfalls in Schwierigkeiten geraten.

Auch die Kodierung von Zustandsautomaten (state machine) verdient eine Erwähnung. Binäre, One-Hot- und Gray-Kodierung haben alle ihre Berechtigung, und die Wahl hat Auswirkungen sowohl auf die Geschwindigkeit als auch auf den Ressourcenverbrauch. Die Tools wählen oft für dich, aber du solltest wissen, was die Optionen bedeuten. Insbesondere die One-Hot-Kodierung ist hervorragend für große Zustandsautomaten. Aber wenn der Zustandsautomat nicht richtig zurückgesetzt wird, kann diese Kodierung ihn Dinge tun lassen, die laut Verilog-Code unmöglich sind. Es sieht aus wie Hexerei im FPGA oder ein Fehler im Synthesizer, aber nein, es ist One-Hot-Kodierung und ein schlecht angewendeter Reset.

Und schließlich das Pipelining. Es ist nicht nur eine Technik, sondern eine Denkweise. Ein Register hinzuzufügen ist trivial, aber die Tatsache, dass sich die Datenverarbeitung über mehrere Taktzyklen erstreckt, bringt eine ganze Reihe möglicher Probleme mit sich. Zum Beispiel: Was soll der Empfänger dieser Daten tun, bevor die ersten gültigen Daten angekommen sind? Was passiert, wenn die Eingangsdaten nicht kontinuierlich ankommen und die Pipeline vorübergehend einfrieren muss? Wie macht man das, ohne ein einziges Clock Enable mit einem riesigen Fan-out (fan-out) zu allen Logikelementen in der Verarbeitungskette?

Jedes Szenario erfordert eine andere Art von Pipeline-Design, und jedes hat seine eigenen Herausforderungen und Eigenheiten.

Digitaltechnik

Wie oben erwähnt, muss sich ein FPGA-Designer vorstellen können, wie Verilog am Ende zu Logikelementen im FPGA wird. Nehmen wir ein konkretes Beispiel.

Angenommen, ich schreibe ein schlichtes „assign x = a + b;“ in Verilog. Wie wird dieser Addierer implementiert? Nutzt dieses konkrete FPGA besondere Tricks, um einen Addierer zu implementieren? Verwendet es einen dedizierten Hard Block, zum Beispiel einen DSP-Block? Und wenn ja, wie viel hilft das, wenn das Ergebnis des Addierers ein Register statt eines Drahts ist? Was passiert, wenn ich drei Zahlen addiere, wie in „assign x = a + b + c;“? Hat das FPGA irgendeine Abkürzung, um drei Zahlen zu addieren? Die Antwort ist höchstwahrscheinlich nein, also wird das als so etwas wie (a + b) + c implementiert. Zwei Logikoperationen in Kaskade können das Design erheblich verlangsamen. Aber wie funktioniert das auf deinem konkreten FPGA?

Es ist wichtig, sich bewusst zu sein, welche Ressourcen in dem konkreten FPGA verfügbar sind, das du als Zielplattform wählst. Das prägt die Art, wie du Verilog schreibst, damit der Synthesizer schnelle und effiziente Logik erzeugen kann. Der Synthesizer ist kein Magier, der jedes Problem löst, das man ihm vorwirft. Wenn du Verilog klug schreibst und seine Grenzen kennst, bekommst du ein Design, das wenige Ressourcen verbraucht, relativ wenig Leistung aufnimmt und bei einer hohen Taktfrequenz arbeitet. Das kommt mit Erfahrung, und Wissen über Digitaltechnik beschleunigt den Prozess, diese Art von Weisheit zu erlangen.

In der Praxis sind wir normalerweise nur dann gezwungen, uns die Logikimplementierung im FPGA anzusehen, wenn wir Probleme beim Timing-Abschluss (timing closure) lösen, weil wir verstehen müssen, warum das Ergebnis langsam war oder zu viele Ressourcen verbraucht hat. Also gehen wir die kleinen Details der Logikimplementierung eins nach dem anderen durch und suchen nach verschwendeter Zeit oder verschwendeten Ressourcen. Aber es ist auch eine gute Idee, die Ergebnisse ab und zu freiwillig zu analysieren, nur um mehr Wissen zu sammeln oder um zu prüfen, dass nichts Verrücktes passiert ist. Das zahlt sich langfristig aus.

Kenne dein FPGA

Ein weiterer Aspekt beim Vorstellen, wie Verilog zu Logikelementen wird, betrifft die grundlegenden Logikressourcen. Das bedeutet, die Bausteine des FPGA zu kennen und zu wissen, wofür sie gut sind.

Zuerst die Struktur eines FPGA selbst: die Grundelemente, die CLBs und die Slices (slice) deines FPGA. Beim Schreiben von Verilog-Code ist es ein großer Vorteil, wenn du dir vorstellen kannst, wie diese Elemente verwendet werden, um die erforderliche Logik zu implementieren. So kannst du erkennen, ob das, was du schreibst, zum Engpass beim Timing-Abschluss (timing closure) des Designs werden könnte oder ob dich dieses Code-Schnipsel nie wieder stören wird.

Die meisten FPGAs sind mehr oder weniger gleich aufgebaut. Alle haben eine Möglichkeit, arithmetische Addierer, Multiplexer, Demultiplexer und so weiter effizient zu implementieren, weil diese Funktionen viel verwendet werden. Zum Beispiel haben viele FPGAs Multiplizierer als Hard Block, wodurch Operationen wie „assign x = a * b;“ bei einer hohen Taktfrequenz laufen können.

Aber die genauen Eigenschaften dieser Multiplizierer können sich unterscheiden. Bei manchen FPGAs sind die Operanden dieser Multipliziererblöcke 18-Bit-Ganzzahlen mit Vorzeichen. Eine Multiplikation mit Operanden dieser Breite oder weniger läuft also bei einer viel höheren Taktfrequenz als wenn einer der Operanden 19 Bit breit ist. Das ist ein weiteres Beispiel dafür, warum es wichtig ist, die Logikblöcke des FPGA zu kennen: Ein einziges zusätzliches Bit kann die Taktfrequenz erheblich senken. Beachte, dass es bei einer anderen FPGA-Familie ein völlig anderes Spiel mit anderen Operandenbreiten sein kann.

Auch die Routing-Ressourcen zählen. Die Logikelemente sind nur die eine Hälfte der Geschichte; die Drähte zwischen ihnen sind die andere Hälfte. Ziemlich oft kann ein Design seine Taktfrequenz nicht erreichen, weil die Verdrahtung überlastet und dadurch langsam wird. Darüber sollte man nachdenken, wenn man sein FPGA zu fast 100 % seiner Logikkapazität auslasten will und viele breite Datenbusse im Design hat. Einige Routing-Ressourcen („Drähte“) im FPGA sind schnell, andere langsamer. Wenn die schnellen aufgebraucht sind, wird das gesamte Design langsamer.

Du solltest außerdem FIFOs und BRAMs verstehen. Das sind die Speicherressourcen im FPGA, und du wirst sie ständig nutzen, sowohl zum Speichern und Puffern von Daten als auch zum Überqueren zwischen Taktbereichen (clock domain). Zu wissen, wie man mit einem FIFO arbeitet, ist das tägliche Brot. Es gibt eine Seitenreihe auf dieser Website zu diesem Thema.

Die Taktressourcen sind ihr eigenes kleines Universum: PLLs, Clock Buffer und die globalen und regionalen Taktnetzwerke (clock networks). Die PLL ist die Komponente, die einen eingehenden Takt in die Takte umwandelt, die deine Logik tatsächlich braucht. Sie multipliziert und teilt Frequenzen und erlaubt auch Phasenverschiebung. Es ist auch wichtig zu wissen, welche Takte phasenausgerichtet sind und welche nicht. Angenommen, eine PLL gibt zwei Takte aus, und einer hat die doppelte Frequenz des anderen: Ist es sicher, dass ein Register, das mit dem ersten Takt getaktet wird, die Ausgabe eines Registers abtastet, das mit dem zweiten Takt getaktet wird? Normalerweise ja, aber es hängt davon ab, ob diese beiden Takte phasenausgerichtet sind. Du musst aber wissen, wie man prüft, dass das tatsächlich der Fall ist. Es gibt eine Seite auf dieser Website, die dieses Thema behandelt.

Als Nächstes haben wir die I/O-Block-Ressourcen. In Designs mit Hochgeschwindigkeits-I/O-Signalen wie DDR und SERDES musst du verstehen, was die I/O-Blöcke für dich tun können und wie sie I/O mit Datenraten ermöglichen, die viel höher sind als die Taktfrequenz deines Designs. Sie können auch so konfiguriert werden, dass sie bei der Impedanzanpassung helfen, indem sie einen Abschlusswiderstand (termination) und andere elektronische Low-Level-Funktionen hinzufügen.

Und wenn du Datenraten über einem Gigabit pro Sekunde brauchst, sind Multi-Gigabit Transceivers (MGTs) das Richtige für dich. Das ist ein relativ fortgeschrittenes und kompliziertes Thema und nichts für Anfänger, es sei denn, es wird für ein bestimmtes Projekt benötigt. Auch dazu gibt es eine Seitenreihe auf dieser Website.

Und ein letztes, etwas langweiliges Thema: Konfigurationsspeicher und das Laden des Bitstroms (bitstream). Wenn du mit dem Design fertig bist, willst du den Bitstrom nicht jedes Mal vom Computer in das FPGA laden. Also kann das FPGA ihn selbst aus dem Flash-Speicher laden. Oder von einer SD-Karte. Oder eine separate Komponente auf der Platine kann den Bitstrom in das FPGA schieben, eine Lösung, die oft gewählt wird, wenn es einen separaten Prozessor auf der Platine gibt.

Die Techniken zum Laden des FPGA sind nichts Lustiges, aber wenn du in einem kleinen Team arbeitest, wirst du auch dafür verantwortlich sein. Und oft gibt es Anforderungen daran, wie schnell das FPGA nach dem Einschalten der Platine betriebsbereit sein muss. Das musst du herausfinden.

Ein weiterer Grund, sich dieses Themas bewusst zu sein, ist, dass das FPGA beim Einschalten oft automatisch aus dem Flash-Speicher geladen wird, insbesondere auf Evaluierungsplatinen. Um es noch kniffliger zu machen: FPGA-Platinen haben oft mehr als eine mögliche Speicherquelle, aus der der Bitstrom geladen werden kann. Sehr lange Debugging-Sitzungen entstehen, wenn Leute nicht wissen, dass eine alte Version ihres Projekts in das FPGA geladen ist: Egal welche Änderungen sie am Design vornehmen, das FPGA verhält sich gleich, weil sie jedes Mal den falschen Flash-Speicher aktualisieren.

Timing

Zuerst ein kurzes Wort darüber, was Timing ist (im Kontext eines Logikdesigns). Um es kurz zu machen: Jedes digitale Signal innerhalb und außerhalb des FPGA muss während bestimmter Zeiträume elektrisch stabil sein, normalerweise in Bezug auf Taktflanken. Andernfalls wird das Verhalten der Logik unvorhersehbar. Die Entwicklungswerkzeuge stellen sicher, dass diese Timing-Anforderungen überall dort erfüllt werden, wo es nötig ist. Damit das aber passiert, müssen wir diesen Tools bestimmte Informationen geben, und das sehr genau. Darüber hinaus muss auch das Logikdesign so gemacht sein, dass die Tools die Timing-Anforderungen erfüllen können. Darum geht es beim Timing im Kern.

Timing ist möglicherweise der schwierigste Teil des FPGA-Designer-Daseins. Es ist auch der wichtigste Bereich, den man wirklich beherrschen und richtig umsetzen muss. Leider ist es ziemlich leicht, dieses Thema zu vernachlässigen und trotzdem ein Design zu bekommen, das einigermaßen gut funktioniert oder vielleicht gerade gut genug, um den Eindruck zu erwecken, dass du fast fertig bist. Alles funktioniert einwandfrei, aber im FPGA scheinen übernatürliche Kräfte zu walten, die bei Vollmond plötzliche Ausfälle verursachen. Diese Denkweise nenne ich den „Black-Magic-Modus“, und es gibt eine separate Seite darüber.

An einem guten Tag lässt sich ein FPGA-Design, das ohne Timing im Hinterkopf geschrieben wurde, leicht durch das Hinzufügen einiger Timing-Vorgaben (timing constraints) reparieren. Manchmal muss fast alles von Grund auf neu gemacht werden, weil die Entwicklungswerkzeuge es nicht bei der erforderlichen Taktfrequenz zum Laufen bringen, wenn die korrekten Timing-Anforderungen durchgesetzt werden. Dann muss der Verilog-Code selbst überarbeitet werden.

Und an einem wirklich schlechten Tag muss die Platine teilweise neu entwickelt werden, weil es unmöglich ist, sicherzustellen, dass alle physischen Signale auf der Platine innerhalb der Zeitfenster, in denen sie stabil sein müssen, eine stabile Spannung haben. Eine ordnungsgemäße Timing-Analyse, bevor die Platine für die Produktion freigegeben wurde, hätte das aufgedeckt, aber wenn das vernachlässigt wurde, ist die Hardware möglicherweise nicht für die Aufgabe geeignet.

Aber wenn du das Timing sorgfältig und korrekt machst, ist das FPGA die zuverlässigste Komponente der Welt. Viele FPGA-Designer haben Angst, die geringste Änderung am Design vorzunehmen, und haben jedes Mal Angst, wenn eine neue Charge FPGA-Chips in der Produktion verwendet wird. Verrückte Kühlung wird eingesetzt, denn um Himmels willen, wenn das FPGA ein bisschen warm wird. Ich sage: Mach das Timing unbedingt richtig, und vergiss alle Sorgen.

Musst du das vom ersten Tag an perfekt beherrschen? Ich würde tatsächlich ja sagen. Im Prinzip würde ich zustimmen, dass es reicht, wenn in einem Team von FPGA-Designern nur einer wirklich gut im Timing ist. Sei dieser eine FPGA-Designer, aus einem einfachen Grund: Die Wahrscheinlichkeit ist hoch, dass es sonst niemand sein wird.

Es gibt eine ziemlich lange Seitenreihe über Timing auf dieser Website, daher ist es wenig sinnvoll, die Themen hier auszuführen. Hier ist also nur eine kurze Liste von Themen, mit denen sich meiner Meinung nach jeder FPGA-Designer wohlfühlen sollte:

Elektronik

Das FPGA ist ein elektronisches Bauteil, und FPGA-Design ist ein Fachgebiet innerhalb der Elektrotechnik. Und es ist die Art von Elektrotechnik, die sich mit Schaltplänen und Datenblättern, Spannungen und Strömen, Signalintegrität und Impedanzanpassung befasst. Das ist das Wissen, das jeder Platinenentwickler haben muss, und das Leben eines FPGA-Designers ist deutlich einfacher, wenn er diese Art von Wissen ebenfalls hat.

Es ist üblich, dass dem FPGA-Designer die Aufgabe zugewiesen wird, sicherzustellen, dass das FPGA korrekt mit den anderen Komponenten auf der Platine kommuniziert. Tatsächlich ist es nicht selten, dass Platinenentwickler alles, was sie können, mit dem FPGA verbinden, um sich von der Verantwortung zu befreien, diese Komponenten zum Laufen zu bringen. Vom FPGA-Designer wird daher oft ein tiefes Verständnis dafür verlangt, wie Komponenten auf einer Platine miteinander kommunizieren. Oft ist es der FPGA-Ingenieur, der auf mögliche Signalintegritätsprobleme hinweisen muss, die bei Drähten mit hohen Schaltfrequenzen behandelt werden müssen.

Wenn eine neue Platine entwickelt wird, muss der FPGA-Designer des Teams das Design üblicherweise freigeben, das heißt prüfen, dass die Verbindungen zum FPGA korrekt sind. Nicht alle Pins des FPGA sind für alle Zwecke geeignet, und manchmal ist es erforderlich oder deutlich besser, dass bestimmte Verbindungen zu einer bestimmten Gruppe („Bank“) von FPGA-Pins gehören. Das sind Dinge, die der FPGA-Designer beherrschen muss oder zu denen er zumindest eine fundierte Meinung haben sollte.

Es ist nicht selten, dass FPGA-Designer ehemalige Platinenentwickler sind. Der Weg (path) vom Board-Design zum FPGA-Design ist ein natürlicher, und diejenigen, die ihn gegangen sind, haben einen deutlichen Vorteil. Selbst wenn der Platinenentwickler verantwortlich ist und eine vollkommen gute Platine entwirft, muss der FPGA-Designer trotzdem die Herausforderungen mit Hochgeschwindigkeitssignalen auf einer Platine verstehen, um die I/O-Blöcke des FPGA richtig zu konfigurieren.

Wie ich bereits erwähnt habe, arbeiten nicht alle FPGA-Ingenieure direkt mit Elektronik. Manche beschränken sich auf die Entwicklung interner Logik, das, was ich „Verarbeitungslogik“ genannt habe, und manchmal stellen Unternehmen einen Ingenieur nur für Simulation und Verifikation ein. Aber die meisten von uns arbeiten direkt mit Elektronik, und in diesem Fall ist etwas verwandtes Wissen erforderlich.

Es beginnt mit den absoluten Grundlagen: Spannung, Strom, Widerstände und das Ohmsche Gesetz. So bewegen sich digitale Signale von einer Komponente zur anderen. Es ist auch eine gute Idee, Kapazität und das Laden und Entladen eines Kondensators zu verstehen. Damit kannst du verstehen, wie Strom und Kapazität die Schaltgeschwindigkeiten und den Leistungsverbrauch beeinflussen.

Du solltest Schaltpläne lesen können: ICs, Module, Induktivitäten, Spannungsversorgungen, digitale und analoge Masse. MOSFETs und Bipolartransistoren tauchen manchmal ebenfalls auf, und du solltest sie zumindest erkennen. Es schadet nicht, eine Vorstellung davon zu bekommen, wie sich ein MOSFET-Transistor verhält.

Du wirst auch viel Zeit mit dem Lesen von Datenblättern verbringen. Der schwierigste und wichtigste Teil ist, die Timing-Spezifikationen im Datenblatt in Timing-Vorgaben (timing constraints) und/oder ein passendes I/O-Design auf dem FPGA zu übersetzen. Board Skew (Platinen-Skew) ist etwas, das du möglicherweise in deinem I/O-Timing berücksichtigen musst.

Du wirst aber auch dafür verantwortlich sein, die Spannungs- und Stromspezifikationen im Datenblatt zu verstehen und den jeweiligen I/O-Block des FPGA mit dem korrekten Spannungsstandard zu konfigurieren: Single-Ended- und Differenzial-Schnittstellen, LVCMOS, SSTL, LVDS und so weiter.

Machen das wirklich alle FPGA-Designer richtig? Die Antwort ist nein. Es ist ziemlich häufig, Designs zu sehen, die wegen ihrer elektronischen Missgeschicke überhaupt nicht funktionieren dürften und trotzdem perfekt zu funktionieren scheinen. Es ist nicht selten, dass der Ausgangspin einer Komponente den Eingangspin einer anderen Komponente mit einer Spannung speist, die über dem absoluten Maximum Rating (absolute maximum rating) liegt. Das ist natürlich ein riesiger Fehler, und die Komponente, die die überhöhte Spannung erhält, kann laut Datenblatt prinzipiell jederzeit durchbrennen. Und trotzdem funktioniert alles ewig und immer. Bis es plötzlich kaputtgeht und kluge Leute alberne Ausreden dafür finden, warum das passiert ist.

Ich füge auch eine kurze Liste von Themen hinzu, die definitiv in der Verantwortung des Platinenentwicklers liegen. Aber wenn diese Person weniger als hervorragend ist, hilft es, wenn der FPGA-Ingenieur auch etwas davon versteht:

Was muss ein FPGA-Designer von all dem wirklich wissen? Was ist von Anfang an entscheidend? Es ist tatsächlich schwer für mich zu sagen. Je besser das Team um dich herum, desto weniger Elektronik musst du wissen. Aber ich würde sagen, dass jeder FPGA-Designer Schaltpläne lesen können und verstehen sollte, was mit dem FPGA verbunden ist, und mehr oder weniger verstehen sollte, warum es auf diese spezielle Weise verbunden ist.

Dies schließt die zweite Seite in dieser Reihe ab. Die nächste Seite geht im selben Geist wie oben zu den praktischen Fähigkeiten über.1

Diese Seite wurde maschinell aus dem Englischen übersetzt. Im Zweifelsfall siehe den Originaltext.
Copyright © 2021-2026. All rights reserved. (852e87d4)