Verwenden beider Taktflanken in einem FPGA-Design

Nachdem ich hier einige Ratschläge von einigen guten Leuten bekommen hatte, gelang es mir, mein erstes (sehr bescheidenes) FPGA-Design zusammenzustellen. Es besteht im Grunde nur aus ein paar Registern und Zählern und läuft nur mit ein paar MHz, aber ich konnte es ohne Warnungen synthetisieren und implementieren, und die realen Signale, die herauskommen, scheinen das zu tun, was die Simulation von mir erwartet hat. Auf dem Weg habe ich einiges gelernt.

Jetzt möchte ich lernen, wie man Timing-Einschränkungen festlegt und Timing-Analysen durchführt. Ich lese also das Xilinx-Dokument UG612 durch und sehe oben auf Seite 205:

"Benutze nur eine Kante der Uhr"

Hmm. Anscheinend habe ich das Gesetz gebrochen. Ein Teil meines Designs ist ein paralleles Ladeschieberegister - ich habe die Negede des letzten Taktzyklus verwendet, um es zu laden (von einem Zähler, der auf der vorherigen Position getaktet wurde). Eine schnelle Skizze:

Takten und Laden

Natürlich verwende ich hier nicht direkt den Negedge, aber das Lastsignal wird daraus abgeleitet. Ich fand das gut - aber Xilinx sagt mir - tu das nicht.

Liege ich falsch? Wenn ja warum? Was soll ich stattdessen tun?

Der Fehler, den Xilinx Ihnen gibt, handelt von einer Gated Clock?
Nein, mein Design kompiliert völlig sauber - keine Warnungen oder Fehler. Ich beziehe mich auf Hinweise im verlinkten Dokument (Seitenzahl im Text oben).
Sie können sie mischen, aber aus Timing-Perspektive bedeutet dies, dass die Setup/Hold-Pfade halb so lang werden und das Timing schwieriger einzuhalten ist. Wovon wird SRCLK abgeleitet?
SRCLK ist ein 2-MHz-Takt, der Haupttakt meines Designs. (Auf dem Entwicklungsboard befindet sich ein 100-MHz-Quarzoszillator, ich habe einen Synchronzähler verwendet, um die 2 MHz zu erhalten.) Ich denke, bei diesen Frequenzen ist es unwahrscheinlich, dass es ein Problem gibt, aber ich würde gerne wissen, was "Best Practice" ist und warum .
Der Ausgang Ihres Zählers ist kein 2-MHz- Takt . Es ist ein Rechtecksignal mit 2 MHz, aber kein (echtes) Taktsignal . Im Allgemeinen unterstützen die meisten FPGAs keine langsamen Takte unter 10 MHz. Sie sollten Ihre Schaltung mit 100 MHz betreiben und ein Taktfreigabesignal mit einer Frequenz von 2 MHz erzeugen.
BiPhase-Clocks sind nützlich, um die Latenz um 50 % zu reduzieren, aber wenn die Anforderungen an die Setup/Hold-Zeit erfüllt sind, kann die asynchrone Eingangsfrequenz mit derselben Flanke verdoppelt werden
FPGAs unterstützen keine DDR-Techniken (die an beiden Taktflanken arbeiten) für interne Flip-Flops. Dies wird nur für Input/Output Blocks (IOBs) unterstützt. Wenn Sie einen Systemtakt von 100 MHz haben, verwenden Sie die Aktivierungstechnik wie oben beschrieben. Dadurch können Sie anstelle einer verschobenen Version (25. Ordnung) bis zu 50 verschobene Versionen Ihres 2-MHz-Signals verwenden.
Ich danke Ihnen allen für Ihre Kommentare und Ratschläge. Paebbels - Ich takte eigentlich kein Gerät an beiden Rändern - aber ich verwende auf einigen Geräten eine Negedge-Uhr. Haben Sie eine Verbindung zur CE-Technik? Und wenn Sie sagen "die meisten FPGAs unterstützen keine langsamen Takte unter 10 MHz" - was bedeutet das wirklich? Was sind die (möglichen) Folgen? und wann genau wird aus einer rechteckwelle eine "richtige uhr"?
@Paebbels "Die meisten FPGAs unterstützen keine langsamen Takte unter 10 MHz" Ich verstehe, dass die PLL möglicherweise keine langsamen Takte erzeugen kann, aber was würde das FPGA daran hindern, mit dieser langsamen Geschwindigkeit fortzufahren, wenn die Uhr extern erzeugt wird (oder sogar intern verwendet wird eine Frequenzteilerlogik)? Haben Sie Referenzen für diese Einschränkung?
Echte Uhren werden nicht mit Benutzerlogik-Ressourcen geroutet, sondern mit (Uhr-) dedizierten Routen - so genannten Uhrennetzwerken. Daher müssen Sie den generierten Takt in einen BUFG, BUFH, BUFR, ... einspeisen. Sie können einen solchen kombinatorischen Takt nicht für einen beliebigen Clock Modifying Block (CMB) als Eingang verwenden. Als nächstes müssen Sie neue Einschränkungen im System spezifizieren, um der statischen Timing-Analyse mitzuteilen, dass dieses Signal eine Frequenz, einen Arbeitszyklus und möglicherweise eine Phasenbeziehung hat. Normalerweise werden solche Beschränkungen automatisch abgeleitet.
Ich habe noch nie einen Studenten oder Ingenieur gesehen, der all dies getan hat, wenn er die schmutzige Art der Erstellung abgeleiteter Uhren verwendet. Ok, nächstes Problem, die Benutzerlogik (Zähler), die zur Generierung der Uhr verwendet wird, führt einen hohen Jitter in das Signal ein. Daher muss man wiederum Zeitbeschränkungen spezifizieren, aber der maximale Jitter in FPGAs für diese Technik ist unbekannt. Es ist auch sehr temperatur- und spannungsabhängig (Arbeitslast). Ingenieure, die diese schmutzige Methode für langsame Designs verwenden, verwenden dieselbe Technik für höhere Frequenzen oder in Multi-Gigabit-Transceiver-Designs. Es gibt also eine sehr einfache Gestaltungsregel – tun Sie es nicht!
Dies ist auch in den HDL-Designrichtlinien der Hersteller zu finden...
Ich denke, dass ISE sich bewusst ist, dass dies Taktsignale sind: "1 Clock Inputs: i_clk_100MHz 4 Leaf Clock Nets: clk_div/o_clk_BUFG i_clk_100MHz_BUFGP " - danke für Ihre Kommentare. Wie gesagt - ich lerne.
Ich habe also herausgefunden, dass ich mit dem Taktassistenten in ISE einen 4-MHz-Takt aus den 100 MHz generieren kann, was in Ordnung ist, indem ich die internen Taktressourcen verwende. (Der niedrigste Wert, der von 100 MHz eingeht, liegt knapp über 3 MHz - wenn mein externer Takt 20 MHz wäre, könnte ich natürlich leicht 2 MHz intern erzeugen.) Das ist natürlich besser als das, was ich getan habe - eine andere Sache, die ich gelernt habe. Ich habe mir auch das Datenblatt angesehen und sehe überhaupt keine Angabe zur minimalen Taktfrequenz. Viel Fmax, kein Fmin. Wenn jemand eine solche Anforderung in den Xilinx Spartan 6-Daten kennt, würde mich das natürlich interessieren.

