Kann ein FPGA-Design größtenteils (oder vollständig) asynchron sein?

Wir hatten einen sehr kurzen FPGA/Verilog-Kurs an der Universität (vor 5 Jahren) und wir haben immer und überall Uhren verwendet.

Ich fange jetzt wieder als Hobby mit FPGAs an und kann nicht anders, als mich über diese Uhren zu wundern. Sind sie unbedingt erforderlich oder kann ein FPGA-basiertes Design vollständig asynchron sein? Kann man ein komplexes Bündel von Logik aufbauen und Sachen so schnell wie möglich durchlaufen lassen?

Mir ist klar, dass es dabei viele Fallstricke gibt, wie zum Beispiel zu wissen, wann sich das Signal durch alle Teile der Schaltung ausgebreitet hat und sich der Ausgang stabilisiert hat. Das ist nebensächlich. Es ist nicht so, dass ich tatsächlich ein Design erstellen möchte, das vollständig asynchron ist, sondern nur, um mein Verständnis der Fähigkeiten zu verbessern.

Für mein Anfängerauge scheint es, dass das einzige Konstrukt, das unbedingt eine Uhr benötigt, eine ist reg, und ich verstehe, dass ein typisches FPGA (z. B. ein Cyclone II) seine Flip-Flops mit bestimmten Taktsignalen vorverdrahtet hat. Ist das richtig? Gibt es andere implizite Uhren wie diese und können sie normalerweise manuell durch das Design gesteuert werden?

Ich weiß, dass Simon Moore an der Universität Cambridge viel über asynchrones Design geforscht hat, einschließlich der Herstellung eines Testchips. Es erfordert einen völlig neuen Satz von Designwerkzeugen und hat seltsame Nebeneffekte: Beispielsweise ist die Ausführungsgeschwindigkeit umgekehrt proportional zur Temperatur.

Antworten (9)

Eine kurze Antwort wäre: ja; Eine längere Antwort wäre: Es ist Ihre Zeit nicht wert.

Ein FPGA selbst kann problemlos ein vollständig asynchrones Design ausführen. Das Ergebnis, das Sie erhalten, ist das Problem, da das Timing durch jedes FPGA nicht sehr vorhersehbar ist. Das größere Problem ist die Tatsache, dass Ihr Timing und das resultierende Design mit ziemlicher Sicherheit zwischen verschiedenen Orten und Routen variieren werden. Sie können Einschränkungen für einzelne asynchrone Pfade festlegen, um sicherzustellen, dass sie nicht zu lange dauern, aber ich bin mir nicht ganz sicher, ob Sie eine Mindestverzögerung angeben können.

Am Ende bedeutet dies, dass Ihr Design unvorhersehbar und möglicherweise sogar bei einer geringfügigen Designänderung vollständig variabel ist. Sie müssten jedes Mal, wenn Sie etwas ändern, den gesamten Timing-Bericht durchsehen, nur um sicherzustellen, dass es noch funktioniert. Auf der anderen Seite, wenn das Design synchron ist, suchen Sie am Ende von Place und Route einfach nach einem Pass oder Fail (vorausgesetzt, Ihre Einschränkungen sind richtig eingerichtet, was überhaupt nicht lange dauert).

In der Praxis streben die Leute nach vollständig synchronen Designs, aber wenn Sie ein Signal einfach puffern oder invertieren müssen, müssen Sie kein Flip-Flop durchlaufen, solange Sie es richtig einschränken.

Hoffe das klärt es ein wenig auf.

