Verilog blokkeren en niet-blokkeren
Blokkeren
Blokkeren toewijzingsinstructies worden toegewezen met behulp van =
en worden na elkaar uitgevoerd in een procedureel blok. Dit verhindert echter niet de uitvoering van opgaven die in een parallel blok lopen.
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
Merk op dat er twee initial
. zijn blokken die parallel worden uitgevoerd wanneer de simulatie start. Statements worden achtereenvolgens uitgevoerd in elk blok en beide blokken eindigen op tijdstip 0ns. Om specifieker te zijn, variabele a wordt eerst toegewezen, gevolgd door de display-instructie die vervolgens wordt gevolgd door alle andere instructies. Dit is zichtbaar in de uitvoer waar variabele b en c zijn 8'hxx in de eerste weergave-instructie. Dit komt omdat variabele b en c opdrachten zijn nog niet uitgevoerd wanneer de eerste $display
wordt gebeld.
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 instructies om te zien hoe deze 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
Simulatielogboek 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.
Niet-blokkerend
Niet-blokkerend toewijzing maakt het mogelijk toewijzingen te plannen zonder de uitvoering van de volgende instructies te blokkeren en wordt gespecificeerd door een <=
symbool. Het is interessant om op te merken dat hetzelfde symbool wordt gebruikt als een relationele operator in uitdrukkingen en als een toewijzingsoperator in de context van een niet-blokkerende toewijzing. Als we het eerste voorbeeld van hierboven nemen, vervang dan alle =
symobls met een niet-blokkerende toewijzingsoperator <=
, we zullen enig verschil in de uitvoer zien.
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
Zorg ervoor dat alle $display
verklaringen afgedrukt 'h'x
. De reden voor dit gedrag ligt in de manier waarop niet-blokkerende opdrachten worden uitgevoerd. De RHS van elke niet-blokkerende verklaring van een bepaalde tijdstap wordt vastgelegd en gaat naar de volgende verklaring. De vastgelegde RHS-waarde wordt pas aan het einde van de tijdstap aan de LHS-variabele toegewezen.
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.
Dus als we de uitvoeringsstroom van het bovenstaande voorbeeld opsplitsen, krijgen we zoiets als wat hieronder wordt weergegeven.
|__ Spawn Block1: initial | |___ Time #0ns : a <= 8'DA, is non-blocking so note value of RHS (8'hDA) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement: But a hasn't received new values so a=8'hx | |___ Time #0ns : b <= 8'F1, is non-blocking so note value of RHS (8'hF1) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement. But b hasn't received new values so b=8'hx | |___ Time #0ns : c <= 8'30, is non-blocking so note value of RHS (8'h30) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement. But c hasn't received new values so c=8'hx | |___ End of time-step and initial block, assign captured values into variables a, b, c | |__ Spawn Block2: initial | |___ Time #0ns : d <= 8'AA, is non-blocking so note value of RHS (8'hAA) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement: But d hasn't received new values so d=8'hx | |___ Time #0ns : e <= 8'55, is non-blocking so note value of RHS (8'h55) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement. But e hasn't received new values so e=8'hx | |___ End of time-step and initial block, assign captured values into variables d and e | |__ End of simulation at #0ns
Laten we vervolgens het tweede voorbeeld gebruiken en alle blokkerende instructies vervangen door niet-blokkerende.
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
Wederom kunnen we zien dat de output anders is dan wat we eerder kregen.
Simulatielogboekncsim> 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 wordt weergegeven.
|__ Spawn Block1 at #0ns: initial | |___ Time #0ns : a <= 8'DA, is non-blocking so note value of RHS (8'hDA) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement: But a hasn't received new values so a=8'hx | |___ End of time-step : Assign captured value to variable a, and a is now 8'hDA | |___ Wait until time advances by 10 time-units to #10ns | | |___ Time #10ns : b <= 8'F1, is non-blocking so note value of RHS (8'hF1) and execute next step | |___ Time #10ns : $display() is blocking, so execute this statement. But b hasn't received new values so b=8'hx | |___ Time #10ns : c <= 8'30, is non-blocking so note value of RHS (8'h30) and execute next step | |___ Time #10ns : $display() is blocking, so execute this statement. But c hasn't received new values so c=8'hx | |___ End of time-step and initial block, assign captured values into variables b, c | |__ Spawn Block2 at #0ns: initial | |___ Wait until time advances by 5 time-units to #5ns | | |___ Time #5ns : d <= 8'AA, is non-blocking so note value of RHS (8'hAA) and execute next step | |___ Time #5ns : $display() is blocking, so execute this statement: But d hasn't received new values so d=8'hx | |___ End of time-step : Assign captured value to variable d, and d is now 8'hAA | |___ Wait until time advances by 5 time-units to #5ns | | |___ Time #10ns : e <= 8'55, is non-blocking so note value of RHS (8'h55) and execute next step | |___ Time #10ns : $display() is blocking, so execute this statement. But e hasn't received new values so e=8'hx | |___ End of time-step and initial block, assign captured values to variable e, and e is now 8'h55 | |__ End of simulation at #10ns
Verilog