Guten Morgen! Ich arbeite zurzeit an einem Dual-Clock-DMA, welcher zwischen zwei Clock-Domains Daten hin- und herschieben kann (jeweils ein Avalon-Master pro Clock-Domain). Die Daten werden mit Hilfe einer Dual-Clock-FIFO zwischen beiden Domains übertragen, sodass der Signalpfad zwischen beiden Avalon-Master-Modulen timing-technisch wohldefiniert ist. Nun habe ich ein Control-Slave-Modul, welches in einer der beiden Clock-Domains arbeitet und per Register-Map den DMA konfiguriert und startet. Folgendes Design habe ich mir hierfür erarbeitet: * Beide Avalon-Master setzen ein Idle-Signal auf High, wenn sie bereit für die nächste Operation sind. Wird in dieser Zeit ein Start-Signal auf High gezogen (für einen Takt), startet der Avalon-Master mit der Datenübertragung. Einige Kontrollsignale wie Start-Adresse und Byte-Count, die wie das Start-Signal vom Control-Modul kommen, werden erst dann als Valid anerkannt, wenn der Handshake erfolgt ist. Ab dann darf das Control-Modul die Kontrollsignale (Start-Adresse etc.) nicht ändern, bis das Modul wieder in den Idle wechselt. * Innerhalb einer Clock-Domain werden die Signale ohne CDC übernommen. Zwischen zwei Clock-Domains werden zurzeit 2-stufige CDCs verwendet. Hiermit bläst sich das Modul jedoch drastisch auf, da jedes Signal mehrere Register benötigt. Nun zu meiner Frage: Dadurch, dass erst die Kontrollsignale gesetzt werden, und mindestens ein Takt später das Start-Signal gesetzt wird, kann ich davon ausgehen, dass in der zweiten Clock-Domain die Signale stabil genug sind, um ohne CDC auszukommen. Nur das Start- und Idle-Signal muss speziell behandelt werden, bspw. mit CDC beim Start-Signal. Wie kann ich per Constraints definieren, dass Quartus dies erlaubt?
dono schrieb: > Dadurch, dass erst die Kontrollsignale gesetzt > werden, und mindestens ein Takt später das Start-Signal gesetzt wird, > kann ich davon ausgehen, dass in der zweiten Clock-Domain die Signale > stabil genug sind, um ohne CDC auszukommen. Nicht zwingend. Das kommt auf das Verhältnis der beiden Takte zueinander und den Routing Delays an. Dafür gibt es maxdelay. Für sowas verwendet man auch eigentlich vector synchronizer. https://www.edn.com/Pdf/ViewPdf?contentItemId=4435339 Figure 11. dono schrieb: > Wie kann ich per Constraints definieren, dass Quartus > dies erlaubt? Inwiefern "erlaubt"?
Erik schrieb: > Dafür gibt es maxdelay. > > Für sowas verwendet man auch eigentlich vector synchronizer. > https://www.edn.com/Pdf/ViewPdf?contentItemId=4435339 > Figure 11. Nehmen wir an, ich habe folgende Signale:
1 | * data_clk1, data_clk2 |
2 | * req_clk1, req0_clk2, req1_clk2 |
3 | * ack_clk2, ack0_clk1, ack1_clk1 |
req und ack werden jeweils mit zwei Registern synchronisiert, und mindestens N Takte angelegt, wobei N abhängig ist vom Verhältnis der Taktfrequenzen. Zwischen data_clk1 und data_clk2 wird maxdelay verwendet. Wie muss dann die Constraint aussehen?
1 | set_max_delay -from [get_registers data_clk1] -to [get_registers data_clk2] ...? |
> dono schrieb: >> Wie kann ich per Constraints definieren, dass Quartus >> dies erlaubt? > > Inwiefern "erlaubt"? Damit die Timing Analysis nicht meckert, und Quartus die Signale nicht versucht, unnötig zu optimieren.
Ich kenne Quartus nicht, aber in Vivado gibt es ein "Timing Ignore" Constraint (TIG), mit dem man einzelne Pfade von der Timinganalyse ausnehmen kann. Gibts bei Quartus sicher auch. Wahrscheinlich hast du schon selbst dran gedacht, aber zur Vorsicht: Das was du vorhast, funktioniert nur dann, wenn du die Signale in der Zieldomain tatsächlich nur dann einsamplest wenn sie stabil sind. Es nutzt dir nichts, wenn du sie in jedem Takt einsamplest und nur gelegentlich auswertest. Dann kann das Eingangsregister schon längst metastabil sein. Du brauchst also in den Eingangsregistern ein clock enable oder einen Multiplexer, das/der von irgendwo gesteuert wird. Ein wenig Overhead bekommst du also auf jeden Fall.
set_max_delay ist dafür bei Quartus m.E. nicht, bzw. nur bedingt geeignet. set_max_delay berücksichtigt den clock skew, was bei CDC zu eher unbefriedigenden (um nicht zu sagen: falschen) Ergebnissen führt. Angeblich gibt/gabs mal ein set_data_delay (das praktisch dem Xilinx set_max_delay -datapath only, das den clock skew ignoriert) entsprach. Ich habe allerdings noch keine TimeQuest-Version gefunden, die das unterstützen würde. Ich würde den speziellen Datenpfad einfach timing-technisch (set_false_path) auftrennen. Da kommt erfahrungsgemäß am wenigsten Blödsinn raus.
dono schrieb: > * Innerhalb einer Clock-Domain werden die Signale ohne CDC übernommen. > Zwischen zwei Clock-Domains werden zurzeit 2-stufige CDCs verwendet. > Hiermit bläst sich das Modul jedoch drastisch auf, da jedes Signal > mehrere Register benötigt. Wird ein CDC auch für parallele Daten wie Start-Adresse etc. genutzt? Wenn ja, dringend anders designen und wie schon geschrieben: Vancouver schrieb: > Wahrscheinlich hast du schon selbst dran gedacht, aber zur Vorsicht: Das > was du vorhast, funktioniert nur dann, wenn du die Signale in der > Zieldomain tatsächlich nur dann einsamplest wenn sie stabil sind. Z. B. begründet im Paper "14-ways-to-fool-your-synchroniser" Abschnitt 3.12 (Jaja, ich weiss, ich hab dieses Paper schon an anderer Stelle erwähnt, aber ich finds halt kurz und gut geschrieben)
Vancouver schrieb: > Wahrscheinlich hast du schon selbst dran gedacht, aber zur Vorsicht: Das > was du vorhast, funktioniert nur dann, wenn du die Signale in der > Zieldomain tatsächlich nur dann einsamplest wenn sie stabil sind. Es > nutzt dir nichts, wenn du sie in jedem Takt einsamplest und nur > gelegentlich auswertest. Dann kann das Eingangsregister schon längst > metastabil sein. > Du brauchst also in den Eingangsregistern ein clock enable oder einen > Multiplexer, das/der von irgendwo gesteuert wird. Ein wenig Overhead > bekommst du also auf jeden Fall. Genau so mache ich es. Ich warte auf das "req"-Signal und übernehme erst dann die Signale in die Register. Markus F. schrieb: > Ich würde den speziellen Datenpfad einfach timing-technisch > (set_false_path) auftrennen. Da kommt erfahrungsgemäß am wenigsten > Blödsinn raus. So werde ich es wohl machen. Das "req"-Signal kommt einige Takte nach den Kontrolldaten an, sodass ich mit einem set_false_path wohl auf der sicheren Seite bin. Irgendwo muss man ja auch realistisch einsehen, dass es nicht nicht klappen sollte. Christophz schrieb: > Wird ein CDC auch für parallele Daten wie Start-Adresse etc. genutzt? Im neuen Design nicht mehr. Dort wird nur ein CDC für das "req"-Signal verwendet, die parallelen Daten werden als false_path konfiguriert. Christophz schrieb: > Z. B. begründet im Paper "14-ways-to-fool-your-synchroniser" Abschnitt > 3.12 (Jaja, ich weiss, ich hab dieses Paper schon an anderer Stelle > erwähnt, aber ich finds halt kurz und gut geschrieben) Tolles Paper! Hatte eine Diskussion mit einem Kollegen, kann mit ihm das gleich mal durchspielen. Fazit: Ich teste das Design nächste Woche auf der Hardware aus, sobald ich alle Signale in der .sdc richtig konfiguriert habe. Vielen Dank.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.