Ich musste einige Geräte mit asynchronen FPGA-Designs verwenden. Es war schwer, mit ihnen zu arbeiten. Bitte verwenden Sie zumindest zeitliche Beschränkungen
Es stimmt zwar, dass es möglich ist, asynchrone Designs mit einem FPGA zu implementieren, aber die meisten FPGAs sind so gebaut, dass sie speziell synchrone Designs unterstützen. Sie haben viele Ressourcen (PLLs, Taktverteilungsschaltungen und eine riesige Menge an Flip-Flops), die in einem asynchronen Design verschwendet werden.
Diese Antwort bietet keinen besonders guten Rat. Sie können ein taktloses FPGA erstellen und es vereinfacht die Platzierung und Route, beseitigt eine Menge Probleme in Bezug auf Timing-Anforderungen und kann aufgrund des feinkörnigen Pipelining einen messbar höheren Durchsatz haben. Das eigentliche Problem tritt auf, wenn Sie versuchen, eine getaktete Schaltung auf ein taktloses FPGA abzubilden, da sie sehr unterschiedliche Timing-Eigenschaften haben. Es ist möglich, es erfordert nur etwas mehr Front-End-Verarbeitung, um die Konvertierung durchzuführen. vlsi.cornell.edu/~rajit/ps/rc_overview.pdf
Sie KÖNNEN verzögerungsunempfindliches Design machen. Ich habe eine kleine Schaltung entworfen, die ein Bit in einem Flip-Flop speichert und ein Signal auslöst, wenn sie erkennt, dass das Bit gespeichert wurde. Es erkennt auch, ob das Bit tatsächlich empfangen wurde (im Gegensatz zu einer Null, weil eine 1 verzögert gesendet wird) und ist immun gegen Störungen. Die Schaltkreise müssen per Handshake kommunizieren und diese Art von Komponenten verwenden, um zu interagieren; Die Schaltungen selbst warten nur darauf, dass ihre Ausgabe abgeschlossen ist, und führen dann die gesamte Kommunikation durch. Keine Uhr.

„Kann man ein komplexes Bündel von Logik aufbauen und so schnell wie möglich Daten durchfließen lassen?“ Ja. Es wurden ganze CPUs gebaut, die vollständig asynchron sind – mindestens eine davon war die schnellste CPU der Welt. http://en.wikipedia.org/wiki/Asynchronous_circuit#Asynchronous_CPU

Es ärgert mich, dass Leute asynchrone Designtechniken ablehnen, obwohl sie theoretisch mehrere Vorteile gegenüber synchronen Designtechniken haben, nur weil (wie andere hier gesagt haben) asynchrone Designs nicht so gut von den verfügbaren Tools unterstützt werden.

Für mich ist das so, als würde ich empfehlen, alle Brücken aus Holz zu bauen, weil mehr Leute Holzbearbeitungswerkzeuge als Stahlbearbeitungswerkzeuge haben.

Glücklicherweise können einige der Vorteile des asynchronen Entwurfs erzielt werden, während immer noch hauptsächlich synchrone Entwurfstechniken verwendet werden, indem ein globaler asynchroner lokaler synchroner (GALS) Entwurf verwendet wird.

