So erhalten Sie ein FPGA-Design, das definitiv auf tatsächlicher Hardware funktioniert

Ich habe gerade angefangen, digitales Logikdesign mit FPGAs zu lernen, und habe viele Projekte erstellt. Meistens (da ich ein Noob bin) habe ich ein Design, das perfekt simuliert (Verhaltenssimulation), aber nicht richtig synthetisiert.

Meine Frage lautet also: "Welche Designschritte kann ich in meinen Workflow integrieren, um sicherzustellen, dass ich ein funktionierendes Design habe, das direkt auf meinem FPGA funktioniert?"

Ich habe zwei Hauptbereiche, in denen ich Ratschläge erwarte, aber dies basiert absolut auf einer sehr engen Sichtweise von mir als Anfänger, und weitere sind willkommen:

  • Welche Schritte (Anzeigen von RTL-Schemas, Post-Synthese-Simulation, ...) sollte ich für die beste Praxis lernen?
  • Was sollte ich beim Entwerfen meiner Logik (z. B. FSMs oder sequentielle Schaltungen) beachten, um unerwartete Ergebnisse zu vermeiden?

Ich verwende ein Xilinx Spartan 6 FPGA und die Xilinx ISE Design Suite für meine Arbeit.

Auf welche Art von Problemen stoßen Sie bei der Synthese? Erreichen Sie eine hohe Abdeckung in der Simulation?
@ pjc50 Ich verstehe die Frage nicht. Was meinen Sie mit „hohe Abdeckung in der Simulation“?
Sie haben eine Testbench oder einen Stimulus, der die Simulation antreibt. Coverage-Tools sagen Ihnen, wie viel des Designs tatsächlich durch den Test ausgeübt wird, als Prozentsatz. Wenn diese Zahl zu niedrig ist, ist Ihre Testbench unzureichend und Sie testen einige Fälle nicht, die in der realen Verwendung auftreten könnten.
@ pjc50 das ist eigentlich ein sehr guter Rat. Was ist das Äquivalent dazu in der Xilinx ISE Design Suite?
Schnelles Googeln deutet darauf hin, dass dies in ISIM tatsächlich fehlt und Sie Modelsim oder einige andere Tools von Drittanbietern verwenden müssen. Ich bin mit dem Altera-Pfad (der Modelsim verwendet) besser vertraut.
Der erste Schritt, wenn Sie ISIM verwenden, besteht darin, die verdammten Reichweitenprüfungen einzuschalten. Warum sie standardmäßig ausgeschaltet sind, kann sich jeder vorstellen, aber es hat diesen Typen Stunden gekostet . electronic.stackexchange.com/questions/153362/…
Bemerkenswert: Synthetisiert und "funktioniert definitiv auf tatsächlicher Hardware" sind unterschiedliche Strenge. Es gibt Muster, denen man folgen kann, um sicherzustellen, dass es synthetisiert wird. Wenn es jedoch darum geht, es auf echter Hardware zum Laufen zu bringen, muss man sich mit Sicherheit an die Maxime der Simulation erinnern: "Alle Modelle sind falsch; einige sind nützlich."
In Kommentaren zu Ihrer früheren Frage haben Sie Ihren Code geteilt. Ich sehe keinen Grund, warum dieser Code nicht synthetisiert werden sollte. Aber Sie haben nie Einschränkungen erwähnt. Haben Sie eine Einschränkungsdatei bereitgestellt, die das Takttiming richtig angibt? Selbst eine einfache Taktperiodenbeschränkung sollte für Ihr Design ausreichend sein.
@ThePhoton Das Problem lag in den Einschränkungen, denn für den Pin, den ich als Eingang verwendete, habe ich weder Pullup aktiviert noch einen externen Pullup angeschlossen. Deshalb hat es nicht funktioniert. Nach der Änderung wurde das Design einwandfrei ausgeführt.

Antworten (5)

An einem Ort, an dem ich arbeitete, gab es zwei Lager von FPGA-Designern. Ein Lager habe ich „simulieren“, „simulieren“, „simulieren“ oder „s cubed“ genannt. Im anderen Lager drehte sich alles um Design.

Die S-Cubed-Jungs verwendeten einen Simulator wie Modelsim, sie entwickelten ein erstes Design über Codierungsmethoden und/oder Blöcke in der Design-Suite. Dann würden sie es simulieren und die Dinge finden, die nicht funktionieren würden, und dann den Code ändern. Dieser Prozess wurde mehrere Male wiederholt, bis sie zu einem funktionierenden Design kamen.