Antworten (3)

"Benutze nur eine Kante der Uhr"

Ich weiß nicht, warum sie das sagen würden. Sie können im Design sowohl ansteigende als auch abfallende Taktflanken verwenden, und der Timing-Analysator wird dies berücksichtigen.

Somit gibt Ihnen ein 200-MHz-Takt 5 ns von der steigenden Flanke zur steigenden Flanke, aber nur 2,5 ns von der steigenden Flanke zur fallenden Flanke. Ich habe ein kleines Beispiel mit 16-Bit-Werten gemacht:

always @(posedge clk)
   result1 <= counter + hold;
always @(negedge clk)
   result2 <= counter + hold;

Unten ist ein Screenshot der ISE-Timing-Analyse. Es ist für einen Takt mit 5 ns 50% Arbeitszyklus.

Der Text handelt von einem fehlerhaften Pfad von Bit 3 von counterzu Bit 15 von result2. Wie Sie sehen können, verwendet es die steigende Flanke als Quelle und die fallende Flanke als Ziel.

Geben Sie hier die Bildbeschreibung ein

Ich denke, sie sagen es, um weitere SR-Tickets zu verhindern ... und weil KISS sowieso besser ist. Aber, ja, es ist völlig gültig, verschiedene Kanten zu verwenden, und ihre Timing-Tools können damit umgehen
Danke schön. In der Tat scheint es möglich zu sein – aber wie Photon weiter unten betont – bedeutet das nicht, dass es so sein sollte.

Die Logikelemente im FPGA sind normalerweise mit einer Haltezeit von null ausgelegt , speziell damit Sie mit nur einer Taktflanke entwerfen können.

In Ihrem Beispiel bedeutet dies, dass sowohl das CTR INC-Signal als auch das SR LOAD-Signal an Flanke 0 als aktiviert angesehen werden und keines an Flanke 15 als aktiviert angesehen wird. Der Wert, der in das Schieberegister geladen wird, ist derjenige, der das ist vor der Flanke 0 im Zähler ist. Die Wirkung des Inkrementierens des Zählers wird nicht im Schieberegister gesehen, bis SR LOAD das nächste Mal geltend gemacht wird.

Wenn Sie das SR-Signal derselben Wellenform wie CTR INC folgen lassen würden, wäre dies immer noch wahr, und das Schaltungsverhalten wäre dasselbe.

Rechts. Das ist sehr hilfreich, denn hier habe ich nicht ganz klar gedacht. Als ich dies tat, machte ich mir Sorgen, dass der SR eine Zählung überspringen würde, wenn ich dasselbe Signal verwenden würde. Dies wird nicht passieren, da die Flip-Flops von FPGA noch nicht in der Lage sind, die Zukunft vorherzusagen. Beruhigend!

Sie liegen nicht falsch, Sie machen Ihr Leben nur schwieriger, als es sein muss ... besonders wenn es um den zeitlichen Abschluss geht (genaue Einschränkungen zu entwickeln ist schwieriger). Sie können dieses Design einfach nur mit steigender Flanke betreiben.

Mir scheint, wenn Sie laden möchten, wenn Zähler = 0 ist, könnten Sie eine kombinatorische Logik haben, die: assign load = (counter==15)(oder ähnlich). Dies verschiebt Ihr Ladesignal um 1/2 Taktzyklus zurück und wird an der steigenden Flanke von edge0 als bestätigt angezeigt. Es gibt jedoch viele Möglichkeiten, dies zu tun (unter Verwendung aller getakteten FFs mit steigender Flanke), und wahrscheinlich wird ein wenig Googeln einen langen Weg zurücklegen.