Ich habe gerade angefangen, digitales Logikdesign mit FPGAs zu lernen, und habe viele Projekte erstellt. Meistens (da ich eine Art Noob bin) habe ich ein Design, das perfekt simuliert (Verhaltenssimulation), aber nicht richtig synthetisiert.
Meine Frage lautet also: "Welche Entwurfsschritte 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 des RTL-Schaltplans, Nachsynthesesimulation, ...) sollte ich für die Best Practice lernen?
- Was alles sollte ich beachten, wenn ich meine Logik entwerfe (z. B. FSMs oder sequentielle Schaltungen), um unerwartete Ergebnisse zu vermeiden.
Ich verwende für meine Arbeit ein Xilinx Spartan 6 FPGA und eine Xilinx ISE Design Suite.
Antworten:
An einem Ort, an dem ich arbeitete, gab es zwei Lager von FPGA-Designern. Ein Lager, das ich simulieren, simulieren, simulieren oder gewürfelt nannte. Das andere Camp drehte sich alles um Design.
Die gewürfelten Jungs benutzten 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 mehrmals wiederholt, bis ein funktionierendes Design gefunden wurde.
Das Designcamp (das ich bevorzugt habe) würde die Wellenform auf Papier (oder digitalem Papier wie visio) entwerfen, genau das, was erforderlich war. Dann überlegen Sie sich 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 Simulationswellenform wurde mit der auf Papier entworfenen Wellenform verglichen, und es wurde erwartet, dass sie dieselbe ist.
Am Ende habe ich beides gemacht, manchmal bin ich in den Cubed-Modus geraten, und es hat nicht sehr viel Spaß gemacht. Ich stellte fest, dass ich manchmal mein Ziel aus den Augen verlor. 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 als darüber nachzudenken.
In welchem Lager würdest du lieber sein? Ich denke, es muss strenges Design geben, das tun, was für Sie funktioniert, aber ich denke, je detaillierter und strenger Sie entwerfen, 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, besteht darin, dass Sie darüber nachdenken müssen, was Sie tun. Es macht es einfach zu debuggen. Entwickeln Sie einen Design-Workflow, der dies ermöglicht. Machen Sie sich auch mit den Simulationswerkzeugen 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 für das FPGA-Design (meiner Meinung nach) ist ein gutes Testverfahren, mit dem Sie Ihr Design vollständig testen und auf Herz und Nieren prüfen können. Von einem FPGA-Design kann nicht erwartet werden, dass es "nur funktioniert". Es erfordert Mühe, um sicherzustellen, dass alle Teile funktionieren. Wenn Sie Fehler entdecken, kehren Sie zur Simulation und zum Design zurück und erfahren Sie, welche Unterschiede zwischen einem simulierten FPGA und RTL bestehen. Das hängt hauptsächlich mit der Erfahrung zusammen, aber wenn das Design in der Simulation funktioniert, aber nicht in der Hardware, 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, sonst kann sich die Metastabilität durch Ihr System ausbreiten. Wissen, was ein Synchronisierer mit zwei Rängen ist. Es gibt viele verschiedene Topologien für Reset-Schaltungen, wissen, wie man sie verwendet (es gibt einen großartigen Artikel im Internet, den ich jedoch nicht zur Hand habe).
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 bestimmten Anforderungen stellen, dann überlegen Sie sich diese selbst.
3) Die Matlab-Fixpunkt-Toolbox eignet sich hervorragend zum Simulieren von Steuerungssystemen und DSP-Anwendungen. Möglicherweise haben Sie jedoch keinen Zugriff darauf. Es ist eine großartige Möglichkeit, ein Design zu beweisen, bevor Sie codieren.
4) Design kommt zuerst, dann Codierung, dann Simulation.
5) Stark typisiert, halten Sie auch die Signalnamen auf dem Leiterplattenschema und der HDL konsistent. (Aus diesem Grund bevorzuge ich VHDL gegenüber Verilog.
quelle
Hauptsachen sind:
Ich habe mehrere ziemlich komplexe Designs beim ersten Test auf einem tatsächlichen FPGA korrekt (oder zumindest größtenteils korrekt) arbeiten lassen, indem ich den obigen Anweisungen gefolgt bin. Sie müssen das RTL-Schema nicht überprüfen, das ist nur extrem umständlich und für große Designs eine reine Zeitverschwendung. Eine Nachsynthesesimulation wäre viel nützlicher.
quelle
Ihr gesamter synthetisierbarer Code muss wie folgt ausgedrückt werden können:
Herstellerspezifische Grundelemente werden entweder explizit instanziiert oder vom Assistenten des Herstellers generiert oder durch sehr spezifische Codierungsmuster abgeleitet, sodass dort keine Mehrdeutigkeit bestehen sollte.
In VHDL können Sie beispielsweise keinen
wait for
synthetisierbaren Code verwenden. Um zu verstehen, warum, versuchen Sie, deterministischwait for 100 ns
mit LUTs oder Flip-Flops auszudrücken. Das kannst du 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 anhand seiner Zählung wissen, wann die Zeit abgelaufen ist. Die Synthese-Engine wird dieses Schema jedoch nicht automatisch erstellen. Sie müssen die Architektur in Bezug auf kombinatorische Logik (Gates / LUTs) und Register explizit beschreiben.
Das Wichtigste, was Sie beachten müssen, um synthetisierbaren Code zu generieren, ist ein relativ klares Bild davon, wie Ihr Code zu Logikgattern und Flip-Flops wird. Das ist es wirklich.
quelle
wait until rising_edge(clk);
ist sicherlich synthetisierbar, obwohl einige Tools die Verwendung einschränken.Der naheliegendste erste Schritt besteht darin, die Warnungen zu überprüfen.
Xilinx-Tools erstellen Protokolldateien, die vor allem warnen, was möglicherweise nicht den Absichten des Codierers entspricht. Manchmal ist dies ärgerlich, wenn Sie unzählige Warnungen vor nicht verwendeten Signalen haben, von denen Sie genau wissen, dass sie nicht verwendet werden. 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 Einschränkungen einrichten. Wie schnell muss nach einer ansteigenden Flanke auf Takt A die Datenleitung B gesetzt werden? Oder wie lange muss die Datenleitung B vor einer fallenden Flanke auf Takt A gehalten werden? Mit zeitlichen Einschränkungen können Sie all dies angeben. Wenn Sie keine zeitlichen Einschränkungen haben, kann der Compiler davon ausgehen, dass Sie sich nicht besonders darum kümmern und Ihre Signale überall weiterleiten können. Wenn Sie zeitliche Einschränkungen haben, stellt der Compiler sicher, dass Ihre Signale diese Einschränkungen erfüllen, indem Sie die Platzierung verschieben. Und wenn es die zeitlichen Einschränkungen nicht erfüllen kann, wird eine Warnung ausgegeben.
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. Jedem E / A-Pin ist ein bisschen Logik und ein Flip-Flop zugeordnet. Die Reihenfolge, in der Sie Ihre Logik- und Statusvariablen in Ihrem Code angeben, ermöglicht es möglicherweise nicht, dass Ihr Code in diese Architektur passt, sodass Sie eine zusätzliche Verzögerung von jedem Ort erhalten, an dem er gerade platziert wird. Warnungen zu Zeiteinschränkungen zeigen an, ob dies geschieht (vorausgesetzt, Sie haben Ihre Zeiteinschränkungen eingerichtet). Um dies zu beheben, müssen Sie jedoch die Hardware verstehen und wissen, wie Ihr Design der Hardware zugeordnet wird. Im Allgemeinen ist dies nur dann ein Problem, wenn Sie anfangen, hohe Taktraten zu erreichen, aber es ist erwähnenswert.
quelle