Das Designcamp (das ich bevorzugte) entwarf die Wellenform auf Papier (oder digitalem Papier wie Visio), genau das, was erforderlich war. Dann erstelle ein Logikdiagramm. Dies ist ein selbstdokumentierender Prozess. Dann wurde das Diagramm in Code übersetzt (der Code und das Diagramm waren 1:1, wenn etwas im Diagramm war, gab es einen Prozess dafür im Code). Dann wurde es simuliert, und die simulierte Wellenform wurde mit der entworfenen Wellenform auf Papier verglichen, und es wurde erwartet, dass sie gleich ist.

Am Ende habe ich beides gemacht, manchmal geriet ich in den Würfelmodus, und es war nicht sehr lustig. Ich habe gemerkt, dass ich manchmal mein Ziel aus den Augen verloren habe. Zum Beispiel würde ich einen Zustand in einer Zustandsmaschine ändern, und die Änderung würde sich auf den nächsten Zustand auswirken, dann müsste ich das beheben. Am Ende verbrachte ich mehr Zeit damit, als darüber nachzudenken.

In welchem ​​Camp wärst du lieber? Ich denke, es muss ein strenges Design geben, tun Sie, was für Sie funktioniert, aber ich denke, je detaillierter und strenger Sie beim Entwerfen sind, desto weniger Probleme werden Sie auf lange Sicht haben. Ich habe einige Beispiele dafür gegeben, was möglich ist, sie passen möglicherweise nicht zur Organisationsstruktur Ihres Arbeitsplatzes. Der Grund, warum Designdetails und sorgfältige Planung so nützlich sind, ist, dass es Sie dazu zwingt, darüber nachzudenken, was Sie tun. Es erleichtert das Debuggen. Entwickeln Sie einen Design-Workflow, der dies ermöglicht. Machen Sie sich außerdem wirklich mit den Simulationstools vertraut und schreiben Sie gute Testbenches, die alle Bedingungen testen, denen das simulierte Gerät ausgesetzt sein könnte. Dies muss natürlich mit der Zeit ausgeglichen werden. Schreiben Sie beispielsweise ADC-HDL-Code, der das Gerät in Ihren Simulationen simuliert.

Das wertvollste Werkzeug im FPGA-Design ist (meiner Meinung nach) ein gutes Testverfahren, mit dem Sie Ihr Design vollständig testen und auf Herz und Nieren testen können. Von einem FPGA-Design kann nicht erwartet werden, dass es "einfach funktioniert", es erfordert Anstrengung, um sicherzustellen, dass alle Teile funktionieren. Wenn Sie Fehler entdecken, gehen Sie zurück zur Simulation und zum Design und erfahren Sie, was die Unterschiede zwischen einem simulierten FPGA und RTL sind. Das kommt hauptsächlich von Erfahrung, aber wenn das Design in der Simulation funktioniert, aber nicht in der Hardware, dann müssen Sie herausfinden, warum es einen Unterschied gibt.

