Hallo,
Ich muss meinem Beitrag vorausschicken, dass ich bei der Entwicklung von
FPGA-Anwendungen nicht besonders beschlagen bin. Ich lasse mich also
gerne auch zu allgemeinen Themen wie Designgrundsätze oder Ähnlichem
belehren, aber ich bitte auch um Nachsicht, denn ich kann vielleicht
nicht jedes Problem treffend genug benennen, um danach zu googeln.
Also zur Sache: Ich habe einen einfachen Decoder entworfen, der ein
Datenwort entgegennimmt und den relevanten Teil auf verschiedenen
Ausgängen weiterleiten kann. Die Bits 25 bis 20 im Datenwort entscheiden
dabei, auf welchem Ausgang die Bits 19 bis 0 weitergeschickt werden.
Bei der Synthese erstellt mir Quartus eine RTL-Struktur, die ich als
Bild angehängt habe. Im zweiten Bild habe ich den entscheidenden Teil
nachgezeichnet, damit man sich nicht erst ins Leitungsgewirr einfinden
muss.
Mein Problem ist nun: Der Rumpf des Datenwortes ist wegen der
Verzögerung durch den Decoder schneller an den Ausgangsregistern als die
Adresse. Dadurch kann es zu der Situation kommen, dass Daten über
falsche Ausgänge verschickt werden.
Meine Frage ist nun: Wie zwinge ich den Synthesizer, die internen
Signale mit Flipflops synchron zu halten? Oder habe ich einfach schlecht
designt und kann das Problem einfach umgehe?
Ich bin für jeden Anstoß, Ansatz, Hilfestellung, Link oder Hinweis
dankbar.
Zu den Formalien: Ich versuche mich hier an einem Cyclone-V-SoC, meine
Entwicklungsumgebung ist Quartus 15.1 und ich schreibe meinen Code in
Verilog. Hier der betreffende Auszug:
Jan B. schrieb:> Meine Frage ist nun: Wie zwinge ich den Synthesizer, die internen> Signale mit Flipflops synchron zu halten?
Es ist ganz einfach: du nimmst ganz einfach nur 1 einzigen Takt im
Design. Dann ist das gesamte Design synchron.
Ein synchrones Design funktioniert im FPGA in etwa so: nach der
Taktflanke herrscht Hektik und Unruhe im FPGA, bis alle Signale durch
die Kombinatorik gelaufen sind. Und rechtzeitig vor dem nächsten Takt
muss alles ruhig sein, damit die Flipflops wieder korrekte Daten
übernehmen können.
Ergo wirst du natürlich kurz mal irgendwelche schnelleren oder
langsameren Signale haben. Oder auch jede Menge Glitches. Aber weil zur
nächsten Taktflanke wieder Ruhe herrscht, übernimmt das getaktete
Flipflop einen definierten Pegel.
> Dadurch kann es zu der Situation kommen, dass Daten über falsche> Ausgänge verschickt werden.
Da hast du ein anderes Problem. Oder gar ein asynchrones Design. Das
kann man aber am geposteten Quellcode nicht erkennen...
> Also zur Sache: Ich habe einen einfachen Decoder entworfen, der ein> Datenwort entgegennimmt und den relevanten Teil auf verschiedenen> Ausgängen weiterleiten kann.
Du hast in der geposteten Skizze elegant jede Art der Synchronisierung
weggelassen. Das kann so nicht funktionieren. Woher kommt der Takt in
deinem Design? Zu was ist der Synchron?
Jan B. schrieb:> Im zweiten Bild habe ich den entscheidenden Teil> nachgezeichnet, damit man sich nicht erst ins Leitungsgewirr einfinden> muss.
Das hast du nicht hinbekommen. Das 2. Bild hat mit dem ersten nichts zu
tun.
Im ersten Bild sind die von dir gewünschten (und auch korrekt in Verilog
beschriebenen) Flip-Flops vorhanden. Was dich vermutlich verwirrt hat,
ist die Rückführung des Ausgangs auf einen Multiplexer. Das dient zur
Erhaltung der Registerinhalte (und damit des Ausgangs) wenn bei einem
Takt der Ausgang nicht ausgewählt ist.
Lothar M. schrieb:> Es ist ganz einfach: du nimmst ganz einfach nur 1 einzigen Takt im> Design. Dann ist das gesamte Design synchron.
Erstmal vielen Dank für deine ausführliche Antwort. Eine weiterführende
Frage habe ich dazu noch: Du schilderst ja, was in einem synchronen
Design auf "Gatterebene" passiert. Nun entwickele ich ja selbst in einer
HDL. Ich habe dabei einen einzigen Takt und lasse den Code in allen
Modulen bei einer steigenden Flanke ausführen. Reicht das au HDL-Ebene,
um Synchronität zu gewährleisten?
Und sorgt der Synthesizer selbstständig dafür, dass die Synchronität
auch auf Gatterebene noch vorhanden ist? Wie würde der Synthesizer
beispielsweise bei einem Design verfahren, dass so viele Logikgatter
hintereinander benötigt, das deren Gesamtlaufzeit eine Taktperiode
übersteigt?
Lothar M. schrieb:> Da hast du ein anderes Problem. Oder gar ein asynchrones Design. Das> kann man aber am geposteten Quellcode nicht erkennen...
Wäre es denn bei meinem Design nicht denkbar, dass der Decoder zum
auflösen der 6-Bit-Adresse länger als einen Takt braucht? Dann würde
einen Takt lang ein Rumpf auf der Adresse ausgegeben werden, die vorher
vom Decoder ausgegeben wurde. Oder würde der Synthesizer sowas gar nicht
zulassen?
Lothar M. schrieb:> Das kann so nicht funktionieren. Woher kommt der Takt in> deinem Design? Zu was ist der Synchron?
Also wie schon oben kurz angerissen verwende ich in meinem ganzen System
nur einen einzigen Takt, der in dem hier dargestellten Beispiel die
Flipflops steuert. Auf diesen Takt "triggern" alle Module. Welche
Auszüge müsste ich denn bei künftigen Fragen mitliefern, damit das mit
den Synchronität etwas nachvollziehbarer wird?
Lattice User schrieb:> Das hast du nicht hinbekommen. Das 2. Bild hat mit dem ersten nichts zu> tun.
Jetzt stehe ich natürlich blöd da, aber du hast selbstverständlich
recht. Und zwar auch mit deiner Vermutung, dass die Rückführung mich
aufs Glatteis geführt hat. Also: Mein zweiter Versuch lässt vielleicht
ein wenig mehr Ähnlichkeit mit dem Ergebnis der Synthese erkennen.
Allerdings ging es mir auch nicht um die Flipflops selbst, sondern um
den Teil des Netzwerks, der vor dem FF ist, weil ich dort den "Fehler"
vermute.
Jan B. schrieb:> Nun entwickele ich ja selbst in einer HDL.
Zu deutsch: "Hardware Beschreibungssprache". Du musst dir also eine
Hardware vorstellen oder skizzieren, und die dann beschreiben. Aus
diesem Grund bist du auch "auf HDL-Ebene" direkt an der Hardware und
somit auch auf "der Gatterebene".
> Ich habe dabei einen einzigen Takt und lasse den Code in allen Modulen> bei einer steigenden Flanke ausführen. Reicht das au HDL-Ebene,> um Synchronität zu gewährleisten?
Ja.
> Und sorgt der Synthesizer selbstständig dafür, dass die Synchronität> auch auf Gatterebene noch vorhanden ist?
Ja.
> Wie würde der Synthesizer beispielsweise bei einem Design verfahren,> dass so viele Logikgatter hintereinander benötigt, das deren> Gesamtlaufzeit eine Taktperiode übersteigt?
Der Synthesizer noch nicht, aber P&R wird es tun, WENN du auf den Takt
ein Timing-Constraint gesetzt hast.
> Wäre es denn bei meinem Design nicht denkbar, dass der Decoder zum> auflösen der 6-Bit-Adresse länger als einen Takt braucht?
Nein. So schnell kannst du gar nicht takten...
> Oder würde der Synthesizer sowas gar nicht zulassen?
Dem Synthesizer ist ziemlich viel recht egal. Der lässt dich auch Sachen
machen, die sicher nicht funktionieren (Stichwort: kombinatorische
Schleife). Er informiert oder warnt dich bestenfalls...
> Also wie schon oben kurz angerissen verwende ich in meinem ganzen System> nur einen einzigen Takt, der in dem hier dargestellten Beispiel die> Flipflops steuert.
Und: ist dieser Takt synchron zu den Eingangsdaten? Oder ändern die
sich zu irgendwelchen x-beliebigen Zeitpunkten (bezogen auf den
FPGA-Takt)?
Jan B. schrieb:> Allerdings ging es mir auch nicht um die Flipflops selbst, sondern um> den Teil des Netzwerks, der vor dem FF ist, weil ich dort den "Fehler"> vermute.
Bei einem synchronen Design, und dein Schnipsel ist synchron, sollten
solche Laufzwitfehler nicht auftreten, vorrausgestzt deine
Timingconstraints sind vollständig und stimmen. Mit Hilfe der
Constraints stellt die Toolchain bei P&R sicher dass alle Signale
rechtzeitig vor der Clockflanke am FF ankommen. Wenn es Decive nicht
hergibt (z.B. weil zu langsam) gibt es eine detalierte Fehlermeldung
Lothar M. schrieb:> Und: ist dieser Takt synchron zu den Eingangsdaten? Oder ändern die> sich zu irgendwelchen x-beliebigen Zeitpunkten?
Das war ein guter Tipp, dem ich nochmal nachgegangen bin. Die Daten
kommen über die HPS-FPGA-Bridge und sind natürlich nicht synchron zum
Referenztakt der FPGA. Nach deinem Hinweis habe ich zwischen Bridge und
FPGA Flipflops platziert und jetzt tritt mein Fehler nicht mehr auf.
Ich vermute, dass es bisher zu Fehlern gekommen ist, wenn das
Eingangssignal sehr kurz vor einer steigenden Taktflanke eingetroffen
ist.
Lattice User schrieb:> vorrausgestzt deine Timingconstraints sind vollständig und stimmen
Ich habe noch nicht viel Erfahrung mit FPGAs und bastele im Moment nur
an sehr einfachen Testprojekten herum. Über die Timingconstraints bin
ich in den Quartus-Handbüchern und den Onlinekursen von Altera schon
öfter gestolpert und ich habe den Eindruck, dass es sich um ein
praktisches und mächtiges Tool bei der Entwicklung handelt. Bisher habe
ich aber einen Bogen darum gemacht in der naiven Hoffnung, erstmal ohne
auszukommen. Daher kann ich leider keine Meldungen von TimeQuest
liefern.
Hier zum Abschluss die denkbar einfache Lösung des Problems mit dem
asynchronen Eingang:
Jan B. schrieb:> und jetzt tritt mein Fehler nicht mehr auf.
Glück? Oder simpler Zufall?
Denn das eigentliche Problem hast du immer noch: die Daten sind
asynchron zum Takt. Du brauchst irgendeinen Validierungsmechanismus,
also ein zusätzlichse Signal, das anzeigt, dass "jetzt" die Daten
garantiert stabil und bereit für die Übernahme sind.
Lothar M. schrieb:> Du brauchst irgendeinen Validierungsmechanismus,> also ein zusätzlichse Signal, das anzeigt, dass "jetzt" die Daten> garantiert stabil und bereit für die Übernahme sind.
Das verstehe ich noch nicht so wirklich. Egal zu welchem Zeitpunkt ein
neues Datum eintrifft, es wird dem Rest der Schaltung erst mit der
nächsten steigenden Taktflanke zugeführt. Habe ich das Signal dadurch
nicht gewissermaßen auf den Takt des FPGAs synchronisiert? Ab diesem
Punkt kann ich dann doch auf Handshake- oder Indukationsleitungen
verzichten, oder?
Jan B. schrieb:> Egal zu welchem Zeitpunkt ein neues Datum eintrifft, es wird dem Rest> der Schaltung erst mit der nächsten steigenden Taktflanke zugeführt.
Aber das "Datum" sind doch mehrere Bits, oder nicht? Und genau dann kann
es passieren, dass du z.B. schon 3 Bits vom "neuen Datum" übernimmst und
die anderen Bits noch "alt" sind...
Lothar M. schrieb:> Aber das "Datum" sind doch mehrere Bits, oder nicht? Und genau dann kann> es passieren, dass du z.B. schon 3 Bits vom "neuen Datum" übernimmst und> die anderen Bits noch "alt" sind...
Ich verstehe jetzt was du meinst. Vorher war der Eingang meiner gesamten
Schaltung asynchron, jetzt ist es natürlich immer noch der Eingang der
Flipflops.
Da das FF eine geringere "Laufzeit" hat als der Eingang der
nachgelagerten Schaltung, kommt es jetzt bei mir nicht mehr zu Fehlern.
Wenn jetzt aber die Daten am Eingang genau während einer steigenden
Taktflanke eintreffen, werden sie aber trotzdem nicht korrekt in das FF
"gelatcht".
Zwischen Prozessor und FPGA gibt es GPIO-Leitungen. Davon werde ich eine
nehmen und und als "Data Ready" Leitung auf den Enable-Eingang der FFs
führen, die während des Anlegens eines Datenwortes auf Low geht. Vielen
Dank für den zusätzlichen Hinweis.
Jan B. schrieb:> kommt es jetzt bei mir nicht mehr zu Fehlern.
Fast richtig: es kommt viel seltener zu Fehlern...
Die Vorgehensweise mit dem DataValid Signal ist der einzig sichere Weg.
Lothar M. schrieb:> Die Vorgehensweise mit dem DataValid Signal ist der einzig sichere Weg.
Meine Kristalkugel dagt mir allerdings, dass Jan das Signal direkt als
FF Enable verwenden will. Also ohne es einzusynhronisieren.
Lattice User schrieb:> Lothar M. schrieb:>> Die Vorgehensweise mit dem DataValid Signal ist der einzig sichere Weg.>> Meine Kristalkugel dagt mir allerdings, dass Jan das Signal direkt als> FF Enable verwenden will. Also ohne es einzusynhronisieren.
Wenn das externe Signal als "Takt" für die erste Flipflop Stufe
verwendet, dann hat man natürlich wieder 2 Takte im FPGA und muss sich
wieder Gedanken um Synchronisieren machen. Kurz: damit würde nichts
gewonnen...
Es wäre natürlich schon korrekt, "Data Ready" zum Eintakten des
Daten/Adresswortes zu verwenden, da ja (hoffentlich) durch die
Ansteuerung sichergestellt wird, dass die Flanke auf "Data Ready" erst
nach Anlegen der neuen Daten erzeugt wird.
Jedoch darf "Data Ready" nicht anschließend als Takt für die
Registerzugriffe verwendet werden, sondern nur das mittels CLK
einsynchronisierte "Data Ready".
Ein kleiner Tipp schrieb:>> nach der Taktflanke herrscht Hektik und Unruhe im FPGA>> Klingt wie beim Sommerschlussverkauf (???)
Genau, und wenn der durch ist, ist Ruhe bis zum Winterschlussverkauf
(=nächste Taktflanke).
Vor dem Takt ist nach dem Takt, oder so ählich...