Ich denke genauso über die moderne Tendenz, Leiterplatten auf einem quadratischen Raster zu verlegen , obwohl die Vorteile der Migration viel geringer sind.
@romkyns - Das liegt eher an der Tatsache, dass das Schreiben von PCB-Software, die nicht-geradlinige Gitter verwendet, schwierig ist .
Ich bin gerade über diese Antwort von Ihnen auf eine frühere Frage gestolpert. GALS scheint ein Begriff für Designs zu sein, die mehrere synchrone Blöcke nehmen und diese miteinander verbinden, obwohl sie asynchron zueinander sind. Gibt es einen Begriff für Geräte, die von verschiedenen Taktgebern getaktet werden, die eine bekannte zeitliche Beziehung haben (z. B. die ansteigende Flanke des Taktgebers X (X+) wird nicht später als die ansteigende Flanke von Y (Y+) sein und deutlich vor der abfallenden Flanke von Y auftreten (Y-); X+ kann verwendet werden, um Daten zu takten, die von Daten abgeleitet sind, die von Y+ getaktet wurden, aber nicht umgekehrt; Y- taktet Daten, die von X+ abgeleitet sind).
@supercat: Ich vermute, Sie spielen auf die Vier-Phasen-Logik an . Es ist eines der mehrphasigen Taktsignale , das vergessen zu sein scheint.
Ich dachte nicht an dynamische Logik. Ich habe einfach darüber nachgedacht, wie man richtige kausale Beziehungen mit Taktsignalen sicherstellen kann, die leicht verzerrt sein könnten. Wenn eine ansteigende Flanke von Takt Nr. 2 durch Kombinieren von Takt Nr. 1 mit einer anderen Logik abgeleitet wird, so dass sie nach einer ansteigenden Flanke von Takt Nr. 1 auftritt, wird eine ansteigende Flanke von Takt Nr. 1 verwendet, um ein Signal zu speichern, das sich auf a ändert eine ansteigende Flanke von Takt Nr. 2 würde eine Wettlaufbedingung erzeugen. Die Verwendung einer fallenden Flanke von Takt Nr. 2 sollte stattdessen sicher sein.
@supercat: Richtig. Vielleicht denken Sie an Systeme mit einem Zwei-Phasen-Takt oder einem anderen Mehr-Phasen-Taktsystem. Lassen Sie mich wissen, wenn Sie einen besseren Begriff für diese Systeme finden.
@davidcary: So ungefähr, außer beide "Phasen" auf einem Draht - eine Phase wird von der steigenden Flanke und eine von der fallenden Flanke gesteuert. Grundsätzlich würde ich Latch-Clocks in vier Kategorien einteilen: sauberes Steigen, sauberes Fallen, spätes Steigen, spätes Fallen. Latches, die durch (L/CB) eine saubere steigende oder fallende Flanke getaktet werden, könnten Daten von jeder steigenden oder fallenden Flanke nehmen. L/CB eine späte ansteigende Flanke könnte Daten von L/CB sauber ansteigende Flanke an jeder abfallenden Flanke nehmen. L/CB durch spät fallende Flanke könnte Daten von L/CB sauber fallend oder beliebig steigend nehmen.
@davidcary: Vorausgesetzt, die schnellste Ausbreitungszeit für einen beliebigen Latch überschreitet die längste Haltezeit und vorausgesetzt, dass der längste Signalpfad von einer Taktflanke über die Clock-Gating-Logik und "späte" Latches, die von dieser Flanke ausgelöst werden, zu jedem von der ausgelösten Latch folgende Flanke die Mindestzeit zwischen Taktflanken nicht überschreitet, würde ich denken, dass ein solches Design unter jeder Kombination von Ausbreitungsverzögerungen absolut zuverlässig und frei von intern erzeugter Metastabilität sein sollte.
@supercat - interessanterweise habe ich kürzlich einen Prozessor entworfen, der diese Art von Ansatz verwendet: Ich habe einen einzelnen Takteingang, der mehrere Phasen ausführt, um (1) mehrere Registeraktualisierungen pro Zyklus zuzulassen, während ein Registerdateidesign verwendet wird, das nur einen einzigen Eingang hat Port und (2) haben eine zweistufige Pipeline, die vom Lesen des Befehls bis zum Zurückschreiben des Registers in 1,5 Zyklen abgeschlossen ist, so dass Pipeline-Hazards nur eine einzige Befehlslänge dauern. Eine Übersicht gibt es hier und eine ausführlichere Beschreibung hier in diesem Forumsthread .
Ich arbeite an einem PCB-Layout dafür, sobald ich Zeit finde (bisher ist es nur simuliert), aber ich verwende einen Inverter mit einer Kapazität, die seinem Ausgang hinzugefügt wird, um eine leichte Verzögerung des Schreibtakts der Registerdatei in Ordnung zu bringen um Zeit für alles andere zu haben, bevor das Ergebnis tatsächlich geschrieben wird. In der Simulation sieht alles gut aus... mal sehen, was passiert, wenn ich ein richtiges Board dafür habe. :)
@ Jules: Danke. Das CPU-Design sieht faszinierend aus.

Ein noch nicht erwähnter Faktor ist die Metastabilität. Wenn eine Latch-Schaltung von einer Folge von Eingaben/Übergängen getroffen wird, so dass der resultierende Zustand von Ausbreitungsverzögerungen oder anderen unvorhersehbaren Faktoren abhängen würde, gibt es keine Garantie dafür, dass der resultierende Zustand ein sauberes "High" oder "Low" sein wird. Betrachten Sie beispielsweise ein flankengetriggertes Flip-Flop, das derzeit ein "Low" ausgibt und dessen Eingang fast gleichzeitig mit dem Eintreffen einer Taktflanke von Low auf High wechselt. Wenn die Taktflanke lange genug vor der Eingangsänderung auftritt, bleibt der Ausgang einfach bis zur nächsten Taktflanke niedrig. Wenn die Taktflanke lange genug nach dem Eingangswechsel erfolgt, schaltet der Ausgang schnell einmal von Low auf High und bleibt dort bis zur nächsten Taktflanke. Wenn keine dieser Bedingungen zutrifft,. Es kann niedrig bleiben oder schnell einmal umschalten und hoch bleiben, aber es kann eine Weile niedrig bleiben und dann umschalten oder umschalten und dann einige Zeit später zurückschalten oder ein paar Mal hin und her wechseln usw.