Ein paar wichtige Dinge, die ich gelernt habe:
1) Bereinigen Sie Ihre Eingänge, die Takt- und Rücksetzschaltungen müssen sauber sein, oder Sie können Metastabilität durch Ihr System ausbreiten. Wissen, was ein Dual-Rank-Synchronizer ist. Es gibt viele verschiedene Topologien für Reset-Schaltungen, wissen Sie, wie man sie benutzt (es gibt einen großartigen Artikel im Internet, ich habe ihn jedoch nicht zur Hand).
2) Holen Sie sich die Anforderungen des Designs im Voraus und entwerfen Sie dann um diese herum. Wenn die Leute um Sie herum Ihnen keine konkreten Anforderungen stellen, dann überlegen Sie sich selbst welche.
3) Die Matlab Fixed Point Toolbox eignet sich hervorragend zum Simulieren von Steuerungssystemen und DSP-Anwendungen, aber Sie haben möglicherweise keinen Zugriff darauf. Es ist eine großartige Möglichkeit, ein Design zu testen, bevor Sie es programmieren.
4) Design kommt zuerst, dann codieren, dann simulieren.
5) Stark typisiert, halten Sie auch Signalnamen auf PCB-Schaltplan und HDL konsistent. (Deshalb bevorzuge ich auch VHDL gegenüber Verilog.

+1 für "s cubed" oder s ich m u l a t ich Ö n 3
Ziemlich gut: zu "rigoroses Design" würde ich "Verwendung des Typsystems" hinzufügen. Beispiel: ein Array-Index des geeigneten Typs, wie z. B. der Bereich des Arrays, es ist nicht erforderlich, auf eine Bedingung außerhalb der Grenzen zu testen. Ich würde nur "Wellenform verglichen mit der entworfenen Wellenform auf Papier" widersprechen ... die entworfene Wellenform sollte zu diesem Zeitpunkt in VHDL vorliegen (oder vielleicht aus einer Textdatei gelesen werden) und der Simulator sollte den Vergleich durchführen.
Es könnte auch so gemacht werden, ich fand es nützlich, eine Wellenform auf Papier zu entwerfen, weil es etwas zum Vergleichen gab. Wie bei einer ADC-Wellenform wurde das Timing entworfen und dann mit dem Modlesim-Ausgang verglichen und dann physisch verifiziert. Wenn die Modelsim-Ausgabe korrekt ist, vergleichen Sie sie damit. Der Code war stark typisiert (das habe ich vergessen zu erwähnen), aber das ist wirklich wichtig. Aus diesem Grund bevorzuge ich VHDL gegenüber Verilog, es gibt weniger Abkürzungen, die Sie nehmen können. Und es macht den Code viel besser lesbar.
Jawohl. Genau wie in anderen Bereichen wie Software oder herkömmlicher Hardware besteht der Ausgangspunkt darin, das Problem in Blöcke zu unterteilen und sich dann zu fragen: „Woher weiß ich, wann dieser Block funktioniert?“. Dann tu es. Bauen Sie Ihr Design Block für Block auf, fügen Sie die Blöcke dann zusammen und testen Sie erneut, ob das, was Sie erhalten, den Erwartungen entspricht. Manchmal stellen Sie vielleicht fest, dass es mit einem besseren Design auf Blockebene sauberer oder einfacher wäre, also gehen Sie zurück.

Hauptsache sind:

  • Sorgfältige Codierung, um nicht synthetisierbare Strukturen zu vermeiden
  • Minimieren Sie die Logikpegel für eine bessere Timing-Leistung (machen Sie die Logik zwischen den Registern so einfach wie möglich)
  • Testen, testen, testen, um die funktionale Korrektheit sicherzustellen, und auf Dinge wie nicht initialisierte Registrierungen und getrennte Kabel prüfen
  • Synthese und überprüfen Sie die Syntheseprotokolle auf Warnungen, stellen Sie sicher, dass die Warnungen keine Probleme anzeigen (d. h. die Warnung „Register entfernt“ kann beabsichtigt sein (keine Modulausgabe verwendet) oder unbeabsichtigt (Modulausgabe/Tippfehler/usw. vergessen))
  • Mapping und Kartenbericht auf Auslastungszahlen überprüfen, stellen Sie sicher, dass das FPGA nicht zu voll ist
  • Ort- und Routen- sowie Timing-Analysen stellen Sie sicher, dass Ihr Design mit der erforderlichen Taktgeschwindigkeit läuft

Ich habe mehrere ziemlich komplexe Designs beim ersten Test auf einem tatsächlichen FPGA richtig (oder zumindest größtenteils richtig) funktionieren lassen, indem ich das oben Gesagte befolgt habe. Es ist nicht nötig, den RTL-Schaltplan zu überprüfen, das ist nur extrem umständlich und bei großen Designs eine reine Zeitverschwendung. Eine Post-Synthese-Simulation wäre viel nützlicher.

Danke für ihre schnelle Antwort. Könnten Sie bitte den zweiten Punkt näher erläutern (Logikebenen minimieren).

Ihr gesamter synthetisierbarer Code muss ausdrückbar sein als:

  • LUTs
  • Flip-Flops
  • Anbieterspezifische Primitive

Anbieterspezifische Primitive werden entweder explizit instanziiert oder vom Assistenten des Anbieters generiert oder von sehr spezifischen Codierungsmustern abgeleitet, sodass hier keine Mehrdeutigkeit bestehen sollte.

In VHDL können Sie beispielsweise keinen wait forsynthetisierbaren Code verwenden. Um zu verstehen, warum, versuchen Sie, wait for 100 nsmithilfe von LUTs oder Flip-Flops deterministisch auszudrücken. Du kannst nicht.

Das bedeutet nicht, dass Sie es nicht implementieren können, indem Sie einen Zähler mit einer bekannten Taktfrequenz (mit einer Periode, die 100 ns teilen kann) einrichten und dessen Zählung verwenden, um zu wissen, wann die Zeit abgelaufen ist. Aber die Synthese-Engine wird dieses Schema nicht automatisch erstellen, Sie müssen die Architektur in Bezug auf kombinatorische Logik (Gatter/LUTs) und Register explizit angeben.

Um synthetisierbaren Code zu generieren, müssen Sie also vor allem ein relativ klares Bild davon haben, wie Ihr Code zu Logikgattern und Flipflops wird. Das ist es wirklich.

wait until rising_edge(clk);ist sicherlich synthetisierbar, obwohl einige Werkzeuge seine Verwendung einschränken.

Der offensichtlichste erste Schritt besteht darin, die Warnungen zu überprüfen.

Xilinx-Tools erzeugen Protokolldateien, die vor allem warnen, was nicht das sein könnte, was der Programmierer beabsichtigt hat. Manchmal ist das ärgerlich, wenn Sie Unmengen von Warnungen über ungenutzte Signale haben, von denen Sie genau wissen, dass sie ungenutzt sind. Aber manchmal fängt es echte Fehler. Wenn Sie ein Neuling sind, ist die Wahrscheinlichkeit, dass Sie einen Fehler machen, erheblich höher.

Dann müssen Sie zeitliche Beschränkungen einrichten. Wie schnell nach einer steigenden Flanke an Takt A muss Datenleitung B gesetzt werden? Oder wie lange muss die Datenleitung B vor einer fallenden Flanke von Takt A gehalten werden? Durch zeitliche Beschränkungen können Sie all dies spezifizieren. Wenn Sie keine zeitlichen Beschränkungen haben, kann der Compiler davon ausgehen, dass Sie sich nicht besonders darum kümmern und Ihre Signale überall hin leiten könnten. Wenn Sie zeitliche Einschränkungen haben, stellt der Compiler sicher, dass Ihre Signale diese Einschränkungen erfüllen, indem er die Platzierung verschiebt. Und wenn es die zeitlichen Einschränkungen nicht einhalten kann, wird es eine Warnung ausgeben.

Wenn Ihr Problem darin besteht, dass die Ausgänge nicht das tun, was Sie erwarten, sehen Sie sich die E/A-Blöcke im Detail an. Jeder I/O-Pin hat ein Bit zugehöriger Logik und ein Flip-Flop. Die Reihenfolge, in der Sie Ihre Logik- und Zustandsvariablen in Ihrem Code angeben, macht es möglicherweise nicht möglich, dass Ihr Code in diese Architektur passt, sodass Sie eine zusätzliche Verzögerung erhalten, wo immer er platziert wird. Warnungen zu Zeitbeschränkungen werden Sie darüber informieren, ob dies passiert (vorausgesetzt, Sie haben Ihre Zeitbeschränkungen eingerichtet), aber um dies zu beheben, müssen Sie die Hardware verstehen und wissen, wie Ihr Design auf die Hardware abgebildet wird. Im Allgemeinen ist dies nur ein Problem, wenn Sie anfangen, hohe Taktraten zu erreichen, aber es ist erwähnenswert.

Ich habe mich nicht auf das Design integrierter Schaltkreise spezialisiert, aber mein erster Job nach dem Abschluss bestand darin, digitale Module in einer MCU-Designfirma zu entwerfen. Ich hatte damals sogar keine Ahnung von Verilog.

Meiner Erfahrung nach ist das Wichtigste, in Hardware zu denken. Lesen Sie mehrere Branchen-HDL-Module und überprüfen Sie den entsprechenden Schaltplan nach Möglichkeit mit Hilfe von EDA-Tools. Lernen und merken Sie sich einige grundlegende Bausteine ​​wie Kantenerkennung/Gray-Codierung/FIFO-Controller/FSM usw. Der synthetisierbare Code ist eine Teilmenge des gesamten Standards. Zum Zwecke eines robusten/fehlerfreien Designs ist die Sprachstruktur, die in einem Unternehmen tatsächlich verwendet wird, ferner eine Teilmenge von synthetisierbarem Code. Sie brauchen also nicht viel Sprachstruktur.

Eine Schaltung ist eine Verbindung zwischen verschiedenen Blöcken, die bestimmte Funktionen ausführen, und dieser Block selbst kann weiter in Verbindungen detaillierterer Elemente unterteilt werden. Um mit dem Design zu beginnen, verwenden Sie die grundlegenden Blöcke, um den Cuicuit mit Bleistift oder schematischem Zeichenwerkzeug zu entwerfen, oder untersuchen Sie ihn in Gedanken. Und notieren Sie den HDL-Code, um Ihr Design in einem ASCII-Format zu beschreiben.