Verilog-Verzögerungssteuerung
Es gibt zwei Arten von Zeitsteuerungen in Verilog - Verzögerung und Ereignis Ausdrücke. Die Verzögerung control ist nur eine Möglichkeit, eine Verzögerung zwischen dem Zeitpunkt hinzuzufügen, zu dem der Simulator auf die Anweisung trifft, und wenn er sie tatsächlich ausführt. Der Ereignisausdruck ermöglicht es, die Anweisung bis zum Auftreten eines Simulationsereignisses zu verzögern, das eine Wertänderung in einem Netz oder einer Variablen sein kann (implizites Ereignis ) oder ein explizit benanntes Ereignis, das in einer anderen Prozedur ausgelöst wird.
Die Simulationszeit kann durch eine der folgenden Methoden verlängert werden.
Tore und Netze, die so modelliert wurden, dass sie interne Verzögerungen haben, beschleunigen auch die Simulationszeit.
Verzögerungssteuerung
Wenn der Verzögerungsausdruck einen unbekannten oder hochohmigen Wert ergibt, wird er als Nullverzögerung interpretiert. Wenn sie einen negativen Wert ergibt, wird sie als vorzeichenlose Ganzzahl im Zweierkomplement mit der gleichen Größe wie eine Zeitvariable interpretiert.
`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
Beachten Sie, dass die Genauigkeit der Zeitskala in 1 ps liegt und daher $realtime
ist erforderlich, um den Genauigkeitswert für die Anweisung mit einem Verzögerungsausdruck (a+b)*10ps anzuzeigen.
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.
Ereignissteuerung
Wertänderungen an Netzen und Variablen können als Synchronisationsereignis verwendet werden, um die Ausführung anderer prozeduraler Anweisungen auszulösen, und sind implizit Veranstaltung. Das Ereignis kann auch auf der Änderungsrichtung basieren, z. B. in Richtung 0, was es zu einer negedge
macht und eine Änderung in Richtung 1 macht es zu einem posedge
.
- A
negedge
ist, wenn es einen Übergang von 1 zu X, Z oder 0 und von X oder Z zu 0 gibt - A
posedge
ist, wenn es einen Übergang von 0 zu X, Z oder 1 und von X oder Z zu 1 gibt
Ein Übergang vom gleichen Zustand zum gleichen Zustand wird nicht als Kante betrachtet. Ein Flankenereignis wie Posedge oder Negedge kann nur am LSB eines Vektorsignals oder einer Variablen erkannt werden. Wenn ein Ausdruck dasselbe Ergebnis liefert, kann er nicht als Ereignis betrachtet werden.
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
Simulationsprotokoll 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.
Benannte Ereignisse
Das Schlüsselwort event
kann verwendet werden, um einen named zu deklarieren Ereignis, das explizit ausgelöst werden kann. Ein event
kann keine Daten enthalten, hat keine Zeitdauer und kann zu einem bestimmten Zeitpunkt ausgeführt werden. Ein benanntes Ereignis wird durch ->
ausgelöst -Operator, indem Sie ihn vor das benannte Ereignishandle voranstellen. Auf ein benanntes Ereignis kann mit @
gewartet werden oben beschriebenen 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
Benannte Ereignisse können verwendet werden, um zwei oder mehr gleichzeitig laufende Prozesse zu synchronisieren. Zum Beispiel always
Block und der zweite initial
Block werden von a_event synchronisiert. Ereignisse können als Arrays deklariert werden, wie im Fall von b_event, das ein Array der Größe 5 ist und der Index 3 für Trigger- und Wartezwecke verwendet wird.
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.
Ereignis oder Operator
Die or
-Operator kann verwendet werden, um zu warten, bis eines der aufgelisteten Ereignisse in einem Ausdruck ausgelöst wird. Das Komma ,
kann auch anstelle des or
verwendet werden Betreiber.
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
Simulationsprotokoll 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.
Implizite Ereignisausdrucksliste
Die Sensitivitätsliste oder die Ereignisausdrucksliste ist oft eine häufige Ursache für viele Funktionsfehler in der RTL. Dies liegt daran, dass der Benutzer möglicherweise vergisst, die Empfindlichkeitsliste zu aktualisieren, nachdem er ein neues Signal in den Verfahrensblock eingefügt hat.
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
Simulationsprotokoll 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.
Wenn der Benutzer beschließt, ein neues Signal e hinzuzufügen und das Inverse in z zu erfassen, muss besonders darauf geachtet werden, e auch in die Empfindlichkeitsliste aufzunehmen.
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
Simulationsprotokoll 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 erlaubt jetzt, dass die Vertraulichkeitsliste durch *
ersetzt wird Dies ist eine bequeme Abkürzung, die diese Probleme beseitigt, indem alle Netze und Variablen hinzugefügt werden, die von der Anweisung gelesen werden, wie unten gezeigt.
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
Simulationsprotokoll 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.
Ebenenabhängige Ereignissteuerung
Die Ausführung einer prozeduralen Anweisung kann auch verzögert werden, bis eine Bedingung wahr wird, und kann mit wait
ausgeführt werden Schlüsselwort und ist ein pegelabhängiges Steuerelement.
Die Wait-Anweisung wertet eine Bedingung aus, und wenn sie falsch ist, bleiben die ihr folgenden Prozeduranweisungen blockiert, bis die Bedingung wahr wird.
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
Simulationsprotokoll 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