Abend.
Gegeben zwei clockdomains.
Einer läuft mit 27MHZ und liefert Pixeldaten eines Bildes.
Zweiter läuft mit 166MHZ und schreibt die Daten in SDRAM.
Jetzt habe fogendes Problem.
Jedes mal, wenn auf Domain1 eine gültige Datei vorliegt, wird diese
Datei in den SDRAM geschrieben (Domain2).
Wenn ich die SDRAM Adresse im Domain1 steuere, habe ich kein Problem
damit. (Siehe Bild1)
Will ich aber die ganze Steuerung im Domain2 realisieren, sieht das
Bild stark verzerrt und instabil aus(Bild. 2).
Ich verstehe nicht ganz, warum das passiert, denn im Simulator sehen
die beide Fälle gut aus.
Danke im voraus für die Hilfe;)
Anbei mein Code für den Ok-Fall:
Ohne jetzt sicher sagen zu können, dass genau darin der Fehler liegt,
aber vielleicht erklärt es das prinzipielle Problem, welches bei solchen
Domainünbergängen passiert.
z.B. wird das Signal ENABLE in der Domain 1 erzeugt. Also synchron zu
TD_CLK27
Mit diesem ENABLE-Signal steuerst du irgendwas in Domain 2
Im Gut-Fall übernimmst du nur Daten von einem Register in ein anderes.
Im Schlecht-Fall steuerst du mit dem ENABLE-Signal einen Zähler. Gibst
das hochzählen also frei.
Problem 1:
Ist sichergestellt, dass das ENABLE-Signal immer nur genau für einen
Takt der Domain2 aktiv ist? Wenn ja, ist gut, aber wenn nein.. dann kann
sein, dein Zähler zählt auch mehrfach hintereinander, oder?
Problem 2:
Wenn die Phasenlage zwischen Domain 1 und 2 nicht starr ist, hat die
Synthese ein Problem.
Es kann nicht ausgeschlossen werden, dass es zu Setup-Zeit verletzungen
am Zielregister kommt. Das heißt, dass das ENABLE sich zu einem so
blöden Zeitpunkt ändert, an dem die Register-Eingänge der Ziel-Domain
stabil sein müssen, um Metastabilitäten zu verhindern.
Steuerst du mit dem ENABLE nur EIN einzelnes Register, kann das Problem
noch gering sein. Wenn das Register kurz metastabil wird, fällt es bis
zum nächsten Takt entweder in den alten Zustand zurück oder übernimmt
doch den neuen.
Aber wenn du einen Zähler hast, und ein paar Register "sehen" beim Takt
das ENABLE und ein paar Register nicht, dann gerät der Zähler außer Rand
und Band..
Das ist ein generelles Problem. Wo jetzt genau in deinem Code die
Ursache liegt, kann ich nicht sagen, aber die o.g. Stelle mit dem ENABLE
ist auf jeden Fall eine, die Probleme machen kann.
Aber ich vermute, dass sich da noch mehr so Stellen finden lassen, wenn
man genau hinschaut.
Böser Kommunist schrieb:> Das 2. Problem ist wirklich echtes ein Problem. Ich habe verstanden was> du meinst, aber wie kann ich sowas vermeiden?
Das kann man z.B. dadurch vermeiden, dass ein Steuersignal aus der einen
Domain immer nur auf EIN Steuersignal in der anderen Domain wirkt. Oder
zumindest nur auf Register wirkt, die nicht unbedingt konsistent
zueinander sein müssen.
Also z.B.:
Du steuerst mit dem ENABLE-Signal nicht direkt alle Zählerregister an,
sondern nur EIN Register in der Zieldomain. Du synchronisierst quasi
erst das Steuersignal in die Zieldomain ein und das einsynchronisierte
Signal verwendest du dann, um deinen Zähler zu steuern.
So kannst du sicherstellen, dass alle Register des Zählers immer das
identische Steuersignal sehen.
Domain 1: Domain 2:
ENABLE ------------> en_sync(0) ---> en_sync(1)--------> counter(0...n)
ggf kannst du dann auch bei der Einsynchronisierung gleich die Flanke
des Steuersignals erkennen und dann nur für EINEN Takt der Domain 2
einen enable-Impuls erzeugen. Dann kannst du dir das mit dem ACK sparen.
also so, wenn sichergestellt ist, dass die Metastabilität der Register
deutlich kürzer als ein Takt der Zeildomain ist:
Domain 1: Domain 2:
ENABLE ------------> en_sync(0) ---> en_sync(1)
en_sync = "10" --------> counter(0...n)
oder so, wenn Zweifel bestehen, ob die Metastabilität bis zur nächsten
Flanke nicht abgeklungen ist:
Domain 1: Domain 2:
ENABLE ------------> en_sync(0) ---> en_sync(1) ---> en_sync(2)
en_sync(1,2) = "10" -------->
counter(0...n)
Schlumpf du bist der Hammer. Danke!
omain 1: Domain 2:
ENABLE ------------> en_sync(0) ---> en_sync(1)--------> counter(0...n)
hat geholfen!=)
Wieder was neues gelernt;)