vincolo di temporizzazione per i circuiti del sincronizzatore del bus


10

Ho un circuito di sincronizzazione bus per il passaggio di un ampio registro tra domini di clock.

Fornirò una descrizione semplificata, omettendo la logica di ripristino asincrona.

I dati vengono generati su un orologio. Gli aggiornamenti sono diversi (almeno una dozzina) di bordi dell'orologio a parte:

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;

Il segnale di controllo per nuovi dati, che è codificato NRZI (quindi una parola valida sul bus corrisponde a una transizione sul segnale di controllo). Il segnale di controllo passa attraverso una catena DFF che funge da sincronizzatore.

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;

Il circuito di sincronizzazione introduce un breve ritardo, che fornisce molto tempo per stabilizzare il bus dati; il bus dati viene campionato direttamente senza rischio di metastabilità:

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;

Questo si compila e funziona bene se sintetizzato in un FPGA Cyclone II. Tuttavia, TimeQuest segnala l'installazione e la conservazione delle violazioni del tempo, poiché non riconosce il sincronizzatore. Peggio ancora, dice il manuale di Quartus

Concentrati sul miglioramento dei percorsi che mostrano il peggior gioco. The Fitter lavora duramente sui percorsi con il peggior gioco. Se si correggono questi percorsi, Fitter potrebbe essere in grado di migliorare gli altri percorsi di temporizzazione non riusciti nella progettazione.

Quindi voglio aggiungere i giusti vincoli di temporizzazione al mio progetto in modo che Quartus spenda i suoi sforzi di Fitter in altre aree del progetto.

Sono abbastanza sicuro che set_multicycle_pathsia il comando SDC (Synopsis Design Constraint) corretto, poiché le linee dati avranno più cicli dell'orologio di destinazione per stabilizzarsi, ma non riesco a trovare alcun esempio completo usando questo comando per descrivere la logica di attraversamento del dominio dell'orologio .

Gradirei davvero alcune indicazioni sulla scrittura dei vincoli di temporizzazione SDC per i sincronizzatori. Se vedi un problema con questo approccio, per favore fammi sapere.


Orologio dettaglio:

Generatore di clock esterno: due canali, refclk = 20 MHz, refclk2 = refclk / 2 (10 MHz e relativi).

Altera PLL: src_clk = refclk * 9/5 = 36 MHz

Altera PLL: dest_clk = refclk2 * 10 = 100 MHz

Ho anche dati che vanno nella direzione opposta, con 100 MHz src_clk e 36 MHz dest_clk.


TL; DR: quali sono i vincoli di temporizzazione SDC corretti per il codice sopra?


1
Questo sarebbe meglio sul sito di progettazione FPGA proposto, ma quella proposta non ha ancora raggiunto la beta.
Ben Voigt,

Puoi pubblicare le definizioni di clock per src_clk e dest_clk? Sono in qualche modo correlati (multipli sincroni)? Se sono orologi non correlati, è tipico utilizzare set_false_path in questa situazione.
Andy,

@Andy: ho aggiunto alcuni dettagli. Grazie per l'aiuto.
Ben Voigt,

Risposte:


9

Non ho esperienza con Quartus, quindi trattalo come un consiglio generale.

Quando si lavora su percorsi tra domini di clock, gli strumenti di temporizzazione espandono gli orologi al multiplo meno comune dei loro periodi e selezionano la coppia di bordi più vicina.

Per percorsi da un clock a 36 MHz (27.777 ns) a un clock a 100 MHz (10 ns), se ho eseguito correttamente i miei calcoli rapidi, la coppia più vicina di fronti di salita è 138.888 ns sul clock sorgente e 140 ns sul clock di destinazione. Questo è effettivamente un vincolo a 900 MHz per quei percorsi! A seconda dell'arrotondamento (o per gli orologi senza relazione), potrebbe venire peggio di così.

Esistono almeno tre modi per scrivere i vincoli per questa struttura. Chiamerò gli orologi fast_clke slow_clkcome penso sia più chiaro per l'illustrazione.

Opzione 1: disabilitare il cronometraggio con set_false_path

La soluzione più semplice è utilizzare set_false_pathper disabilitare il cronometraggio tra gli orologi:

set_false_path -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_false_path -from [get_clocks slow_clk] -to [get_clocks fast_clk]

Ciò non è strettamente corretto, poiché esistono requisiti di temporizzazione per il corretto funzionamento del sincronizzatore. Se l'implementazione fisica ritarda troppo i dati relativi al segnale di controllo, il sincronizzatore non funzionerà. Tuttavia, poiché non esiste alcuna logica sul percorso, è improbabile che il vincolo di temporizzazione venga violato. set_false_pathè comunemente usato per questo tipo di struttura, anche negli ASIC, dove lo scambio tra sforzo e rischio per guasti a bassa probabilità è più cauto che per gli FPGA.

Opzione 2: allenta il vincolo con set_multicycle_path

Puoi concedere tempo aggiuntivo per determinati percorsi con set_multicycle_path. È più comune utilizzare percorsi multiciclo con orologi strettamente correlati (ad es. Orologi 1X e 2X interagenti), ma funzionerà qui se lo strumento lo supporta sufficientemente.

set_multicycle_path 2 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -setup
set_multicycle_path 1 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -hold

La relazione limite predefinita per l'installazione è a ciclo singolo, ad es set_multicycle_path 1. Questi comandi consentono un ulteriore ciclo dell'orologio endpoint ( -end) per i percorsi di installazione. La -holdregolazione con un numero uno in meno rispetto al vincolo di impostazione è quasi sempre necessaria quando si impostano percorsi multi-ciclo, per ulteriori informazioni, vedere di seguito.

