Ich habe eine Bussynchronisationsschaltung zum Weiterleiten eines breiten Registers über Taktdomänen.
Ich werde eine vereinfachte Beschreibung bereitstellen, wobei die asynchrone Rücksetzlogik weggelassen wird.
Die Daten werden auf einer Uhr generiert. Updates sind viele (mindestens ein Dutzend) Taktflanken voneinander entfernt:
PROCESS (src_clk)
BEGIN
IF RISING_EDGE(clock) THEN
IF computation_done THEN
data <= computation;
ready_spin <= NOT ready_spin;
END IF;
END IF;
END PROCESS;
Das Steuersignal für frische Daten, das NRZI-codiert ist (ein gültiges Wort auf dem Bus entspricht also einem Übergang auf dem Steuersignal). Das Steuersignal durchläuft eine DFF-Kette, die als Synchronisierer fungiert.
PROCESS (dest_clk)
BEGIN
IF RISING_EDGE(dest_clk) THEN
ready_spin_q3 <= ready_spin_q2;
ready_spin_q2 <= ready_spin_q1;
ready_spin_q1 <= ready_spin;
END IF;
END PROCESS;
Die Synchronisationsschaltung führt eine kurze Verzögerung ein, die dem Datenbus genügend Zeit zur Stabilisierung bietet. Der Datenbus wird direkt ohne Metastabilitätsrisiko abgetastet:
PROCESS (dest_clk)
BEGIN
IF RISING_EDGE(dest_clk) THEN
IF ready_spin_q3 /= ready_spin_q2 THEN
rx_data <= data;
END IF;
END IF;
END PROCESS;
Dies kompiliert und funktioniert gut, wenn es zu einem Cyclone II-FPGA synthetisiert wird. TimeQuest meldet jedoch Verstöße gegen die Setup- und Haltezeit, da der Synchronizer nicht erkannt wird. Schlimmer noch, sagt das Quartus-Handbuch
Konzentrieren Sie sich darauf, die Pfade zu verbessern, die den schlechtesten Durchhang aufweisen. Der Monteur arbeitet am härtesten auf Wegen mit dem schlechtesten Durchhang. Wenn Sie diese Pfade korrigieren, kann der Monteur möglicherweise die anderen fehlerhaften Timing-Pfade im Entwurf verbessern.
Daher möchte ich meinem Projekt die richtigen zeitlichen Einschränkungen hinzufügen, damit Quartus seine Fitter-Bemühungen für andere Bereiche des Designs ausgibt.
Ich bin mir ziemlich sicher, dass dies set_multicycle_path
der richtige SDC-Befehl (Synopsis Design Constraint) ist, da die Datenleitungen mehrere Zyklen der Zieluhr haben, um sich zu stabilisieren, aber ich kann keine vollständigen Beispiele finden, die diesen Befehl verwenden, um die Logik der Taktdomänenkreuzung zu beschreiben .
Ich würde mich sehr über eine Anleitung zum Schreiben von SDC-Zeiteinschränkungen für Synchronisierer freuen. Wenn Sie ein Problem mit diesem Ansatz sehen, lassen Sie es mich bitte auch wissen.
Uhrendetail:
Externer Taktgenerator: Zwei Kanäle, refclk = 20 MHz, refclk2 = refclk / 2 (10 MHz und verwandte).
Altera PLL: src_clk = refclk * 9/5 = 36 MHz
Altera PLL: dest_clk = refclk2 * 10 = 100 MHz
Ich habe auch Daten in die andere Richtung, mit 100 MHz src_clk und 36 MHz dest_clk.
TL; DR: Was sind die korrekten SDC-Zeiteinschränkungen für den obigen Code?