Verilog-vertragingsregeling
Er zijn twee soorten timingcontroles in Verilog - vertraging en evenement uitdrukkingen. De vertraging controle is slechts een manier om een vertraging toe te voegen tussen het moment waarop de simulator de instructie tegenkomt en wanneer deze deze daadwerkelijk uitvoert. De gebeurtenisuitdrukking staat toe dat de verklaring wordt uitgesteld tot het optreden van een simulatiegebeurtenis die een waardeverandering op een net of variabele kan zijn (impliciete gebeurtenis ) of een expliciet genoemde gebeurtenis die in een andere procedure wordt geactiveerd.
De simulatietijd kan op een van de volgende manieren worden vervroegd.
Poorten en netten waarvan is gemodelleerd dat ze interne vertragingen hebben, verlengen ook de simulatietijd.
Vertragingsregeling
Als de vertragingsexpressie resulteert in een onbekende of hoge impedantiewaarde, wordt deze geïnterpreteerd als nulvertraging. Als het een negatieve waarde oplevert, wordt het geïnterpreteerd als een geheel getal zonder teken van een 2-complement van dezelfde grootte als een tijdvariabele.
`timescale 1ns/1ps
module tb;
reg [3:0] a, b;
initial begin
{a, b} <= 0;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#10;
a <= $random;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#10 b <= $random;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#(a) $display ("T=%0t After a delay of a=%0d units", $realtime, a);
#(a+b) $display ("T=%0t After a delay of a=%0d + b=%0d = %0d units", $realtime, a, b, a+b);
#((a+b)*10ps) $display ("T=%0t After a delay of %0d * 10ps", $realtime, a+b);
#(b-a) $display ("T=%0t Expr evaluates to a negative delay", $realtime);
#('h10) $display ("T=%0t Delay in hex", $realtime);
a = 'hX;
#(a) $display ("T=%0t Delay is unknown, taken as zero a=%h", $realtime, a);
a = 'hZ;
#(a) $display ("T=%0t Delay is in high impedance, taken as zero a=%h", $realtime, a);
#1ps $display ("T=%0t Delay of 10ps", $realtime);
end
endmodule
Merk op dat de precisie van de tijdschaal in 1ps is en dus $realtime
is vereist om de precisiewaarde voor de instructie weer te geven met een vertragingsexpressie (a+b)*10ps.
xcelium> run T=0 a=x b=x T=10000 a=0 b=0 T=20000 a=4 b=0 T=24000 After a delay of a=4 units T=29000 After a delay of a=4 + b=1 = 5 units T=29050 After a delay of 5 * 10ps T=42050 Expr evaluates to a negative delay T=58050 Delay in hex T=58050 Delay is unknown, taken as zero a=x T=58050 Delay is in high impedance, taken as zero a=z T=58051 Delay of 10ps xmsim: *W,RNQUIE: Simulation is complete.
Gebeurtenisbeheer
Waardeveranderingen op netten en variabelen kunnen worden gebruikt als een synchronisatiegebeurtenis om de uitvoering van andere procedurele instructies te activeren en is een impliciete evenement. De gebeurtenis kan ook gebaseerd zijn op de richting van de verandering, zoals naar 0, waardoor het een negedge
. wordt en een verandering naar 1 maakt het een posedge
.
- Een
negedge
is wanneer er een overgang is van 1 naar X, Z of 0 en van X of Z naar 0 - Een
posedge
is wanneer er een overgang is van 0 naar X, Z of 1 en van X of Z naar 1
Een overgang van dezelfde toestand naar dezelfde toestand wordt niet als een rand beschouwd. Een randgebeurtenis zoals posedge of negedge kan alleen worden gedetecteerd op de LSB van een vectorsignaal of variabele. Als een uitdrukking hetzelfde resultaat oplevert, kan deze niet als een gebeurtenis worden beschouwd.
module tb;
reg a, b;
initial begin
a <= 0;
#10 a <= 1;
#10 b <= 1;
#10 a <= 0;
#15 a <= 1;
end
// Start another procedural block that waits for an update to
// signals made in the above procedural block
initial begin
@(posedge a);
$display ("T=%0t Posedge of a detected for 0->1", $time);
@(posedge b);
$display ("T=%0t Posedge of b detected for X->1", $time);
end
initial begin
@(posedge (a + b)) $display ("T=%0t Posedge of a+b", $time);
@(a) $display ("T=%0t Change in a found", $time);
end
endmodule
Simulatielogboek ncsim> run T=10 Posedge of a detected for 0->1 T=20 Posedge of b detected for X->1 T=30 Posedge of a+b T=45 Change in a found ncsim: *W,RNQUIE: Simulation is complete.
Genoemde evenementen
Het trefwoord event
kan worden gebruikt om een named . te declareren gebeurtenis die expliciet kan worden geactiveerd. Een event
kan geen gegevens bevatten, heeft geen tijdsduur en kan op een bepaald moment plaatsvinden. Een benoemde gebeurtenis wordt geactiveerd door de ->
operator door het voor de benoemde gebeurtenishandle te plaatsen. Op een benoemde gebeurtenis kan worden gewacht met behulp van de @
hierboven beschreven operator.
module tb;
event a_event;
event b_event[5];
initial begin
#20 -> a_event;
#30;
->a_event;
#50 ->a_event;
#10 ->b_event[3];
end
always @ (a_event) $display ("T=%0t [always] a_event is triggered", $time);
initial begin
#25;
@(a_event) $display ("T=%0t [initial] a_event is triggered", $time);
#10 @(b_event[3]) $display ("T=%0t [initial] b_event is triggered", $time);
end
endmodule
Benoemde gebeurtenissen kunnen worden gebruikt om twee of meer gelijktijdig lopende processen te synchroniseren. Bijvoorbeeld de always
blok en de tweede initial
blok worden gesynchroniseerd door a_event. Gebeurtenissen kunnen worden gedeclareerd als arrays, zoals in het geval van b_event, een array van grootte 5 en de index 3 wordt gebruikt voor trigger- en wachtdoeleinden.
ncsim> run T=20 [always] a_event is triggered T=50 [always] a_event is triggered T=50 [initial] a_event is triggered T=100 [always] a_event is triggered T=110 [initial] b_event is triggered ncsim: *W,RNQUIE: Simulation is complete.
Evenement of operator
De or
operator kan worden gebruikt om te wachten totdat een van de vermelde gebeurtenissen in een expressie wordt geactiveerd. De komma ,
kan ook worden gebruikt in plaats van de or
telefoniste.
module tb;
reg a, b;
initial begin
$monitor ("T=%0t a=%0d b=%0d", $time, a, b);
{a, b} <= 0;
#10 a <= 1;
#5 b <= 1;
#5 b <= 0;
end
// Use "or" between events
always @ (posedge a or posedge b)
$display ("T=%0t posedge of a or b found", $time);
// Use a comma between
always @ (posedge a, negedge b)
$display ("T=%0t posedge of a or negedge of b found", $time);
always @ (a, b)
$display ("T=%0t Any change on a or b", $time);
endmodule
Simulatielogboek ncsim> run T=0 posedge of a or negedge of b found T=0 Any change on a or b T=0 a=0 b=0 T=10 posedge of a or b found T=10 posedge of a or negedge of b found T=10 Any change on a or b T=10 a=1 b=0 T=15 posedge of a or b found T=15 Any change on a or b T=15 a=1 b=1 T=20 posedge of a or negedge of b found T=20 Any change on a or b T=20 a=1 b=0 ncsim: *W,RNQUIE: Simulation is complete.
Lijst met impliciete gebeurtenisuitdrukkingen
De gevoeligheidslijst of de gebeurtenisexpressielijst is vaak een veelvoorkomende oorzaak van veel functionele fouten in de RTL. Dit komt omdat de gebruiker kan vergeten de gevoeligheidslijst bij te werken nadat hij een nieuw signaal in het procedureblok heeft ingevoerd.
module tb;
reg a, b, c, d;
reg x, y;
// Event expr/sensitivity list is formed by all the
// signals inside () after @ operator and in this case
// it is a, b, c or d
always @ (a, b, c, d) begin
x = a | b;
y = c ^ d;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b x=%0b y=%0b", $time, a, b, c, d, x, y);
{a, b, c, d} <= 0;
#10 {a, b, c, d} <= $random;
#10 {a, b, c, d} <= $random;
#10 {a, b, c, d} <= $random;
end
endmodule
Simulatielogboek ncsim> run T=0 a=0 b=0 c=0 d=0 x=0 y=0 T=10 a=0 b=1 c=0 d=0 x=1 y=0 T=20 a=0 b=0 c=0 d=1 x=0 y=1 T=30 a=1 b=0 c=0 d=1 x=1 y=1 ncsim: *W,RNQUIE: Simulation is complete.
Als de gebruiker besluit een nieuw signaal e toe te voegen en de inverse in z vast te leggen, moet er extra op worden gelet dat e ook aan de gevoeligheidslijst wordt toegevoegd.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Add "e" also into sensitivity list
always @ (a, b, c, d, e) begin
x = a | b;
y = c ^ d;
z = ~e;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b",
$time, a, b, c, d, e, x, y, z);
{a, b, c, d, e} <= 0;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
end
endmodule
Simulatielogboek ncsim> run T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1 T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1 T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0 T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0 ncsim: *W,RNQUIE: Simulation is complete.
Verilog staat nu toe dat de gevoeligheidslijst wordt vervangen door *
wat een handige afkorting is die deze problemen elimineert door alle netten en variabelen toe te voegen die worden gelezen door de verklaring zoals hieronder weergegeven.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Use @* or @(*)
always @ * begin
x = a | b;
y = c ^ d;
z = ~e;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b",
$time, a, b, c, d, e, x, y, z);
{a, b, c, d, e} <= 0;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
end
endmodule
Simulatielogboek ncsim> run T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1 T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1 T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0 T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0 ncsim: *W,RNQUIE: Simulation is complete.
Niveaugevoelige gebeurteniscontrole
De uitvoering van een procedurele verklaring kan ook worden uitgesteld totdat een voorwaarde waar wordt en kan worden bereikt met de wait
zoekwoord en is een niveaugevoelig besturingselement.
De wait-instructie evalueert een voorwaarde en als deze onwaar is, blijven de procedurele instructies die erop volgen geblokkeerd totdat de voorwaarde waar wordt.
module tb;
reg [3:0] ctr;
reg clk;
initial begin
{ctr, clk} <= 0;
wait (ctr);
$display ("T=%0t Counter reached non-zero value 0x%0h", $time, ctr);
wait (ctr == 4) $display ("T=%0t Counter reached 0x%0h", $time, ctr);
$finish;
end
always #10 clk = ~clk;
always @ (posedge clk)
ctr <= ctr + 1;
endmodule
Simulatielogboek ncsim> run T=10 Counter reached non-zero value 0x1 T=70 Counter reached 0x4 T=90 Counter reached 0x5 T=170 Counter reached 0x9 Simulation complete via $finish(1) at time 170 NS + 1
Verilog