contrainte de synchronisation pour les circuits du synchroniseur de bus

10

J'ai un circuit de synchronisation de bus pour passer un registre large à travers les domaines d'horloge.

Je vais fournir une description simplifiée, en omettant la logique de réinitialisation asynchrone.

Les données sont générées sur une horloge. Les mises à jour sont éloignées de plusieurs (au moins une douzaine) fronts d'horloge:

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;

Le signal de commande pour les nouvelles données, qui est codé NRZI (donc un mot valide sur le bus correspond à une transition sur le signal de commande). Le signal de commande passe à travers une chaîne DFF faisant office de synchroniseur.

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;

Le circuit de synchronisation introduit un court délai, ce qui laisse suffisamment de temps au bus de données pour se stabiliser; le bus de données est échantillonné directement sans risque de métastabilité:

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;

Cela se compile et fonctionne bien lorsqu'il est synthétisé dans un FPGA Cyclone II. Cependant, TimeQuest signale les violations de temps de configuration et de blocage, car il ne reconnaît pas le synchroniseur. Pire, le manuel Quartus dit

Concentrez-vous sur l'amélioration des chemins qui présentent le pire ralentissement. Le monteur travaille le plus dur sur les chemins avec le pire jeu. Si vous corrigez ces chemins, l'installateur pourrait être en mesure d'améliorer les autres chemins de synchronisation défaillants dans la conception.

Je veux donc ajouter les bonnes contraintes de timing à mon projet afin que Quartus consacre ses efforts d'ajusteur à d'autres domaines de la conception.

Je suis à peu près sûr que set_multicycle_pathc'est la commande SDC (Synopsis Design Constraint) appropriée, car les lignes de données auront plusieurs cycles de l'horloge de destination pour se stabiliser, mais je ne trouve aucun exemple complet utilisant cette commande pour décrire la logique de croisement de domaine d'horloge .

J'apprécierais vraiment quelques conseils sur l'écriture des contraintes de synchronisation SDC pour les synchroniseurs. Si vous voyez un problème avec cette approche, faites-le moi savoir également.


Détail de l'horloge:

Générateur d'horloge externe: deux canaux, refclk = 20 MHz, refclk2 = refclk / 2 (10 MHz et connexes).

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

Altera PLL: dest_clk = refclk2 * 10 = 100 MHz

J'ai également des données allant dans l'autre sens, avec 100 MHz src_clk et 36 MHz dest_clk.


TL; DR: Quelles sont les contraintes de synchronisation SDC correctes pour le code ci-dessus?

Ben Voigt
la source
1
Ce serait mieux sur le site FPGA Design proposé, mais cette proposition n'a pas encore atteint la version bêta.
Ben Voigt
Pouvez-vous publier les définitions d'horloge pour src_clk et dest_clk? Sont-ils liés de quelque façon que ce soit (multiples synchrones)? Si ce sont des horloges indépendantes, il est typique d'utiliser set_false_path dans cette situation.
Andy
@Andy: J'ai ajouté certains détails. Merci pour votre aide.
Ben Voigt

Réponses:

9

Je n'ai pas d'expérience avec Quartus, alors considérez cela comme un conseil général.

Lorsque vous travaillez sur des chemins entre des domaines d'horloge, les outils de temporisation étendent les horloges au multiple le moins commun de leurs périodes et sélectionnent la paire d'arêtes la plus proche.

Pour les trajets allant d'une horloge de 36 MHz (27,777 ns) à une horloge de 100 MHz (10 ns), si j'ai fait mes calculs rapides correctement, la paire de fronts montants la plus proche est de 138,888 ns sur l'horloge source et 140 ns sur l'horloge de destination. C'est effectivement une contrainte de 900 MHz pour ces chemins! Selon l'arrondissement (ou pour les horloges sans relation), cela pourrait être pire que cela.

Il existe au moins trois façons d'écrire des contraintes pour cette structure. Je vais appeler les horloges fast_clket slow_clkcomme je pense que c'est plus clair à titre d'illustration.

Option 1: désactiver le chronométrage avec set_false_path

La solution la plus simple consiste à set_false_pathdésactiver le chronométrage entre les horloges:

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]

Ce n'est pas strictement correct, car le synchroniseur doit fonctionner correctement. Si l'implémentation physique retarde trop les données par rapport au signal de commande, le synchroniseur ne fonctionnera pas. Cependant, comme il n'y a aucune logique sur le chemin, il est peu probable que la contrainte de temps soit violée. set_false_pathest couramment utilisé pour ce type de structure, même dans les ASIC, où le compromis effort / risque pour les défaillances à faible probabilité est plus prudent que pour les FPGA.

Option 2: assouplissez la contrainte avec set_multicycle_path

Vous pouvez prévoir du temps supplémentaire pour certains chemins d'accès avec set_multicycle_path. Il est plus courant d'utiliser des trajets multicycliques avec des horloges étroitement liées (par exemple, des horloges 1X et 2X en interaction), mais cela fonctionnera ici si l'outil le prend en charge suffisamment.

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 relation de bord par défaut pour la configuration est un cycle unique, c'est-à-dire set_multicycle_path 1. Ces commandes permettent un cycle supplémentaire de l'horloge de point de terminaison ( -end) pour les chemins de configuration. L' -holdajustement avec un numéro un de moins que la contrainte de configuration est presque toujours nécessaire lors de la définition de pistes cyclables multiples, pour plus d'informations, voir ci-dessous.

