FPGA Internal Timing Constraint fehlgeschlagen

Ich versuche derzeit, einen IP-Core auf einem Cyclone V 5CSEBA6U23I7 FPGA-HPS-System mit Altera Quartus II und TimeQuest Analyzer zu implementieren.
Der unten eingefügte Verilog-Code erzeugt ein Timing-Problem, nämlich die Zuweisung fifo_wdata_289[255:0] <= {fifo_out,fifo_wdata_289[255:16]};, die die Ausgabe eines FIFO in ein anderes FIFO-Registerarray schreibt.
Die verwendeten FIFOs sind asynchron, aber die verwendeten Signale befinden sich in derselben Taktdomäne.
Dies wird mit einem Taktversatz von -2,255 ns auf den Chip gebracht , was etwas weniger als eine ganze Periode ist ( 288-MHz-Takt => 3,47 ns ), und TimeQuest beschwert sich, dass die Einschränkungen verletzt werden.
Die Empfehlung von TimeQuest lautet, die Ebenen der kombinatorischen Logik für den Pfad zu reduzieren(Issue Long Combinational Path ) mit zusätzlichen Ebenen der kombinatorischen Logik = 1.

Der 288-MHz-Takt wird über PLL generiert und ich verwende Timeconstraint-Dateien (sdc) mit den Befehlen derive_pll_clocks und derive_clock_uncertainty.

