Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Verilog

Verilog Blocking vs Non-Blocking : Différences Clés Expliquées

Assignations Bloquantes (Blocking)

Les instructions d'affectation bloquantes utilisent le symbole = et sont exécutées les unes après les autres dans un bloc procédural. Cependant, cela n'empêche pas l'exécution d'instructions qui s'exécutent dans un bloc parallèle.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a = 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    b = 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c = 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    d = 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    e = 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

Notez qu'il y a deux blocs initial qui s'exécutent en parallèle au démarrage de la simulation. Les instructions sont exécutées séquentiellement dans chaque bloc et les deux blocs se terminent à 0ns. Plus précisément, la variable a est affectée en premier, suivie de l'instruction display qui est ensuite suivie de toutes les autres instructions. Cela est visible dans la sortie où les variables b et c sont 8'hxx dans la première instruction display. C'est parce que les affectations des variables b et c n'ont pas encore été exécutées lorsque le premier $display est appelé.

Journal de Simulation

ncsim> run
[0] a=0xda b=0xx c=0xx
[0] a=0xda b=0xf1 c=0xx
[0] a=0xda b=0xf1 c=0x30
[0] d=0xaa e=0xx
[0] d=0xaa e=0x55
ncsim: *W,RNQUIE: Simulation is complete.

Dans l'exemple suivant, nous ajouterons quelques délais au même ensemble d'instructions pour voir comment cela se comporte.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a = 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    #10 b = 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c = 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    #5 d = 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    #5 e = 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

Journal de Simulation

ncsim> run
[0] a=0xda b=0xx c=0xx
[5] d=0xaa e=0xx
[10] a=0xda b=0xf1 c=0xx
[10] a=0xda b=0xf1 c=0x30
[10] d=0xaa e=0x55
ncsim: *W,RNQUIE: Simulation is complete.

Assignations Non-Bloquantes (Non-blocking)

L'affectation non-bloquante permet de planifier des affectations sans bloquer l'exécution des instructions suivantes et est spécifiée par le symbole <=. Il est intéressant de noter que le même symbole est utilisé comme opérateur relationnel dans les expressions, et comme opérateur d'affectation dans le contexte d'une affectation non-bloquante. Si nous reprenons le premier exemple ci-dessus et remplaçons tous les symboles = par l'opérateur d'affectation non-bloquante <=, nous verrons une différence dans la sortie.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a <= 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    b <= 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c <= 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    d <= 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    e <= 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

On voit que toutes les instructions $display ont affiché 'h'x. La raison de ce comportement réside dans la façon dont les affectations non-bloquantes sont exécutées. Le RHS de chaque instruction non-bloquante d'un pas de temps particulier est capturé, puis on passe à l'instruction suivante. La valeur RHS capturée est affectée à la variable LHS seulement à la fin du pas de temps.

Journal de Simulation

ncsim> run
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] d=0xx e=0xx
[0] d=0xx e=0xx
ncsim: *W,RNQUIE: Simulation is complete.

Si nous décomposons le flux d'exécution de l'exemple ci-dessus, nous obtenons quelque chose comme ce qui est montré ci-dessous.

|__ Spawn Block1: initial
| |___ Time #0ns : a <= 8'DA, est non-bloquant donc note la valeur du RHS (8'hDA) et exécute l'étape suivante
| |___ Time #0ns : $display() est bloquant, donc exécute cette instruction : Mais a n'a pas reçu les nouvelles valeurs donc a=8'hx
| |___ Time #0ns : b <= 8'F1, est non-bloquant donc note la valeur du RHS (8'hF1) et exécute l'étape suivante
| |___ Time #0ns : $display() est bloquant, donc exécute cette instruction. Mais b n'a pas reçu les nouvelles valeurs donc b=8'hx
| |___ Time #0ns : c <= 8'30, est non-bloquant donc note la valeur du RHS (8'h30) et exécute l'étape suivante
| |___ Time #0ns : $display() est bloquant, donc exécute cette instruction. Mais c n'a pas reçu les nouvelles valeurs donc c=8'hx
| |___ Fin du pas de temps et du bloc initial, affecte les valeurs capturées dans les variables a, b, c
| |__ Spawn Block2: initial
| |___ Time #0ns : d <= 8'AA, est non-bloquant donc note la valeur du RHS (8'hAA) et exécute l'étape suivante
| |___ Time #0ns : $display() est bloquant, donc exécute cette instruction : Mais d n'a pas reçu les nouvelles valeurs donc d=8'hx
| |___ Time #0ns : e <= 8'55, est non-bloquant donc note la valeur du RHS (8'h55) et exécute l'étape suivante
| |___ Time #0ns : $display() est bloquant, donc exécute cette instruction. Mais e n'a pas reçu les nouvelles valeurs donc e=8'hx
| |___ Fin du pas de temps et du bloc initial, affecte les valeurs capturées dans les variables d et e
| |__ Fin de la simulation à #0ns