Wenn ein Design vollständig synchron ist und alle Eingänge doppelt synchronisiert sind, ist es sehr unwahrscheinlich, dass ein Zeitimpuls den ersten Latch eines Synchronisierers so trifft, dass er zum perfekten Zeitpunkt schaltet, um den zweiten zu verwirren verriegeln. Im Allgemeinen ist es sicher, solche Dinge als "einfach nicht passieren" zu betrachten. In einem asynchronen Design ist es jedoch oft viel schwieriger, über solche Dinge nachzudenken. Wenn eine Timing-Beschränkung für eine Latch-Schaltung (nicht nur Flip-Flops, sondern jede Kombination von Logik, die als Latch fungieren würde) verletzt wird, ist nicht abzusehen, was der Ausgang tun wird, bis das nächste Mal eine gültige Eingangsbedingung vorliegt, die den Latch erzwingt in einen bekannten Zustand. Es ist durchaus möglich, dass verzögerte Ausgänge dazu führen, dass die Zeitbeschränkungen von nachgeschalteten Eingängen verletzt werden, was zu unerwarteten Situationen führt.

Der sicherste Weg, eine asynchrone Schaltung zu modellieren, wäre, fast jede Ausgangsschaltung für eine kurze Zeit einen "X" -Ausgang erzeugen zu lassen, wenn sie zwischen "0" und "1" wechselt. Leider führt dieser Ansatz oft dazu, dass fast alle Knoten "X" anzeigen, selbst in Fällen, die in Wirklichkeit mit ziemlicher Sicherheit zu einem stabilen Verhalten geführt hätten. Wenn ein System funktionieren kann, wenn simuliert wird, dass alle Ausgänge sofort nach einer Eingabeänderung zu "X" werden und "X" bleiben, bis die Eingänge stabil sind, ist das ein gutes Zeichen dafür, dass die Schaltung funktioniert, aber asynchrone Schaltungen dazu bringt, unter solchen Einschränkungen zu arbeiten ist oft schwierig.

Wirklich gibt es DREI Arten von Designs.

  1. Kombinatorisch. Es gibt keine Uhren und keine Rückkopplungspfade und das System hat kein "Gedächtnis". Wenn sich eine oder mehrere Eingaben ändern, werden die Änderungen durch die Logik gewellt. Nach einiger Zeit geht der Ausgang in einen neuen Zustand über, in dem er bleibt, bis sich die Eingänge wieder ändern.
  2. Synchron sequentiell. Ein System besteht aus Registern und Blöcken kombinatorischer Logik, die Register werden von einer kleinen Anzahl (oft 1) von Uhren getaktet. Wenn mehrere Takte vorhanden sind, können besondere Vorkehrungen für Signale erforderlich sein, die von einer Taktdomäne zu einer anderen übertragen werden.
  3. Asynchron sequentiell. Es gibt Rückkopplungspfade, Latches, Register oder andere Elemente, die dem Design Erinnerungen an vergangene Ereignisse geben und die nicht durch leicht zu analysierende Taktleitungen getaktet werden.

Im Allgemeinen gehen die Tools beim Synthetisieren/Optimieren der kombinatorischen Logik davon aus, dass alles, was zählt, das Endergebnis und die maximale Zeit ist, die benötigt wird, um sich auf dieses Ergebnis festzulegen.

Sie können ein rein kombinatorisches Design erstellen, das zum richtigen Ergebnis führt. Die Ausgänge können sich in beliebiger Reihenfolge ändern und können sich mehrmals ändern, bevor sie ihre endgültigen Werte erreichen. Solche Konstruktionen verschwenden sehr viel Logikressourcen. Die meisten Logikelemente verbringen die meiste Zeit im Leerlauf, während Sie in einem sequentiellen System diese Elemente zur Verarbeitung mehrerer Datenelemente hätten wiederverwenden können.