Meine Frage ist nun, wie ich dieses Problem lösen kann, da ich nur eine Schicht kombinatorischer Logik (Demuxer und Routing, wie von der Aufgabe vorgeschlagen) habe und daher keine Ahnung habe, wie ich das reduzieren kann. Gibt es eine andere Möglichkeit, um sicherzustellen, dass die Timing-Anforderung erfüllt ist, oder gibt es eine bessere Möglichkeit, diese Zustandsmaschine zu programmieren?
Vielen Dank für Ihre Hilfe.

            case(stateProc)
                2'b00:
                begin
                    if(~fifo_empty&~fifo_full_289)
                    begin
                        fifo_wdata_289[255:0] <= {fifo_out,fifo_wdata_289[255:16]};
                        fifo_wdata_289[287:256] <= {2'b11,fifo_wdata_289[287:258]};
                        if(imgSize >= maxImgSize - 32'd2)//image done, transmit data and fire irq
                        begin
                            fifo_wdata_289[288] <= 1;
                            stateProc <= 2'b01;
                            imgSize <= 32'd0;
                        end
                        else if(fifo_wdata_289[258])//process transfer without irq //258 high means that 256 has been written in this cycle and 258 in the previous cycle
                        begin
                            fifo_wdata_289[288] <= 0;
                            stateProc <= 2'b01;
                            imgSize <= imgSize + 32'd2;
                        end
                        else//accumulate more data
                        begin
                            fifo_wdata_289[288] <= 0;
                            stateProc <= 2'b00;
                            imgSize <= imgSize + 32'd2;
                        end
                    end
                    else
                    begin
                        fifo_wdata_289 <= fifo_wdata_289;
                        imgSize <= imgSize;
                        stateProc <= 2'b00;
                    end
                end
                2'b01:
                begin
                    fifo_wdata_289 <= fifo_wdata_289;
                    imgSize <= imgSize;
                    stateProc <= 2'b11;
                end
                2'b11:
                begin
                    fifo_wdata_289 <= 0;
                    imgSize <= imgSize;
                    stateProc <= 2'b00;
                end
            endcase

BEARBEITEN:

Die Fehlerpfade von TimeQuest sehen meistens so aus:
Slack:
-3.178

From Node:
soc_system:u0|CamConnector:camconnector_0|FIFO_289:FIFO_inst_289|dcfifo:dcfifo_component|dcfifo_6up1:auto_generated|wrptr_g[0]

To Node:
soc_system:u0|CamConnector:camconnector_0 |fifo_wdata_289[267]

EDIT2:
Ich verwende derzeit MLAB-Zellen als FIFO-Speicher, die für 290 MHz ausgelegt sind.
Beide FIFOs sind asynchron und haben eine Synchronisationseinstellung von 3.
Timing Closure Recommandations von TimeQuest meldet die folgenden zwei Probleme:

  1. Unausgeglichene kombinatorische Logik
  2. Langer kombinatorischer Pfad

Antworten (2)

da ich nur eine Schicht kombinatorischer Logik habe (Demuxer und Routing, wie von der Aufgabe vorgeschlagen)

Nein das hast du nicht. Es gibt auch das Clearing in stateProc==2'b11. Aber ich gehe davon aus, dass die Cyclone LUTs groß genug sind, dass sie gleichzeitig ein zusätzliches UND-Gatter umfassen können.

Ich schlage jedoch vor, dass Sie auch den vom Tool gemeldeten fehlerhaften Pfad posten. Denn hier passt etwas nicht zusammen. Der Pfad für fifo_wdata_289[288] ist komplexer und Sie sagen, dass er das Timing passiert . Ich wäre nicht überrascht, wenn die Mux-Steuersignale: fifo_empty, fifo_full_289, stateProc usw. zusammen mit dem Laufwerksbaum auch im fehlerhaften Timing-Pfad liegen, da Sie viele FFs von einem Signal aus steuern.

Wenn nicht, können Sie wirklich nur mit einer niedrigeren Geschwindigkeit laufen. Es hat keinen Sinn, mit der Uhr herumzuspielen, da die Schaltung ihre eigenen Signale verwendet ( fifo_wdata_289 [255:0] <= {fifo_out, fifo_wdata_289[255:16] };) Wenn Sie also die Uhr verzerren oder invertieren, fifo_wdata_289[255: 16] wird später herauskommen und somit erneut das Timing verfehlen. Vielleicht haben Sie Glück und fifo_out kommt zu spät und verursacht den Timing-Fehler, aber sehen Sie sich noch einmal den Timing-Bericht des fehlerhaften Pfads an.

Wie auch immer, das Verzerren einer Uhr ist etwas, das in einem ASIC durchgeführt werden kann, aber ich würde es nicht mit einem FPGA versuchen. Ich glaube nicht, dass Sie die Feinkontrolle haben, um eine Uhr um ~ 300 ps gegen eine andere zu verzerren. Aber ich habe nicht uns Zyklone, also vielleicht ....


Update:
Genau das, was ich erwartet hatte: Der Pfad beginnt am wrptr_g ... Ich nehme an, das ist der Schreibzeiger, der wahrscheinlich mit dem Lesezeiger verglichen wird, der die fifo_full/empty-Flags macht, die den Mux steuern.

Der beste Weg, um das Timing-Problem zu beseitigen, besteht darin, eine registrierte Version der Voll/Leer-Flags zu erstellen. Das kann bedeuten, dass Sie einen Teil der restlichen Schaltung neu entwerfen müssen.

Wenn der FIFO synchron ist, gibt es einen Trick, um synchrone Voll/Leer-Flags zu erzeugen. Sie prüfen, ob der Pegel EINS ist, und bei einem Lese-, aber nicht Schreibvorgang setzen Sie synchron das 'leer'-Flag. Siehe hier für einen kostenlosen Beispielcode von FIFOs, die diese Funktion haben. Leider funktioniert das nicht mit asynchronen FIFOs.

Ich habe mir das RTL-Schema nach der Anpassung angesehen und anscheinend sind die LUTs groß genug, um dies als einzelne Logikblockoperation zu implementieren, aber anscheinend hätte ich die Warnungen genauer lesen sollen. Die Pfade mit den höchsten Fehlern beginnen bei einem internen FIFO-Register (FIFO_289:FIFO_inst_289|dcfifo:dcfifo_component|dcfifo_6up1:auto_generated|wrptr_g[0]) und werden an das Array fifo_wdata_289 weitergegeben. Ich weiß nicht wirklich, warum dies kein falscher Pfad ist, da das Quellsignal in einen registrierten RAM-Block eingespeist wird. Vielleicht ist es sicher zu ignorieren (hoffentlich).
Ich bin mir auch nicht sicher, ob einer der genannten Pfade nicht fehlschlägt. Wenn sie fehlschlagen, schlagen sie nicht so stark fehl wie die Pfade, die ich angezeigt bekomme (TimeQuest hat ein Anzeige-/Analyselimit): D Vielleicht ist es auch relevant zu beachten, dass der RAM ein M10K-Block ist
Vielen Dank für Ihre Aktualisierung. Ich habe den Speicherzellentyp von M10K auf MLAB geändert und die Taktrate auf 288 MHz gesenkt, da die Speicherzellen offenbar nicht mehr vertragen. Leider sind die Probleme nicht verschwunden, der Skew hat sich nur in der Amplitude verringert, da die Taktrate verringert wurde. Ich verwende asynchrone FIFOs, weil ich CDC machen muss und aus diesem Grund verwende ich 3 Synchronisationsstufen, was bedeutet, dass die Voll/Leer-Signale innerhalb des FIFO registriert werden.

Wenn beide FIFOs mit der gleichen Taktphase versorgt werden, dann werden die Setup- und Haltezeiten für den zweiten FIFO verletzt, da er zu früh ankommt. Ihr Programm deutet an, dass Sie etwas verlangsamen müssen, nämlich Ihre Uhr.

Sie können einen Inverter hinzufügen, um den zweiten FIFO auf der fallenden Flanke zu verriegeln, lange nachdem sich die Daten stabilisiert haben. Eine bessere Option, wenn Ihre Software dies tun kann, besteht darin, ein Wackeln in die Taktleitung zu legen, bevor sie den zweiten FIFO erreicht. Software wie Spectctra kann die Berechnungen dafür übernehmen.

In Ermangelung von etwas Besserem erzeugt ein Widerstand mit niedrigem Wert in Reihe mit dem Takt zum zweiten FIFO eine natürliche Verzögerung. Finden Sie die Kapazität des Taktstifts heraus und berechnen Sie, was für eine Verzögerung von einigen nS benötigt wird. Ich würde höchstens 100 Ohm denken, aber mehr als 10 Ohm.

Danke für diesen Vorschlag, aber ich würde keinen Widerstand verwenden, selbst wenn es sich um eine analoge Schaltung handelt, da dies zu Rauschen führt und ich nicht einmal an die EMV denken möchte, wenn Sie einen 360-MHz-Takt auf ein FPGA legen Pin und verwenden Sie einen Widerstand, um das Signal zurückzukoppeln. Die FIFOs werden auch an der invertierten Flanke zwischengespeichert, während die Daten an der anderen Flanke geändert werden, daher hatte ich gehofft, dass die Daten während der Zwischenspeicherzeit der FIFOs stabil sein würden