Forum: FPGA, VHDL & Co. CDC notwendig bei halb-statischen Signalen?


von dono (Gast)


Lesenswert?

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?

von Erik (Gast)


Lesenswert?

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"?

von dono (Gast)


Lesenswert?

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.

von Vancouver (Gast)


Lesenswert?

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.

von Markus F. (mfro)


Lesenswert?

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.

: Bearbeitet durch User
von Christophz (Gast)


Lesenswert?

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)

von dono (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.