Memahami Kontrol Penundaan Verilog: Teknik Waktu dan Praktik Terbaik
Terdapat dua jenis kontrol waktu dalam Verilog - delay dan event expressions. Kontrol delay hanyalah cara untuk menambahkan penundaan antara waktu simulator menemukan pernyataan dan saat sebenarnya mengeksekusinya. Event expression memungkinkan pernyataan ditunda hingga terjadinya beberapa peristiwa simulasi yang dapat berupa perubahan nilai pada jaringan atau variabel (implicit event) atau peristiwa yang dinamai secara eksplisit yang dipicu dalam prosedur lain.
Waktu simulasi dapat ditambah dengan salah satu metode berikut.
Gerbang dan jaringan yang dimodelkan untuk memiliki penundaan internal juga memajukan waktu simulasi.
Kontrol Penundaan
Jika ekspresi penundaan mengevaluasi ke nilai yang tidak diketahui atau impedansi tinggi, maka akan ditafsirkan sebagai penundaan nol. Jika mengevaluasi ke nilai negatif, maka akan ditafsirkan sebagai integer 2's complement unsigned dengan ukuran yang sama seperti variabel waktu.
`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
Perhatikan bahwa presisi timescale adalah 1ps dan oleh karena itu $realtime diperlukan untuk menampilkan nilai presisi untuk pernyataan dengan ekspresi penundaan (a+b)*10ps.
Log Simulasi
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.
Kontrol Peristiwa
Perubahan nilai pada jaringan dan variabel dapat digunakan sebagai peristiwa sinkronisasi untuk memicu eksekusi pernyataan prosedural lain dan merupakan peristiwa implisit. Peristiwa dapat juga berdasarkan arah perubahan seperti menuju 0 yang menjadikannya negedge dan perubahan menuju 1 menjadikannya posedge.
- Sebuah
negedge adalah ketika ada transisi dari 1 ke X, Z atau 0 dan dari X atau Z ke 0 - Sebuah
posedge adalah ketika ada transisi dari 0 ke X, Z atau 1 dan dari X atau Z ke 1
Transisi dari kondisi yang sama ke kondisi yang sama tidak dianggap sebagai tepi. Peristiwa tepi seperti posedge atau negedge hanya dapat terdeteksi pada LSB dari sinyal vektor atau variabel. Jika ekspresi mengevaluasi ke hasil yang sama, tidak dapat dianggap sebagai peristiwa.
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
Log Simulasi
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.
Peristiwa yang Dikenai
Kata kunci event dapat digunakan untuk mendeklarasikan peristiwa yang dinamai yang dapat dipicu secara eksplisit. Sebuah event tidak dapat menyimpan data apa pun, tidak memiliki durasi waktu dan dapat dibuat terjadi pada waktu tertentu. Peristiwa yang dinamai dipicu oleh operator -> dengan menambahkannya sebelum handle peristiwa yang dinamai. Peristiwa yang dinamai dapat ditunggu dengan menggunakan operator @ yang dijelaskan di atas.
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
Peristiwa yang dinamai dapat digunakan untuk menyinkronkan dua atau lebih proses yang berjalan secara bersamaan. Misalnya, blok always dan blok initial kedua disinkronkan oleh a_event. Peristiwa dapat dideklarasikan sebagai array seperti dalam kasus b_event yang merupakan array berukuran 5 dan indeks 3 digunakan untuk tujuan pemicu dan tunggu.
Log Simulasi
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.
Operator Event or
Operator or dapat digunakan untuk menunggu hingga salah satu dari peristiwa yang terdaftar dipicu dalam ekspresi. Koma , juga dapat digunakan sebagai gantinya.
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
Log Simulasi
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.
Daftar Ekspresi Peristiwa Implisit
Daftar sensitivitas atau daftar ekspresi peristiwa seringkali adalah penyebab umum banyak kesalahan fungsional dalam RTL. Ini karena pengguna mungkin lupa memperbarui daftar sensitivitas setelah memperkenalkan sinyal baru dalam blok prosedural.
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
Log Simulasi
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.
Jika pengguna memutuskan untuk menambahkan sinyal baru e dan menangkap inversnya ke z, perhatian khusus harus diambil untuk menambahkan e juga ke dalam daftar sensitivitas.
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
Log Simulasi
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 sekarang memungkinkan daftar sensitivitas diganti dengan * yang merupakan singkatan nyaman yang menghilangkan masalah ini dengan menambahkan semua jaringan dan variabel yang dibaca oleh pernyataan seperti yang ditunjukkan di bawah ini.
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
Log Simulasi
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.
Kontrol Peristiwa Tingkat Sensitive
Eksekusi pernyataan prosedural juga dapat ditunda hingga kondisi menjadi true dan dapat dicapai dengan kata kunci wait dan merupakan kontrol tingkat sensitif.
Pernyataan wait akan mengevaluasi kondisi dan jika false, pernyataan prosedural yang mengikutinya akan tetap diblokir hingga kondisi menjadi true.
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
Log Simulasi
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