Per vincolare i percorsi nell'altra direzione in modo simile (allentando il vincolo di un periodo dell'orologio più veloce), passare -enda -start:

set_multicycle_path 2 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -setup
set_multicycle_path 1 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -hold

Opzione 3: specificare il requisito direttamente con set_max_delay

Questo è simile all'effetto di set_multicycle_pathma evita di dover pensare attraverso le relazioni marginali e l'effetto sui vincoli di attesa.

set_max_delay 10 -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_max_delay 10 -from [get_clocks slow_clk] -to [get_clocks fast_clk]

È possibile associarlo a set_min_delayper i controlli di conservazione o lasciare in posizione il controllo di sospensione predefinito. Potresti anche essere in grado di fare set_false_path -holdper disabilitare i controlli di attesa, se lo strumento lo supporta.


Dettagli cruenti della selezione dei bordi per percorsi multi-ciclo

Per comprendere la regolazione della sospensione associata a ciascuna regolazione della configurazione, considerare questo semplice esempio con una relazione 3: 2. Ogni cifra rappresenta un fronte di clock crescente:

1     2     3
4   5   6   7

Il controllo di configurazione predefinito utilizza i bordi 2 e 6. Il controllo di blocco predefinito utilizza i bordi 1 e 4.

L'applicazione di un vincolo multi-ciclo di 2 con -endregola l'impostazione predefinita e i controlli di mantenimento per utilizzare il bordo successivo dopo quello che stavano utilizzando originariamente, il che significa che il controllo di configurazione ora utilizza i bordi 2 e 7 e il controllo di mantenimento utilizza i bordi 1 e 5. Per due orologi alla stessa frequenza, questa regolazione ha senso: ogni lancio di dati corrisponde a un'acquisizione di dati e se il bordo di acquisizione viene spostato di uno, anche il controllo di mantenimento dovrebbe spostarsi di uno. Questo tipo di vincolo potrebbe avere senso per due rami di un singolo orologio se uno dei rami ha un grande ritardo. Tuttavia, per la situazione qui, un controllo di mantenimento usando i bordi 1 e 5 non è desiderabile, poiché l'unico modo per risolverlo è aggiungere un intero ciclo di ritardo del percorso sul percorso.

Il vincolo di blocco multi-ciclo di 1 (per mantenimento, il valore predefinito è 0) regola il bordo dell'orologio di destinazione utilizzato per i controlli di mantenimento all'indietro di un bordo. La combinazione dei vincoli MCP di impostazione a 2 cicli e MCP di blocco a 1 ciclo comporterà un controllo di configurazione utilizzando i bordi 2 e 7 e un controllo di mantenimento utilizzando i bordi 1 e 4.


2

Non conosco la risposta per Altera, ma in Xilinx Land puoi impostare il ritardo da un dominio di clock a quello successivo. Dovrai elaborare la matematica (dipende dal design), ma di solito è il più breve dei due periodi di clock. Pensa a questo momento come l'inclinazione massima tra due segnali (incluso il segnale di controllo) e puoi capire se il tuo circuito di sincronizzazione sarà in grado di gestirlo.

set_mulicycle_path non è la cosa corretta da usare perché normalmente si occuperebbe dei casi in cui sia l'origine che la destinazione si trovano sullo stesso dominio di clock. Ancora una volta, lo sto basando sulla mia esperienza Xilinx in modo che il tuo chilometraggio possa variare.


1

Penso che sia sicuro mettere un set_false_path sul sincronizzatore.

Inoltre potresti inserire "set_global_assignment -name SYNCHRONIZER_IDENTIFICATION AUTO" nel qsf per aiutare Quartus a individuare il sincronizzatore.


Come sarebbe? set_false_path -from ready_spin -to ready_spin_q2? E set_false_path -from data -to rx_data?
Ben Voigt,

set_false_path -from src_clk -to ready_spinNon sono sicuro che sia appropriato inserire il percorso falso sui dati poiché non lo si sta sincronizzando.
fbo,

0

Sospetto che il problema sia che, sebbene tu possa sapere che i segnali del bus non cambieranno da nessuna parte vicino al punto in cui sono bloccati, il software non lo sa. La tua scommessa migliore è probabilmente quella di dire esplicitamente al software che i segnali del bus in entrata sono sincronizzati con l'orologio del bus e disabilitare tutte le ottimizzazioni in anticipo rispetto al punto in cui le stai effettivamente bloccando (un ottimizzatore potrebbe teoricamente sostituire il tuo circuito con uno che sarebbe equivalente se gli ingressi fossero davvero sincroni, ma che potrebbero essere generati per un loop se cambiassero su cicli di clock di cui il circuito disegnato non sarebbe interessato).


Non set_multicycle_pathsarebbe il modo di dire al sintetizzatore / analizzatore di temporizzazione quanto spesso i segnali sorgente possono cambiare? E non sono sicuro di cosa intendi per "orologio del bus", qui c'è un bus di segnale che attraversa i domini di clock, quindi quale orologio stai chiamando "bus clock"? Penso che tu abbia ragione che potrebbe esserci ancora metastabilità se il sintetizzatore introduce problemi durante i periodi in cui non sto aggiornando data. Immagino di poter istanziare in modo specifico i blocchi DFF lì :(
Ben Voigt,

@BenVoigt: Penso che "set_multicycle_path" sia più spesso usato per dire al validatore di temporizzazione che una catena di logica combinatoria tra due punti di aggancio dovrebbe essere autorizzata a prendere N (Tc) -Ts-Tp (N tempi di ciclo meno tempo di campionamento meno latch tempo di propagazione) anziché solo Tc-Ts-Th. Non so come una cosa del genere possa interagire con il blocco di diversi orologi.
supercat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.