//Show errorcounter or data output depending on define
117
`ifdef LEDS_SHOW_DATA
118
assign aLedO = aoutputData[5:0];
119
120
`else
121
assign aLedO = aerrorCounter;
122
123
`endif
124
125
endmodule
Das Modul wird mit zwei Clocks instanziiert (bei mir ist ClkFastI 25Mhz
und ClkSlowI keinen MHz langsamer) und soll mit dem langsamen Takt immer
ein paar Bit (ainputData) kippen lassen. Diese Bits sollen aus der
langsamen clockdomain in die schnelle überführt werden. Das mache ich
mit der Zeile
aoutputDataReg <= ainputData;
absichtlich falsch, das CDC wird hier nicht beachtet. Direkt darunter
erkennt aoutputDataTrigger als Flankenmerker Änderungen der Daten in der
Zieldomain und prüft, ob die richtig angekommen sind. Wenn nicht, wird
ein Fehlerzähler hochgezählt. Entweder dieser Zähler oder die untersten
6 Datenbits werden als LEDs ausgegeben (je nachdem ob LEDS_SHOW_DATA
definiert ist)
Ersetze ich
aoutputDataReg <= ainputData;
durch
aoutputDataReg <= ainputData + 1'b1;
und bringe so beim Daten Übertragen zwischen den Domains absichtlich
einen Fehler rein, rennt der Zähler hoch. Sonst aber wird kein Fehler
angezeigt. In der Simulation passt das Design soweit, nur dass ich
CDC-Fehler dort nicht simulieren kann. Wo seht ihr den Fehler in dem
Modul, der dafür verantwortlich ist, dass kein CDC-Fehler passiert?
Joschua C. schrieb:> Das Modul wird mit zwei Clocks instanziiert (bei mir ist ClkFastI 25Mhz> und ClkSlowI keinen MHz langsamer)
d.h. beide Clocks sind gleich schnell und ohne ein .sdc-File, das
genaueres dazu erzählt, erst mal synchron?
Welche Art Fehler würdest Du dann erwarten?
Oh sorry, der langsamere Clock ist 24,666 MHz groß, also die Clocks sind
schon unterschiedlich, aber nur um einen kleinen Unterschied.
Meine Erwartung wäre, dass die Situation vorkommt, dass eine ClkFastI
Flanke direkt nach einer ClkSlowI Flanke kommt, sodass die FFs von
aoutputDataReg in Metastabiität kommen, weil aoutputDataReg am Takt
ClkFastI hängt, aber Daten aus der Clockdomain ClkSlowI liest. Ich
erwarte dann, dass einige der Bits, die aoutputDataReg aus ainputData
erhält, nicht stimmen. Und genau das wird mit
if((aoutputDataTrigger != aoutputDataReg) && (ainputData !=
aoutputDataReg))
abgeprüft. Der Fehlerzähler zählt um eins hoch, wenn aputputDataReg sich
geändert hat und wenn diese neuen Daten nicht mit der Quelle ainputData
übereinstimmen. Doch genau diese rechte Bedingung (ainputData !=
aoutputDataReg) wird niemals wahr.
Mein TimeQuest eskaliert brutal und meckert, dass die Setup-Zeit auf dem
Datenpfad
aoutputDataReg <= ainputData;
nicht eingehalten werden kann. Und genau das sollte doch eigentlich
dafür Sorgen, dass die Bedinung (ainputData != aoutputDataReg) mal wahr
wird, weil bei der Zuweisung aoutputDataReg <= ainputData; das CDC
Problem auftritt.
Joschua C. schrieb:> Und genau das wird mit>> if((aoutputDataTrigger != aoutputDataReg) && (ainputData !=> aoutputDataReg))>> abgeprüft.
Mag sein, dass ich falsch liege (meine Verilog-Kenntnisse sind
ausserordentlich rudimentär) aber wenn ich
1
b<=a;//kannschiefgehen
2
c<=b;//gehtnichtschief(gleicheclockdomain)
schreibe, muss meinem bescheidenen Verständnis nach
1
if(c!=b)
immer false sein. Egal, ob blocking oder non-blocking assignment. Mag
sein, dass der Wert nicht der ist, den Du gerne sehen würdest, aber
identisch sollten die Werte schon sein. Wenn dein Zähler hochzählen
soll, würde ich eher mehrfach aus der (falschen) clock domain lesen und
die Werte vergleichen:
Möglicherweise hat der Synthesizer dein 64 bit breites Register auf ein
einzelnes reduziert. Du verändest diese ja immer auf die identische Art.
Wenn das passiert ist, bekommst du nur noch Fehler bei Metastabilität,
und das tritt bei 24 MHz sehr selten auf.
Mach ein 64 bit breites Schieberegister, und füttere es mit einem LFSR.
Zuerstmal danke für die Antworten und entschuldigt, dass ich so selten
hier reinschaue. Bin gerade hart beschäftigt mit Regelungstechnik II :D
Markus F. schrieb:> immer false sein. Egal, ob blocking oder non-blocking assignment. Mag> sein, dass der Wert nicht der ist, den Du gerne sehen würdest, aber> identisch sollten die Werte schon sein. Wenn dein Zähler hochzählen> soll, würde ich eher mehrfach aus der (falschen) clock domain lesen und> die Werte vergleichen:> b <= a;> c <= a;> if (c != b)
Die Bedingung c != b wird wahr, b != a ist das Problem. Hab beide
einzeln im FPGA getestet und den Zähler beobachtet. Deinen Vorschlag
werde ich aber trotzdem mal ausprobieren. Der Ablauf soll sein:
posedge ClkSlowI: ainputData ändert sich
posedge ClkFastI: aoutputDataReg <= ainputData macht den CDC Fehler,
aoutputDataTrigger <= aoutputDataReg ändert keine Daten, weil
aoutputDataReg noch den gleichen Wert wie am Anfang hat
posedge CLKFastI: aoutputDataTrigger != aoutputDataReg wird jetzt wahr,
weil jetzt der aktuelle, neue Wert von aoutputDataReg gelesen wurde.
Dieser Wert wird gleichzeitig mit aoutputDataTrigger <= aoutputDataReg
in die Flankenerkennung eingelesen, damit die Bedingung im nächsten Takt
nicht mehr wahr wird.
Im Simulator läuft das auch.
Lattice User schrieb:> Möglicherweise hat der Synthesizer dein 64 bit breites Register auf ein> einzelnes reduziert. Du verändest diese ja immer auf die identische Art.>> Wenn das passiert ist, bekommst du nur noch Fehler bei Metastabilität,> und das tritt bei 24 MHz sehr selten auf.>> Mach ein 64 bit breites Schieberegister, und füttere es mit einem LFSR.
Auch ein guter Hinweis. Einerseits sieht die .sdc Datei so aus, als
hättest du Recht, andererseits wird der Chip aber randvoll, wenn ich die
Bitbreite vergrößere.
Also werde ich mal den LFSR mit reinnehmen und zwei Mal die CDC
Verletzung kopieren. Und dann drehe ich die PLL nochmal an die Grenze
auf (TimeQuest sagt ja wo die Grenzen liegen) und lasse den zweiten
always-Block mal auf fallende und steigende Flanke hören. Das sollte die
Wahrscheinlichkeit von CDC Fehlern noch weiter steigern. Aber erst
Regelungstechnik...
Viele Grüße
Joschua
Lattice User schrieb:> Möglicherweise hat der Synthesizer dein 64 bit breites Register auf ein> einzelnes reduziert. Du verändest diese ja immer auf die identische Art.>> Wenn das passiert ist, bekommst du nur noch Fehler bei Metastabilität,> und das tritt bei 24 MHz sehr selten auf.>> Mach ein 64 bit breites Schieberegister, und füttere es mit einem LFSR.
Genau das war das Problem. Mit LFSR wird nichts mehr wegoptimiert. Jetzt
läufts wie erwartet. Ca. jede 10. Operation bei 64 Bit und einem PLL
Verhältnis von 199/200 schlägt fehl. TimeQuest moniert jedes Bit von den
64. Vielen Dank!