Pour contraindre les trajectoires dans l'autre sens de la même manière (en relâchant la contrainte d'une période de l'horloge la plus rapide), passez -endà -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

Option 3: spécifiez l'exigence directement avec set_max_delay

Ceci est similaire à l'effet de set_multicycle_pathmais évite d'avoir à réfléchir aux relations de bord et à l'effet sur les contraintes de maintien.

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]

Vous pouvez le coupler avec set_min_delaypour les contrôles de retenue, ou laisser le contrôle de retenue par défaut en place. Vous pouvez également être en mesure de set_false_path -holddésactiver les contrôles de retenue, si votre outil le prend en charge.


Détails sanglants de la sélection des bords pour les chemins multi-cycles

Pour comprendre l'ajustement de maintien associé à chaque ajustement de configuration, considérez cet exemple simple avec une relation 3: 2. Chaque chiffre représente un front d'horloge montant:

1     2     3
4   5   6   7

La vérification de configuration par défaut utilise les bords 2 et 6. La vérification de maintien par défaut utilise les bords 1 et 4.

L'application d'une contrainte multi-cycle de 2 avec -endajuste la configuration par défaut et les contrôles de retenue pour utiliser le bord suivant après ce qu'ils utilisaient à l'origine, ce qui signifie que le contrôle de configuration utilise maintenant les bords 2 et 7 et le contrôle de retenue utilise les bords 1 et 5. Pour deux des horloges à la même fréquence, cet ajustement a du sens - chaque lancement de données correspond à une capture de données, et si le bord de capture est déplacé de un, la vérification de maintien doit également se déplacer de un. Ce type de contrainte peut avoir un sens pour deux branches d'une même horloge si l'une des branches présente un retard important. Cependant, pour la situation ici, un contrôle de maintien en utilisant les bords 1 et 5 n'est pas souhaitable, car la seule façon de le corriger est d'ajouter un cycle d'horloge complet de retard sur le chemin.

La contrainte de maintien multi-cycle de 1 (pour le maintien, la valeur par défaut est 0) ajuste le bord de l'horloge de destination uesd pour les contrôles de maintien en arrière d'un bord. La combinaison de MCP de configuration à 2 cycles et de contraintes MCP de maintien à 1 cycle entraînera une vérification de configuration à l'aide des bords 2 et 7 et une vérification de maintien à l'aide des bords 1 et 4.

Andy
la source
2

Je ne connais pas la réponse pour Altera, mais dans Xilinx Land, vous pouvez définir le délai d'un domaine d'horloge au suivant. Vous devrez travailler sur les mathématiques (cela dépend de la conception), mais c'est généralement la plus courte des deux périodes d'horloge. Considérez cette fois comme le décalage maximal entre deux signaux quelconques (y compris votre signal de contrôle), et vous pouvez déterminer si votre circuit de synchronisation va pouvoir y faire face.

set_mulicycle_path n'est pas la bonne chose à utiliser car cela traiterait normalement des cas où la source et la destination sont sur le même domaine d'horloge. Encore une fois, je fonde cela sur mon expérience Xilinx donc votre kilométrage peut varier.


la source
1

Je pense qu'il est sûr de mettre un set_false_path sur le synchroniseur.

Vous pouvez également mettre "set_global_assignment -name SYNCHRONIZER_IDENTIFICATION AUTO" dans le qsf pour aider Quartus à repérer le synchroniseur.

fbo
la source
À quoi cela ressemblerait-il? set_false_path -from ready_spin -to ready_spin_q2? Et set_false_path -from data -to rx_data?
Ben Voigt
set_false_path -from src_clk -to ready_spinJe ne suis pas sûr qu'il soit approprié de mettre le faux chemin sur les données puisque vous ne les synchronisez pas.
fbo
0

Je soupçonne que le problème est que, même si vous savez que les signaux du bus ne changeront pas près du point où ils sont verrouillés, le logiciel ne le sait pas. Votre meilleur pari est probablement de dire explicitement au logiciel que les signaux de bus entrants sont synchronisés avec l'horloge du bus, et de désactiver toutes les optimisations avant l'endroit où vous les verrouillez réellement (un optimiseur pourrait théoriquement remplacer votre circuit par un circuit qui serait équivalent si les entrées étaient vraiment synchrones, mais qui pourraient être lancées pour une boucle si elles changent sur des cycles d'horloge dont le circuit que vous avez tracé ne se soucierait pas).

supercat
la source
Ne serait-ce pas set_multicycle_pathle moyen de dire au synthétiseur / analyseur de synchronisation à quelle fréquence les signaux source peuvent changer? Et je ne suis pas sûr de ce que vous entendez par "horloge de bus", il y a un bus de signal qui traverse les domaines d'horloge, alors quelle horloge appelez-vous l '"horloge de bus"? Je pense que vous avez raison, il pourrait toujours y avoir une métastabilité si le synthétiseur introduisait des problèmes pendant les périodes où je ne mettais pas à jour data. Je suppose que je pourrais spécifiquement instancier des blocs DFF là-bas :(
Ben Voigt
@BenVoigt: Je pense que "set_multicycle_path" est plus souvent utilisé pour dire au validateur de synchronisation qu'une chaîne de logique combinatoire entre deux points de verrouillage devrait être autorisée à prendre N (Tc) -Ts-Tp (N fois le temps de cycle moins le temps d'échantillonnage moins le verrou) temps de propagation) au lieu de simplement Tc-Ts-Th. Je ne sais pas comment une telle chose interagirait avec le verrouillage par différentes horloges.
supercat