Contrôle des délais Verilog
Il existe deux types de contrôles de synchronisation dans Verilog - retard et événement expressions. Le retard control est juste un moyen d'ajouter un délai entre le moment où le simulateur rencontre l'instruction et le moment où il l'exécute réellement. L'expression d'événement permet de retarder l'instruction jusqu'à l'occurrence d'un événement de simulation qui peut être un changement de valeur sur un réseau ou une variable (événement implicite ) ou un événement explicitement nommé qui est déclenché dans une autre procédure.
Le temps de simulation peut être avancé par l'une des méthodes suivantes.
Les portes et les réseaux qui ont été modélisés pour avoir des retards internes font également avancer le temps de simulation.
Contrôle du délai
Si l'expression de retard est évaluée à une valeur inconnue ou à haute impédance, elle sera interprétée comme un retard nul. S'il est évalué à une valeur négative, il sera interprété comme un entier non signé en complément à 2 de la même taille qu'une variable de temps.
`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
Notez que la précision de l'échelle de temps est en 1ps et donc $realtime
est nécessaire pour afficher la valeur de précision de l'instruction avec une expression de délai (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.
Contrôle des événements
Les changements de valeur sur les réseaux et les variables peuvent être utilisés comme un événement de synchronisation pour déclencher l'exécution d'autres instructions procédurales et sont implicites un événement. L'événement peut également être basé sur la direction du changement comme vers 0 ce qui en fait un negedge
et un changement vers 1 en fait un posedge
.
- Un
negedge
c'est quand il y a une transition de 1 à X, Z ou 0 et de X ou Z à 0 - Un
posedge
c'est quand il y a une transition de 0 à X, Z ou 1 et de X ou Z à 1
Une transition du même état au même état n'est pas considérée comme un front. Un événement de front comme posedge ou negedge ne peut être détecté que sur le LSB d'un signal vectoriel ou d'une variable. Si une expression donne le même résultat, elle ne peut pas être considérée comme un événement.
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
Journal de simulation 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.
Événements nommés
Le mot-clé event
peut être utilisé pour déclarer un named événement qui peut être déclenché explicitement. Un event
ne peut contenir aucune donnée, n'a pas de durée et peut se produire à tout moment. Un événement nommé est déclenché par le ->
opérateur en le préfixant avant le handle d'événement nommé. Un événement nommé peut être attendu en utilisant le @
opérateur décrit ci-dessus.
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
Les événements nommés peuvent être utilisés pour synchroniser deux ou plusieurs processus exécutés simultanément. Par exemple, le always
bloc et le second initial
bloc sont synchronisés par a_event. Les événements peuvent être déclarés sous forme de tableaux comme dans le cas de b_event qui est un tableau de taille 5 et l'index 3 est utilisé à des fins de déclenchement et d'attente.
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.
Événement ou opérateur
Le or
L'opérateur peut être utilisé pour attendre jusqu'à ce que l'un des événements répertoriés soit déclenché dans une expression. La virgule ,
peut également être utilisé à la place du or
opérateur.
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
Journal de simulation 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.
Liste d'expressions d'événements implicites
La liste de sensibilité ou la liste d'expressions d'événements est souvent une cause fréquente d'un grand nombre d'erreurs fonctionnelles dans la RTL. En effet, l'utilisateur peut oublier de mettre à jour la liste de sensibilité après avoir introduit un nouveau signal dans le bloc procédural.
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
Journal de simulation 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.
Si l'utilisateur décide d'ajouter un nouveau signal e et de capturer l'inverse dans z, une attention particulière doit être portée pour ajouter e également dans la liste de sensibilité.
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
Journal de simulation 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 permet désormais de remplacer la liste de sensibilité par *
qui est un raccourci pratique qui élimine ces problèmes en ajoutant tous les réseaux et variables qui sont lus par l'instruction comme indiqué ci-dessous.
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
Journal de simulation 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.
Contrôle des événements sensibles au niveau
L'exécution d'une instruction procédurale peut également être retardée jusqu'à ce qu'une condition devienne vraie et peut être accomplie avec le wait
mot-clé et est un contrôle sensible au niveau.
L'instruction d'attente évaluera une condition et si elle est fausse, les instructions procédurales qui la suivent resteront bloquées jusqu'à ce que la condition devienne vraie.
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
Journal de simulation 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