In einem sequentiellen synchronen System kommt es nur darauf an, dass die Ausgänge des kombinatorischen Blocks ihren korrekten Zustand erreicht haben, wenn sie in das nächste Flip-Flop getaktet werden. Es spielt keine Rolle, in welcher Reihenfolge sie sich ändern oder ob es sich um Störungen auf dem Weg handelt. Auch hier können die Tools dies leicht in Logik umwandeln, die die richtige Antwort liefert, vorausgesetzt, die Uhr ist langsam genug (und sie können Ihnen sagen, ob die Uhr, die Sie verwenden möchten, langsam genug ist).

In einem asynchronen sequentiellen System gehen diese Annahmen aus dem Fenster. Störungen können eine Rolle spielen, die Reihenfolge der Ausgabeänderungen kann eine Rolle spielen. Sowohl die Tools als auch die FPGAs selbst wurden für synchrone Designs entwickelt. Es wurde viel über die Möglichkeit diskutiert (google asynchrones FPGA-Design, wenn Sie mehr wissen möchten) über die Möglichkeit, asynchrone Systeme entweder auf Standard-FPGAs oder auf speziell entworfenen zu implementieren, aber es liegt immer noch außerhalb der allgemein akzeptierten Designpraxis

Wenn Ihre Designanforderungen langsam genug sind, dass viele interne Verzögerungen immer noch um Größenordnungen länger sind als die Zeiten, die Ihnen wichtig sind, ist dies natürlich kein Problem, und Sie können den Timing-Bericht anzeigen, um dies im Auge zu behalten, aber Es gibt eine Grenze für das, was Sie ohne interne Statusinformationen sinnvoll tun können. Wenn Sie nur so etwas wie einen Multiplexer mit 100 Eingängen erstellen möchten, denken Sie daran, dass jeder Eingang eine andere Laufzeitverzögerung hat. Tatsächlich können Sie einige interessante und chaotische Effekte mit einer großen Anzahl von oszillierenden Rückkopplungsschleifen mit unvorhersehbarer Verzögerung erhalten - vielleicht könnte ein vollständig asynchroner FPGA-basierter Synthesizer der nächste "Analog" sein.

Ja, du kannst. Sie können die Flipflops vollständig ignorieren und alles aus LUTs bauen. Und/oder Sie können die Zustandselemente der meisten Xilinx-FPGAs als (pegelgetriggerte) Latches anstelle von (flankengetriggerten) Flipflops verwenden.

