Comprendre le Contrôle de Délai Verilog : Techniques de Timing et Bonnes Pratiques
Il existe deux types de contrôles de timing en Verilog - les expressions de délai et d'événement. Le contrôle de délai est simplement un moyen d'ajouter un délai entre le moment où le simulateur rencontre l'instruction et celui où il l'exécute réellement. L'expression d'événement permet de retarder l'instruction jusqu'à la survenue d'un événement de simulation qui peut être un changement de valeur sur un net 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 nets qui ont été modélisés pour avoir des délais internes font également avancer le temps de simulation.
Contrôle de Délai
Si l'expression de délai s'évalue à une valeur inconnue ou haute impédance, elle sera interprétée comme un délai zéro. Si elle s'évalue à une valeur négative, elle sera interprétée comme un entier non signé en complément à 2 de la même taille qu'une variable time.
`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 du timescale est en 1ps et donc $realtime est requis pour afficher la valeur de précision pour l'instruction avec une expression de délai (a+b)*10ps.
Journal de Simulation
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 d'Événement
Les changements de valeur sur les nets et variables peuvent être utilisés comme événement de synchronisation pour déclencher l'exécution d'autres instructions procédurales et constituent un événement implicite. 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
negedgese produit lors d'une transition de 1 vers X, Z ou 0 et de X ou Z vers 0 - Un
posedgese produit lors d'une transition de 0 vers X, Z ou 1 et de X ou Z vers 1
Une transition du même état vers le 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 ou variable vectoriel. Si une expression s'évalue au 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
// Démarrer un autre bloc procédural qui attend une mise à jour des
// signaux faits dans le bloc procédural ci-dessus
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 événement nommé qui peut être déclenché explicitement. Un event ne peut contenir aucune donnée, n'a pas de durée et peut se produire à n'importe quel moment particulier. Un événement nommé est déclenché par l'opérateur -> en le préfixant avant le handle d'événement nommé. Un événement nommé peut être attendu en utilisant l'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 s'exécutant simultanément. Par exemple, le bloc always et le second bloc initial sont synchronisés par a_event. Les événements peuvent être déclarés comme des tableaux comme dans le cas de b_event qui est un tableau de taille 5 et l'index 3 est utilisé pour le déclenchement et l'attente.
Journal de Simulation
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.
Opérateur or d'Événement
L'opérateur or peut être utilisé pour attendre jusqu'à ce que l'un des événements listés soit déclenché dans une expression. La virgule , peut également être utilisée à la place de l'opérateur or.
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
// Utilise "or" entre événements
always @ (posedge a or posedge b)
$display ("T=%0t posedge of a or b found", $time);
// Utilise une virgule entre
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 courante de nombreuses erreurs fonctionnelles dans le RTL. C'est parce que 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;
// La liste d'expressions d'événements/sensibilité est formée par tous les
// signaux à l'intérieur de () après l'opérateur @ et dans ce cas
// c'est a, b, c ou 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 son inverse dans z, une attention particulière doit être portée pour ajouter e aussi dans la liste de sensibilité.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Ajouter "e" aussi dans la liste de sensibilité
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 maintenant de remplacer la liste de sensibilité par * qui est un raccourci pratique qui élimine ces problèmes en ajoutant tous les nets et variables lus par l'instruction comme montré ci-dessous.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Utilise @* ou @(*)
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 d'Événement Sensible 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 mot-clé wait et est un contrôle sensible au niveau.
L'instruction wait doit évaluer une condition et si elle est fausse, les instructions procédurales la suivant 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
- Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
- Maîtriser la concaténation Verilog : Guide pratique
- Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
- Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
- Maîtriser le Flux de Contrôle Verilog : IF-ELSE, Case, Boucles et Plus
- Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
- Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation
- Comprendre les Délais Inter- et Intra-Affectation en Verilog
- Comprendre les Délais de Portes en Verilog : Timing Précis pour Conceptions Numériques Fiables