Portée de référence hiérarchique Verilog
La plupart des langages de programmation ont une caractéristique appelée portée qui définit la visibilité de certaines sections de code aux variables et aux 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, les fonctions, les tâches, les blocs nommés et les blocs de génération.
module tb;
reg signal;
// Another variable cannot be declared with
// an already existing name in the same scope
reg signal;
// However, the name 'signal' can be reused inside
// a task because it belongs to a different scope.
task display();
reg signal = 1;
$display("signal = %0b", signal);
endtask
endmodule
Un identifiant, comme un nom de signal, peut être utilisé pour déclarer 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 tâche et une variable du même nom, ou même une instance net et gate avec le même nom dans la même portée.
Chaque identifiant dans Verilog a un nom de chemin hiérarchique unique, où chaque instance de module, tâche, fonction ou nommé begin end
ou fork join
bloc définit un nouveau niveau ou une nouvelle portée.
Exemple de référence hiérarchique
module tb;
// Create two instances of different modules
A uA();
B uB();
// Create a named block that declares a signal and
// prints the value at 10ns from simulation start
initial begin : TB_INITIAL
reg signal;
#10 $display("signal=%0d", signal);
end
// We'll try to access other scopes using hierarchical
// references from this initial block
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érencement du nom vers le haut
Un module de niveau inférieur peut référencer des éléments dans un module au-dessus de lui dans la hiérarchie. Par exemple, le signal dans le bloc TB_INITIAL serait visible depuis la tâche d'affichage dans A.
module A;
task display();
$display("Hello, this is A");
// Upward referencing, TB_INITIAL is visible in this module
#5 TB_INITIAL.signal = 1;
endtask
endmodule
Notez que le signal TB est maintenant 1 au lieu de 0, en raison du changement de référencement vers le haut apporté au signal par le module A.
Journal de simulationxcelium> 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 ci-dessus via une référence hiérarchique ascendante.
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(); // or A.display()
b.display(); // or B.display()
c.display(); // or 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.
Lorsque le compilateur trouve b.display(),
- Il regarde dans la portée actuelle du module D pour voir si b est défini. S'il n'existe pas, il recherche le nom dans la portée englobante et se déplace vers le haut jusqu'à ce que la portée du module soit atteinte. Si le nom n'est toujours pas trouvé, il passe à l'étape suivante.
- Il recherche dans la portée la plus externe du module parent et s'il n'est pas trouvé, il continue de remonter dans la hiérarchie.
Verilog