Mam obwód synchronizatora magistrali do przekazywania szerokiego rejestru w domenach zegarowych.
Podam uproszczony opis, pomijając logikę asynchronicznego resetowania.
Dane są generowane na jednym zegarze. Aktualizacje mają wiele (przynajmniej kilkanaście) krawędzi zegara:
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;
Sygnał sterujący dla świeżych danych, który jest zakodowany w NRZI (więc prawidłowe słowo na magistrali odpowiada przejściu w sygnale sterującym). Sygnał sterujący przechodzi przez łańcuch DFF działający jak synchronizator.
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;
Obwód synchronizatora wprowadza krótkie opóźnienie, które zapewnia dużo czasu na ustabilizowanie szyny danych; próbka magistrali danych jest pobierana bezpośrednio bez ryzyka metastabilności:
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;
Kompiluje się i działa dobrze, gdy zostanie zsyntetyzowany do FPGA Cyclone II. Jednak TimeQuest zgłasza przypadki naruszenia ustawień i wstrzymania, ponieważ nie rozpoznaje synchronizatora. Gorzej, mówi Quartus manual
Skoncentruj się na ulepszaniu ścieżek, które wykazują najgorszy zastój. Monter pracuje najtrudniej na ścieżkach z najgorszym luzem. Jeśli naprawisz te ścieżki, instalator może poprawić inne niedziałające ścieżki czasowe w projekcie.
Chcę więc dodać odpowiednie ograniczenia czasowe do mojego projektu, aby Quartus poświęcił wysiłek Montera na inne obszary projektu.
Jestem prawie pewien, że set_multicycle_path
jest to właściwe polecenie SDC (Synopsis Design Constraint), ponieważ linie danych będą miały wiele cykli docelowego zegara do ustabilizowania się, ale nie mogę znaleźć żadnych pełnych przykładów, używając tego polecenia do opisania logiki przekraczania domeny zegara .
Byłbym bardzo wdzięczny za wskazówki dotyczące pisania ograniczeń czasowych SDC dla synchronizatorów. Jeśli zauważysz problem z tym podejściem, daj mi również znać.
Szczegóły zegara:
Zewnętrzny generator zegara: dwa kanały, refclk = 20 MHz, refclk2 = refclk / 2 (10 MHz i powiązane).
Altera PLL: src_clk = refclk * 9/5 = 36 MHz
Altera PLL: dest_clk = refclk2 * 10 = 100 MHz
Mam również dane idące w innym kierunku, z 100 MHz src_clk i 36 MHz dest_clk.
TL; DR: Jakie są prawidłowe ograniczenia czasowe SDC dla powyższego kodu?