Forum: FPGA, VHDL & Co. Interne Signale synchronisieren


von Jan B. (jan1)


Angehängte Dateien:

Lesenswert?

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:
1
module demuxModuleID (
2
  input      clk,    
3
  input      enable,  
4
  input    [25:0]  cmdIn,  
5
  output reg  [19:0]   cmdOut0,  
6
  output reg  [19:0]   cmdOut1,  
7
  output reg  [19:0]   cmdOut2,  
8
  output reg  [19:0]   cmdOut3,  
9
  output reg  [19:0]   cmdOut4,  
10
  output reg  [19:0]   cmdOut5,  
11
  output reg  [19:0]   cmdOut6,  
12
  output reg  [19:0]   cmdOut7  
13
);
14
15
always @(posedge clk)
16
begin
17
  if (enable)
18
  begin
19
    case (cmdIn[25:20])
20
      0: cmdOut0 <= cmdIn[19:0];
21
      1: cmdOut1 <= cmdIn[19:0];
22
      2: cmdOut2 <= cmdIn[19:0];
23
      3: cmdOut3 <= cmdIn[19:0];
24
      4: cmdOut4 <= cmdIn[19:0];
25
      5: cmdOut5 <= cmdIn[19:0];
26
      6: cmdOut6 <= cmdIn[19:0];
27
      7: cmdOut7 <= cmdIn[19:0];
28
    endcase
29
  end
30
end
31
32
endmodule

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

: Bearbeitet durch Moderator
von Lattice User (Gast)


Lesenswert?

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.

von Jan B. (jan1)


Angehängte Dateien:

Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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)?

von Lattice User (Gast)


Lesenswert?

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

von Jan B. (jan1)


Lesenswert?

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:
1
module inputCapture
2
(
3
  input            clk,
4
  input      [31:0]  dataIn,
5
  output reg  [31:0]  dataOut
6
);
7
8
always @(posedge clk)
9
begin
10
  dataOut <= dataIn;
11
end
12
13
endmodule

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Jan B. (jan1)


Lesenswert?

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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

von Jan B. (jan1)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Lattice User (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

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".

von Ein kleiner Tipp (Gast)


Lesenswert?

Lothar M. schrieb:

> nach der Taktflanke herrscht Hektik und Unruhe im FPGA

Klingt wie beim Sommerschlussverkauf (???)

von Duke Scarring (Gast)


Lesenswert?

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...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.