Verilog Hiërarchische Referentie Scope: Naamconflicten in Modules en Blokken vermijden
Meeste programmeertalen hebben een karakteristiek kenmerk genaamd scope dat de zichtbaarheid van bepaalde codesecties voor variabelen en methoden definieert. De scope definieert een namespace om botsing tussen verschillende objectnamen binnen dezelfde namespace te voorkomen.
Verilog definieert een nieuwe scope voor modules, functies, tasks, benoemde blokken en generate-blokken.
module tb;
reg signal;
// Een andere variabele kan niet gedeclareerd worden met
// een al bestaande naam in dezelfde scope
reg signal; // Fout!
// De naam 'signal' kan wel hergebruikt worden binnen
// een task want die behoort tot een andere scope.
task display();
reg signal = 1;
$display("signal = %0b", signal);
endtask
endmodule
Een identifier, zoals een signaalnaam, kan gebruikt worden om slechts één type item in een gegeven scope te declareren. Dit betekent dat twee variabelen van verschillende of dezelfde datatypes niet dezelfde naam mogen hebben, of een task en een variabele met dezelfde naam, of zelfs een net en gate-instantie met dezelfde naam in dezelfde scope.
Elke identifier in Verilog heeft een unieke hiërarchische padnaam, waarbij elke module-instantie, task, functie of benoemd begin end of fork join blok een nieuw niveau of scope definieert.
Hiërarchische Referentie Voorbeeld
module tb;
// Maak twee instanties van verschillende modules
A uA();
B uB();
// Maak een benoemd blok dat een signaal declareert en
// de waarde print op 10ns vanaf simulatiestart
initial begin : TB_INITIAL
reg signal;
#10 $display("signal=%0d", signal);
end
// We proberen andere scopes te benaderen met hiërarchische
// referenties vanuit dit initial-blok
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
Simulatie-log
xcelium> run Hello, this is A TB signal=0 signal_1=1 signal_2=0 xmsim: *W,RNQUIE: Simulation is complete.
Opwaartse Naamreferentie
Een lager niveau module kan items refereren in een module erboven in de hiërarchie. Bijvoorbeeld, signal in TB_INITIAL-blok zou zichtbaar zijn vanuit de display-task in A.
module A;
task display();
$display("Hello, this is A");
// Opwaartse referentie, TB_INITIAL is zichtbaar in deze module
#5 TB_INITIAL.signal = 1;
endtask
endmodule
Let op dat TB signal nu 1 is in plaats van 0, door de opwaartse referentie-wijziging die module A aan het signaal maakte.
Simulatie-log
xcelium> run Hello, this is A TB signal=1 signal_1=1 signal_2=0 xmsim: *W,RNQUIE: Simulation is complete.
Hier is nog een voorbeeld met meerdere geneste modules en de bladknoot kan direct leden van bovenliggende knopen benaderen via opwaartse hiërarchische referentie.
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(); // of A.display()
b.display(); // of B.display()
c.display(); // of C.display()
a.b.c.display();
end
endmodule
Simulatie-log
xcelium> run Hello, this is A Hello, this is B Hello, this is C Hello, this is C xmsim: *W,RNQUIE: Simulation is complete.
Wanneer de compiler b.display() vindt:
- Het kijkt in de huidige scope binnen module D of
bgedefinieerd is. Als niet, kijkt het naar de naam in de omringende scope en gaat omhoog tot het modulescope bereikt is. Als de naam nog steeds niet gevonden is, gaat het naar de volgende stap. - Het kijkt in de parent-module's buitenste scope en als het niet gevonden wordt, gaat het verder op in de hiërarchie.
Verilog
- Verilog beheersen: Complete tutorial voor digitale schakelingontwerp
- Verilog concatenatie beheersen: Een praktische gids
- Verilog Essentials: Een beknopt overzicht
- Verilog-toewijzingen begrijpen: types, syntax en best practices
- Verilog Blocking vs. Non-Blocking: belangrijkste verschillen uitgelegd
- Verilog-functies beheersen voor efficiënt RTL-ontwerp
- Verilog Tasks begrijpen: Functions vs Tasks, Syntax en Gebruik
- Verilog Hiërarchische Referentie Scope: Naamconflicten in Modules en Blokken vermijden
- Verilog Clock Generator: Ontwerp & Implementatie Gids
- Verilog Display Tasks beheersen: Efficiënt Debuggen & Loggen
- Verilog Math Functions beheersen voor efficiënt Hardware-ontwerp