Ensuite, utilisons le second exemple et remplaçons toutes les instructions bloquantes par des non-bloquantes.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a <= 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    #10 b <= 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c <= 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    #5 d <= 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    #5 e <= 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

Une fois de plus, on peut voir que la sortie est différente de ce que nous avions obtenu auparavant.

Journal de Simulation

ncsim> run
[0] a=0xx b=0xx c=0xx
[5] d=0xx e=0xx
[10] a=0xda b=0xx c=0xx
[10] a=0xda b=0xx c=0xx
[10] d=0xaa e=0xx
ncsim: *W,RNQUIE: Simulation is complete.

Si nous décomposons le flux d'exécution, nous obtenons quelque chose comme ce qui est montré ci-dessous.

|__ Spawn Block1 à #0ns: initial
| |___ Time #0ns : a <= 8'DA, est non-bloquant donc note la valeur du RHS (8'hDA) et exécute l'étape suivante
| |___ Time #0ns : $display() est bloquant, donc exécute cette instruction : Mais a n'a pas reçu les nouvelles valeurs donc a=8'hx
| |___ Fin du pas de temps : Affecte la valeur capturée à la variable a, et a est maintenant 8'hDA
| |___ Attend que le temps avance de 10 unités de temps à #10ns
| | |___ Time #10ns : b <= 8'F1, est non-bloquant donc note la valeur du RHS (8'hF1) et exécute l'étape suivante
| |___ Time #10ns : $display() est bloquant, donc exécute cette instruction. Mais b n'a pas reçu les nouvelles valeurs donc b=8'hx
| |___ Time #10ns : c <= 8'30, est non-bloquant donc note la valeur du RHS (8'h30) et exécute l'étape suivante
| |___ Time #10ns : $display() est bloquant, donc exécute cette instruction. Mais c n'a pas reçu les nouvelles valeurs donc c=8'hx
| |___ Fin du pas de temps et du bloc initial, affecte les valeurs capturées dans les variables b, c
| |__ Spawn Block2 à #0ns: initial
| |___ Attend que le temps avance de 5 unités de temps à #5ns
| | |___ Time #5ns : d <= 8'AA, est non-bloquant donc note la valeur du RHS (8'hAA) et exécute l'étape suivante
| |___ Time #5ns : $display() est bloquant, donc exécute cette instruction : Mais d n'a pas reçu les nouvelles valeurs donc d=8'hx
| |___ Fin du pas de temps : Affecte la valeur capturée à la variable d, et d est maintenant 8'hAA
| |___ Attend que le temps avance de 5 unités de temps à #5ns
| | |___ Time #10ns : e <= 8'55, est non-bloquant donc note la valeur du RHS (8'h55) et exécute l'étape suivante
| |___ Time #10ns : $display() est bloquant, donc exécute cette instruction. Mais e n'a pas reçu les nouvelles valeurs donc e=8'hx
| |___ Fin du pas de temps et du bloc initial, affecte les valeurs capturées à la variable e, et e est maintenant 8'h55
| |__ Fin de la simulation à #10ns

Verilog

  1. Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
  2. Maîtriser la concaténation Verilog : Guide pratique
  3. Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
  4. Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation
  5. Générateur d'Horloge Verilog : Guide de Conception et d'Implémentation
  6. Maîtriser les Fonctions Mathématiques Verilog pour une Conception Matérielle Efficace
  7. Maîtriser Verilog $timeformat : Contrôle de Précision et d'Affichage
  8. Comprendre et Afficher les Timescales Verilog à Toute Portée
  9. Maîtriser les entrées/sorties de fichiers en Verilog : Ouvrir, Lire, Écrire et Fermer