Verilog Blocking vs. Non-Blocking: belangrijkste verschillen uitgelegd
Blocking-toewijzing
Blocking-toewijzingsinstructies gebruiken = en worden sequentieel uitgevoerd in een proceduraal blok. Dit voorkomt niet dat statements in een parallel blok worden uitgevoerd.
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
Er zijn twee initial-blokken die parallel uitgevoerd worden wanneer de simulatie start. Statements worden sequentieel uitgevoerd in elk blok en beide blokken zijn klaar op tijd 0ns. Preciezer: variabele a krijgt eerst een waarde, gevolgd door de display-instructie, en dan alle overige statements. Dit is zichtbaar in de output waar variabele b en c 8'hxx zijn in de eerste display-instructie. Dit is omdat de toewijzingen aan b en c nog niet uitgevoerd waren toen de eerste $display werd aangeroepen.
Simulatie-log
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.
In het volgende voorbeeld voegen we een paar vertragingen toe aan dezelfde set statements om te zien hoe het zich gedraagt.
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
Simulatie-log
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.
Non-blocking toewijzing
Non-blocking-toewijzing stelt toewijzingen in zonder de uitvoering van volgende statements te blokkeren en wordt aangeduid met het symbool <=. Het is interessant om te merken dat hetzelfde symbool gebruikt wordt als relationele operator in expressies, en als toewijzingsoperator in de context van een non-blocking toewijzing. Als we het eerste voorbeeld nemen en alle =-symbolen vervangen door de non-blocking toewijzingsoperator <=, zien we een verschil in de output.
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
Zie dat alle $display-instructies 'h'x printen. De reden voor dit gedrag ligt in de manier waarop non-blocking toewijzingen worden uitgevoerd. De RHS van elke non-blocking-instructie van een bepaalde tijdstap wordt vastgelegd, en de simulator gaat door naar het volgende statement. De vastgelegde RHS-waarde wordt pas aan de LHS-variabele toegewezen aan het einde van de tijdstap.
Simulatie-log
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.
Als we de uitvoeringsstroom van het bovenstaande voorbeeld opsplitsen, krijgen we zoiets als hieronder.
|__ Spawn Blok1: initial | |___ Tijd #0ns : a <= 8'DA, is non-blocking dus noteer waarde van RHS (8'hDA) en voer volgende stap uit | |___ Tijd #0ns : $display() is blocking, dus voer deze statement uit: Maar a heeft nog geen nieuwe waarden dus a=8'hx | |___ Tijd #0ns : b <= 8'F1, is non-blocking dus noteer waarde van RHS (8'hF1) en voer volgende stap uit | |___ Tijd #0ns : $display() is blocking, dus voer deze statement uit. Maar b heeft nog geen nieuwe waarden dus b=8'hx | |___ Tijd #0ns : c <= 8'30, is non-blocking dus noteer waarde van RHS (8'h30) en voer volgende stap uit | |___ Tijd #0ns : $display() is blocking, dus voer deze statement uit. Maar c heeft nog geen nieuwe waarden dus c=8'hx | |___ Einde van tijdstap en initial-blok, wijs vastgelegde waarden toe aan variabelen a, b, c | |__ Spawn Blok2: initial | |___ Tijd #0ns : d <= 8'AA, is non-blocking dus noteer waarde van RHS (8'hAA) en voer volgende stap uit | |___ Tijd #0ns : $display() is blocking, dus voer deze statement uit: Maar d heeft nog geen nieuwe waarden dus d=8'hx | |___ Tijd #0ns : e <= 8'55, is non-blocking dus noteer waarde van RHS (8'h55) en voer volgende stap uit | |___ Tijd #0ns : $display() is blocking, dus voer deze statement uit. Maar e heeft nog geen nieuwe waarden dus e=8'hx | |___ Einde van tijdstap en initial-blok, wijs vastgelegde waarden toe aan variabelen d en e | |__ Einde van simulatie op #0ns
Nu laten we het tweede voorbeeld gebruiken en alle blocking-statements vervangen door non-blocking.
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
Opnieuw zien we dat de output anders is dan eerder.
Simulatie-log
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.
Als we de uitvoeringsstroom opsplitsen, krijgen we zoiets als hieronder.
|__ Spawn Blok1 op #0ns: initial | |___ Tijd #0ns : a <= 8'DA, is non-blocking dus noteer waarde van RHS (8'hDA) en voer volgende stap uit | |___ Tijd #0ns : $display() is blocking, dus voer deze statement uit: Maar a heeft nog geen nieuwe waarden dus a=8'hx | |___ Einde van tijdstap : Wijs vastgelegde waarde toe aan variabele a, en a is nu 8'hDA | |___ Wacht tot tijd vooruitgaat met 10 tijdseenheden naar #10ns | | |___ Tijd #10ns : b <= 8'F1, is non-blocking dus noteer waarde van RHS (8'hF1) en voer volgende stap uit | |___ Tijd #10ns : $display() is blocking, dus voer deze statement uit. Maar b heeft nog geen nieuwe waarden dus b=8'hx | |___ Tijd #10ns : c <= 8'30, is non-blocking dus noteer waarde van RHS (8'h30) en voer volgende stap uit | |___ Tijd #10ns : $display() is blocking, dus voer deze statement uit. Maar c heeft nog geen nieuwe waarden dus c=8'hx | |___ Einde van tijdstap en initial-blok, wijs vastgelegde waarden toe aan variabelen b, c | |__ Spawn Blok2 op #0ns: initial | |___ Wacht tot tijd vooruitgaat met 5 tijdseenheden naar #5ns | | |___ Tijd #5ns : d <= 8'AA, is non-blocking dus noteer waarde van RHS (8'hAA) en voer volgende stap uit | |___ Tijd #5ns : $display() is blocking, dus voer deze statement uit: Maar d heeft nog geen nieuwe waarden dus d=8'hx | |___ Einde van tijdstap : Wijs vastgelegde waarde toe aan variabele d, en d is nu 8'hAA | |___ Wacht tot tijd vooruitgaat met 5 tijdseenheden naar #5ns | | |___ Tijd #10ns : e <= 8'55, is non-blocking dus noteer waarde van RHS (8'h55) en voer volgende stap uit | |___ Tijd #10ns : $display() is blocking, dus voer deze statement uit. Maar e heeft nog geen nieuwe waarden dus e=8'hx | |___ Einde van tijdstap en initial-blok, wijs vastgelegde waarden toe aan variabele e, en e is nu 8'h55 | |__ Einde van simulatie op #10ns
Verilog
- Verilog beheersen: Complete tutorial voor digitale schakelingontwerp
- Verilog concatenatie beheersen: Een praktische gids
- Verilog-toewijzingen begrijpen: types, syntax en best practices
- Verilog-functies beheersen voor efficiënt RTL-ontwerp
- Verilog Tasks begrijpen: Functions vs Tasks, Syntax en Gebruik
- Verilog Clock Generator: Ontwerp & Implementatie Gids
- Verilog Math Functions beheersen voor efficiënt Hardware-ontwerp
- Verilog $timeformat beheersen: Precisie en Weergave-controle
- Verilog Timescales begrijpen en printen in elke Scope
- Verilog File I/O onder de knie: Openen, Lezen, Schrijven en Sluiten
- Beginner's Guide to Verilog: Hello World Voorbeeld