Eine Gefahr dabei besteht darin, dass, wenn man den Logik-Compiler nicht einschränkt, er möglicherweise eine Logik erzeugt, die für einige Gatter eine negative Laufzeit hat. Wenn man beispielsweise and angibt X=(someComplexFormula)und Y=X & Dder Compiler diese Formel für X ersetzt und feststellt, dass X & Ddies äquivalent zu A & Dist, ersetzt der Compiler möglicherweise compute Y in Bezug auf A und D und nicht in Bezug auf X, wodurch die Berechnung von Y ermöglicht wird um schneller fortzufahren als die von X. Solche Substitutionen sind mit der kombinatorischen Logik gültig, richten aber in der asynchronen sequentiellen Logik Chaos an.
@supercat - Ich habe noch nie mit den Tools von Xilinx gearbeitet, aber wenn ich mit Altera-FPGAs gearbeitet habe, hatten Sie immer die Möglichkeit, kritische Pfade als verbundene Gate-Module und nicht in RTL anzugeben, an welchem ​​​​Punkt solche Optimierungen sind deaktiviert.
@Jules: Alle meine programmierbaren Logikdesigns haben Abel verwendet, eine etwas doofe Sprache, die es jedoch ermöglicht, Dinge auf eine Weise zu spezifizieren, die einige CPLDs implementieren können, die jedoch für ein VHDL- oder Verilog-Synthesetool Schwierigkeiten bereiten könnten. Bei einem meiner Projekte habe ich beispielsweise die Tatsache ausgenutzt, dass Xilinx-Teile eine Uhr, ein asynchrones Setzen und ein asynchrones Zurücksetzen haben, um ein asynchron ladbares Schieberegister zu implementieren. Wenn ich solche Dinge in einem FPGA tun muss, obwohl ich noch nie Verilog oder VHDL verwendet habe, wie soll ich dann lernen, was dazu erforderlich ist? Übrigens, wenn die Erinnerung dient, habe ich T-Flops für den Schalthebel verwendet und ...
... das Timing war so, dass das asynchrone Schreiben nur zu Zeiten erfolgen konnte, in denen der T-Eingang niedrig war, vorausgesetzt, dass das asynchrone Schreiben weit genug darüber hinausgehen würde, wenn ein Nop-Takt nahe dem Beginn eines Schreibimpulses auftritt um einen stabilen Wert zu gewährleisten, und wenn die Nop-Uhr gegen Ende auftritt, würde sie einfach einen immer noch stabilen Wert zwischenspeichern. Ich bin mir nicht sicher, wie man solche Fälle in VHDL oder Verilog effizient handhaben könnte.
@supercat - Bei einem ähnlichen Problem sehe ich im Cyclone IV Device Handbook, dass der beste Ansatz für dasselbe Problem darin besteht, die Option "LAB-weites synchrones Laden" zu verwenden (ein "LAB" ist eine Gruppe von 16 Logikelementen , wenn also die Größe eines solchen Registers kein Vielfaches von 16 Bit ist, werden einige Bits verschwendet, aber dies scheint sowieso die nützlichste Option zu sein). Ich habe jetzt zwei Möglichkeiten: Ich kann funktionales Verilog schreiben, bei dem das Synthesetool eine Methode zur Implementierung des erforderlichen Registers auswählen muss (was normalerweise die beste Option wäre), oder, wenn ich ein strenges Timing habe ...
... Anforderungen Ich kann es zwingen, dies fest zu verdrahten: Wenn ich die Liste der verfügbaren Low-Level-Module auf dem Gerät durchsehe, finde ich, dass lpm_ffein Flipflop vom Typ d oder t mit synchroner Last implementiert werden kann. Durch die Verwendung dieses Moduls kann ich sicher sein, dass diese Funktionen genau auf die Low-Level-Funktionen des Geräts abgebildet werden, ohne dass sie möglicherweise wegoptimiert werden.

Wie @Andrey betonte, ist es Ihre Zeit nicht wert. Insbesondere die Tools tun dies nicht, sodass Sie völlig auf sich allein gestellt wären. Da sie außerdem eingebaute Register haben, würden Sie nichts sparen, wenn Sie sie nicht verwenden.

Ja. Wenn Sie keine Prozesstypkonstrukte haben, sollte es keine Dinge wie das Ableiten von Registern tun. Es wird Dinge wie Onboard-Speicher geben, die Takte benötigen, obwohl Sie diese, wenn Sie wirklich wollen, wahrscheinlich asynchron generieren könnten.

Wollten Sie dies zu einer einzigen Antwort machen?

FWIW Ich dachte, ich sollte hinzufügen, dass ein offensichtliches Ziel bei asynchronen Logiklösungen die globale Reduzierung des Stromverbrauchs sein würde.

Diese globalen Uhren/PLL/Puffer verbrauchen jede Menge Joule.

Da FPGA-Lösungen in batteriebetriebene Bereiche vordringen (z. B. Lattice Icestick), wird dieser Aspekt viel mehr Aufmerksamkeit erregen.

Dies ist ein guter Punkt, obwohl es sich lohnt zu bedenken, dass eine schlecht entworfene kombinatorische Schaltung, die die gleiche Operation wie eine sequentielle Schaltung durchführt, in einigen Fällen viele vorübergehende Übergänge machen könnte, wenn Teilergebnisse berechnet und die endgültige Ausgabe aktualisiert werden, um sie zu berücksichtigen. und in CMOS-Schaltungen (wie es bei den meisten FPGAs der Fall ist) ist der Stromverbrauch ungefähr proportional zur Anzahl der Übergänge. Uhren können unnötige Übergänge verursachen, aber Sie können auch viele Energieeinsparungen vornehmen, indem Sie Uhren in Teilen der Schaltung deaktivieren, die im Moment nicht benötigt werden.