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

Maîtriser la Portée de Référence Hiérarchique Verilog : Éviter les Collisions de Noms dans les Modules et Blocs

La plupart des langages de programmation ont une caractéristique appelée portée (scope) qui définit la visibilité de certaines sections de code aux variables et méthodes. La portée définit un espace de noms pour éviter les collisions entre différents noms d'objets dans le même espace de noms.

Verilog définit une nouvelle portée pour les modules, fonctions, tasks, blocs nommés et blocs generate.

module tb;
  reg signal;
  // Une autre variable ne peut pas être déclarée avec
  // un nom déjà existant dans la même portée
  reg signal; // Erreur !
  // Cependant, le nom 'signal' peut être réutilisé à l'intérieur
  // d'une task car elle appartient à une portée différente.
  task display();
    reg signal = 1;
    $display("signal = %0b", signal);
  endtask
endmodule

Un identifiant, comme un nom de signal, ne peut être utilisé pour déclarer qu'un seul type d'élément dans une portée donnée. Cela signifie que deux variables de types de données différents ou identiques ne peuvent pas avoir le même nom, ou une task et une variable du même nom, ou même un net et une instance de porte avec le même nom dans la même portée.

Chaque identifiant en Verilog a un nom de chemin hiérarchique unique, où chaque instance de module, task, function ou bloc nommé begin end ou fork join définit un nouveau niveau ou portée.

Exemple de Référence Hiérarchique

module tb;
  // Créer deux instances de modules différents
  A uA();
  B uB();
  // Créer un bloc nommé qui déclare un signal et
  // affiche la valeur à 10ns depuis le début de la simulation
  initial begin : TB_INITIAL
    reg signal;
    #10 $display("signal=%0d", signal);
  end
  // Nous allons essayer d'accéder à d'autres portées en utilisant des
  // références hiérarchiques depuis ce bloc initial
  initial begin
    TB_INITIAL.signal = 0;
    uA.display();
    uB.B_INITIAL.B_INITIAL_BLOCK1.b_signal_1 = 1;
    uB.B_INITIAL.B_INITIAL_BLOCK2.b_signal_2 = 0;
  end
endmodule
module A;
  task display();
    $display("Hello, this is A");
  endtask
endmodule

module B;
  initial begin : B_INITIAL
    #50;
    begin : B_INITIAL_BLOCK1
      reg b_signal_1;
      #10 $display("signal_1=%0d", b_signal_1);
    end
    #50;
    begin : B_INITIAL_BLOCK2
      reg b_signal_2;
      #10 $display("signal_2=%0d", b_signal_2);
    end
  end
endmodule

Journal de Simulation

xcelium> run
Hello, this is A
TB signal=0
signal_1=1
signal_2=0
xmsim: *W,RNQUIE: Simulation is complete.

Référence de Nom Vers le Haut

Un module de niveau inférieur peut référencer des éléments dans un module au-dessus dans la hiérarchie. Par exemple, signal dans le bloc TB_INITIAL serait visible depuis la task display dans A.

module A;
  task display();
    $display("Hello, this is A");
    // Référence vers le haut, TB_INITIAL est visible dans ce module
    #5 TB_INITIAL.signal = 1;
  endtask
endmodule

Notez que le signal TB est maintenant 1 au lieu de 0, à cause du changement de référence vers le haut fait au signal par le module A.

Journal de Simulation

xcelium> run
Hello, this is A
TB signal=1
signal_1=1
signal_2=0
xmsim: *W,RNQUIE: Simulation is complete.

Voici un autre exemple avec plusieurs modules imbriqués et le nœud feuille peut accéder directement aux membres des nœuds du haut par référence hiérarchique vers le haut.

module tb;
  A a();
  function display();
    $display("Hello, this is TB");
  endfunction
endmodule

module A;
  B b();
  function display();
    $display("Hello, this is A");
  endfunction
endmodule

module B;
  C c();
  function display();
    $display("Hello, this is B");
  endfunction
endmodule

module C;
  D d();
  function display();
    $display("Hello, this is C");
  endfunction
endmodule

module D;
  initial begin
    a.display(); // ou A.display()
    b.display(); // ou B.display()
    c.display(); // ou C.display()
    a.b.c.display();
  end
endmodule

Journal de Simulation

xcelium> run
Hello, this is A
Hello, this is B
Hello, this is C
Hello, this is C
xmsim: *W,RNQUIE: Simulation is complete.

Quand le compilateur trouve b.display(),

  1. Il regarde dans la portée courante dans le module D pour voir si b est défini. S'il n'existe pas, alors il cherche le nom dans la portée englobante et monte jusqu'à ce que la portée du module soit atteinte. Si le nom n'est toujours pas trouvé, il passe à l'étape suivante.
  2. Il regarde dans la portée la plus externe du module parent et s'il n'est pas trouvé, il continue de monter dans la hiérarchie.

Verilog

  1. Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
  2. Maîtriser la concaténation Verilog : Guide pratique
  3. Verilog Essentiel : Aperçu concis
  4. Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
  5. Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
  6. Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
  7. Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation
  8. Maîtriser la Portée de Référence Hiérarchique Verilog : Éviter les Collisions de Noms dans les Modules et Blocs
  9. Générateur d'Horloge Verilog : Guide de Conception et d'Implémentation