Affectation bloquante (=) vs non bloquante (<=) en Verilog

Ce sont deux affectations utilisées dans les blocs always de Verilog, mais le membre de gauche n'est pas mis à jour au même moment. L'affectation bloquante (=) met à jour le membre de gauche dès que la ligne est exécutée, et la ligne suivante utilise la nouvelle valeur. L'affectation non bloquante (<=) évalue d'abord tous les membres de droite du même instant, puis met à jour ensemble les membres de gauche. La règle de base est d'utiliser <= pour la logique séquentielle cadencée par l'horloge et = pour les always de logique combinatoire.

CritèreAffectation bloquante (=)Affectation non bloquante (<=)
Écriturea = b;a <= b;
Mise à jour du membre de gaucheImmédiate, dès que la ligne est exécutéeGroupée, après l'évaluation de tous les membres de droite du même instant
Valeur vue par la ligne suivanteLa nouvelle valeur, après mise à jourL'ancienne valeur, avant mise à jour
Dépendance à l'ordre d'écritureOui. Permuter les lignes change le résultatQuasi nulle. Toutefois, si une même variable est affectée deux fois, c'est la dernière affectation qui l'emporte
Comportement matériel correspondantLogique combinatoire qui calcule les valeurs intermédiaires dans l'ordre, de haut en basBascules qui capturent toutes leurs valeurs en même temps au front d'horloge
Usage principalalways @(*) de logique combinatoire, procédures de testbenchalways @(posedge clk) de logique séquentielle cadencée par l'horloge
Registre à décalage à deux étages (bloc cadencé par l'horloge)Avec q1 = d; q2 = q1;, q2 reçoit aussi d au même front : un seul étage de retardAvec q1 <= d; q2 <= q1;, q2 reçoit la valeur de q1 d'avant le front : deux étages
Échange de valeurs (bloc cadencé par l'horloge)Avec a = b; b = a;, a et b prennent la même valeurAvec a <= b; b <= a;, a et b sont échangés
Entre plusieurs blocs alwaysEntre blocs déclenchés par le même front, des courses (race) où le résultat dépend de l'ordre d'exécution apparaissent facilementLes membres de droite sont tous évalués d'abord, d'où peu de courses
En cas de mauvais usageUtilisée en logique séquentielle, le résultat dépend de l'ordre d'exécution des blocs et peut différer du comportement du circuit synthétiséUtilisée en logique combinatoire, des valeurs intermédiaires périmées sont lues : la simulation peut différer du circuit synthétisé, ou le bloc est réexécuté inutilement

Les valeurs indiquées sont des ordres de grandeur typiques et varient selon la génération de procédé et le produit.

Quand choisir l'un ou l'autre ?

Affectation bloquante (=)
Pour calculer dans l'ordre des valeurs intermédiaires dans un always @(*) de logique combinatoire. Pour décrire des étapes dans l'ordre dans un testbench.
Affectation non bloquante (<=)
Pour décrire des bascules cadencées par l'horloge, comme dans always @(posedge clk) : mise à jour des registres, des compteurs et de l'état des machines à états.
Ne pas mélanger
Ne mélangez pas = et <= dans un même bloc always, et n'affectez pas une même variable depuis plusieurs blocs always. En SystemVerilog, always_ff et always_comb permettent d'indiquer l'intention aux outils.

Questions fréquentes

Que se passe-t-il si l'on utilise l'affectation bloquante en logique séquentielle ?

Selon l'ordre des lignes, une valeur mise à jour au même front est transmise telle quelle à la ligne suivante, et l'on obtient un circuit avec moins d'étages que prévu. De plus, avec d'autres blocs always cadencés par la même horloge, des courses où le résultat dépend de l'ordre d'exécution apparaissent, ce qui provoque des écarts entre la simulation et le circuit synthétisé.

Pourquoi a <= b; b <= a; échange-t-il les valeurs avec l'affectation non bloquante ?

Parce que les deux membres de droite sont d'abord évalués avec les anciennes valeurs, puis les membres de gauche sont mis à jour ensemble. Le comportement est le même que celui d'un circuit où la sortie de chacune de deux bascules est reliée à l'entrée de l'autre.

Laquelle utiliser dans un testbench ?

L'affectation bloquante convient pour les parties qui décrivent des étapes dans l'ordre. Cependant, si l'on change les entrées du circuit au même instant que le front d'horloge, la capture de l'ancienne ou de la nouvelle valeur dépend de l'ordre d'exécution : on les change donc légèrement décalées par rapport au front, ou avec une affectation non bloquante.

Vérifier vos connaissances

Quel est le comportement de l'affectation non bloquante (<=) en Verilog ?

  1. ALe membre de gauche est mis à jour à l'instant de l'affectation et la nouvelle valeur est utilisée à la ligne suivante
  2. BTous les membres de droite d'un même instant sont d'abord évalués, puis les membres de gauche sont mis à jour ensemble
  3. CLe résultat de l'affectation est ignoré et rien n'est modifié
Afficher la réponse et l'explication

Réponse : B. Tous les membres de droite d'un même instant sont d'abord évalués, puis les membres de gauche sont mis à jour ensemble

Avec l'affectation non bloquante, au front d'horloge, tous les membres de droite des <= sont d'abord évalués avec les anciennes valeurs, puis les membres de gauche sont réécrits simultanément. C'est le même comportement que dans un circuit réel où de nombreuses bascules cadencées par la même horloge capturent simultanément les valeurs juste avant le front. En principe, on utilise donc l'affectation non bloquante pour décrire les circuits séquentiels cadencés.

Quelle est la règle générale d'usage des types d'affectation en Verilog ?

  1. AN'utiliser partout que l'affectation bloquante (=)
  2. BUtiliser l'affectation non bloquante (<=) pour les circuits séquentiels cadencés, et l'affectation bloquante (=) dans les always des circuits combinatoires
  3. CMélanger arbitrairement les deux dans un même always
Afficher la réponse et l'explication

Réponse : B. Utiliser l'affectation non bloquante (<=) pour les circuits séquentiels cadencés, et l'affectation bloquante (=) dans les always des circuits combinatoires

Écrire les circuits séquentiels en affectation non bloquante correspond au comportement d'un circuit où toutes les bascules capturent simultanément, et le résultat ne dépend ni de l'ordre d'écriture ni de l'ordre d'exécution vis-à-vis des autres blocs always. Pour les circuits combinatoires, calculer les valeurs intermédiaires de haut en bas est naturel ; on utilise donc l'affectation bloquante. Il importe aussi de ne pas mélanger les deux dans un même bloc always.

Dans un banc de test, modifier les entrées du circuit par affectation bloquante au même instant que le front montant d'horloge peut poser problème. Quelle combinaison de raison principale et de remède est correcte ?

  1. ALa valeur capturée, d'avant ou d'après le changement, dépend de l'ordre d'exécution (course) ; on décale légèrement les entrées par rapport au front d'horloge ou on les modifie par affectation non bloquante
  2. BLa fréquence d'horloge baisse automatiquement ; on accélère l'horloge
  3. CL'affectation bloquante est interdite dans les bancs de test ; on utilise uniquement des instructions assign
Afficher la réponse et l'explication

Réponse : A. La valeur capturée, d'avant ou d'après le changement, dépend de l'ordre d'exécution (course) ; on décale légèrement les entrées par rapport au front d'horloge ou on les modifie par affectation non bloquante

Si, au même instant, le banc de test réécrit les entrées et les bascules du circuit les capturent, la valeur capturée sera ancienne ou nouvelle selon l'ordre d'exécution choisi par le simulateur. C'est une course (race) de simulation, dont le résultat peut varier d'un simulateur à l'autre. On l'évite en modifiant les entrées sur le front descendant, en les retardant légèrement, ou en utilisant l'affectation non bloquante ou les clocking blocks de SystemVerilog.

  1. Dans la description ci-dessus, juste avant le front montant d'horloge, a=0 et b=1. Quelles sont les valeurs de a et b après le front montant ?
  2. Voulant un registre à décalage à deux étages, on a écrit le code ci-dessus avec des affectations bloquantes (=). Quel problème survient ?
  3. Voulant un circuit combinatoire, on a écrit le code ci-dessus. Quel problème peut survenir ?

Questions d'entraînement sur HDL et vérification

Termes clés expliqués

Affectation bloquante
Affectation « = » de Verilog. Le membre de gauche est mis à jour immédiatement et la nouvelle valeur est utilisée dès la ligne suivante. Utilisée dans les always combinatoires et les bancs de test.
Affectation non bloquante
Affectation « <= » de Verilog. Tous les membres de droite d'un même instant sont d'abord évalués, puis les membres de gauche sont mis à jour ensemble. Correspondant au comportement des bascules, elle s'utilise pour les circuits séquentiels.
Liste de sensibilité
Liste des signaux écrite dans @( ) après always en Verilog, qui déclenchent l'exécution du bloc. Un oubli dans un circuit combinatoire crée un écart entre la simulation et le circuit.
Verilog
Langage de description matérielle très utilisé pour la conception et la vérification de circuits numériques. Les circuits sont décrits par modules (module) et le comportement par assign ou always.

Comparatifs associés