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:
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?
"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 counter
zu Bit 15 von result2
. Wie Sie sehen können, verwendet es die steigende Flanke als Quelle und die fallende Flanke als Ziel.
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.
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.
SRR
danmcb
Tom Tischler
danmcb
Paebbels
Tony Stewart EE75
Paebbels
danmcb
schwach
Paebbels
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.Paebbels
Paebbels
danmcb
danmcb