Arti "Waktu" di Verilog
Verilog tidak punya konsep detik bawaan. Simulator memajukan "satuan waktu", yaitu tick integer yang nilainya bebas, dan kodemu memakai #N untuk menunggu N tick. Direktif `timescale-lah yang memetakan tick itu ke waktu nyata.
`timescale 1ns / 1ps
module test;
initial begin
$display("t = %0t", $time); // 0
#5;
$display("t = %0t", $time); // 5 ns
#1.5;
$display("t = %0t", $time); // 6500 ps (or 6.5 ns)
$finish;
end
endmodule
Dua parameternya:
- Satuan (angka pertama): arti
#1.1nsberarti satu tick adalah satu nanodetik. - Presisi (angka kedua): seberapa halus simulasi melacak waktu di dalam satuan itu.
1psberarti delay pecahan dibulatkan ke pikodetik.
Presisinya tidak boleh lebih kasar daripada satuannya (1ps / 1ns tidak sah). Pilihan yang umum:
1ns / 1ps: standar de facto. Semuanya dalam nanodetik, dengan presisi di bawah satu nanodetik untuk delay gerbang apa pun.1ps / 1ps: saat memodelkan rangkaian yang sangat cepat, atau saat setiap delay di bawah satu nanodetik.1us / 1ns: untuk simulasi lambat berskala embedded (waktu satu byte UART, protokol lambat).
Di Mana Menaruhnya
`timescale adalah direktif compiler, bukan konstruksi di tingkat module. Ia ditaruh di paling atas file, sebelum module apa pun:
`timescale 1ns / 1ps
module foo(...);
// ...
endmodule
Cakupannya adalah "mulai titik ini dan seterusnya dalam urutan kompilasi, sampai `timescale berikutnya atau akhir kompilasi". Ada implikasi halus di sini: file tanpa `timescale yang eksplisit mewarisi apa pun yang dideklarasikan file yang lebih dulu diproses compiler, dan itu bergantung pada urutan compiler membaca file. Hindari kejutan ini: taruh `timescale di awal setiap file.
Editor browser di dokumentasi ini mengatur timescale default untukmu (biasanya 1ns / 1ps), itulah kenapa contoh-contoh di dokumen sebelumnya berjalan tanpa mendeklarasikannya. Di proyek sungguhan, kamu akan menuliskannya secara eksplisit.
#delay dalam Praktik
Setelah `timescale 1ns / 1ps:
#5 // wait 5 ns
#100 // wait 100 ns
#1.5 // wait 1.5 ns (precision allows it)
#0.001 // wait 1 ps (just barely above precision)
#0 // zero-delay; useful for ordering events at the same time
Di dalam blok initial atau always, #N menahan alur prosedural selama N satuan waktu. Simulator menjeda blok ini (blok lain yang berjalan bersamaan tetap jalan) dan melanjutkannya setelah delay selesai.
Kamu bisa memberi awalan delay pada sebuah penugasan:
#10 a = 1; // wait 10 ns, then assign
data <= #2 new_value; // schedule the non-blocking assignment 2 ns from now
Bentuk pertama adalah andalan testbench. Bentuk kedua (non-blocking dengan delay) dipakai di simulasi gate-level untuk memodelkan delay propagasi.
Membangkitkan Clock
Pola klasiknya:
`timescale 1ns / 1ps
module test;
reg clk = 0;
always #5 clk = ~clk;
// ...
endmodule
Dengan timescale 1ns / 1ps, #5 adalah 5 ns. Clock berbalik setiap 5 ns, sehingga periodenya 10 ns: clock 100 MHz. Untuk mengubah frekuensinya, ubah delay-nya:
| Setengah periode | Periode | Frekuensi |
|---|---|---|
#1 | 2 ns | 500 MHz |
#2.5 | 5 ns | 200 MHz |
#5 | 10 ns | 100 MHz |
#10 | 20 ns | 50 MHz |
#25 | 50 ns | 20 MHz |
#50 | 100 ns | 10 MHz |
Kalau kamu ingin setengah periode berupa pecahan (#2.5), presisimu harus mendukungnya. Presisi 1ps bisa menangani apa pun sampai 0,001 ns, jadi frekuensi wajar apa pun tidak masalah.
Mencampur Timescale di Beberapa File
Desain sungguhan punya banyak file, dan masing-masing bisa mendeklarasikan timescale yang berbeda. Simulator memakai timescale milik masing-masing file untuk membaca delay di file itu. Kalau module_a.v menulis `timescale 1ns / 1ps dan memakai #5, itu 5 ns. Kalau module_b.v menulis `timescale 1us / 1ns dan memakai #5, itu 5 us.
Hal ini sebagian besar tidak terlihat karena simulator tetap menampilkan satu sumbu waktu global, tapi artinya #N yang sama di dua file bisa berarti hal yang sangat berbeda. Solusinya: pilih satu timescale (standar industrinya 1ns / 1ps) dan taruh di awal setiap file. Jangan dicampur.
Delay Tidak Bisa Disintesis
Poin penting: #delay hanya ada untuk simulasi. Tool sintesis membaca:
// In synthesizable RTL - WRONG
always @(posedge clk) begin
out <= #2 in;
end
…dan entah mengabaikan #2 (kebanyakan tool) atau menolak konstruksinya (linter yang lebih ketat). Timing di hardware sungguhan ditentukan oleh clock dan delay propagasi gerbang, yang keduanya tidak terlihat di kode sumber.
Aturannya: pakai # hanya di testbench. RTL yang bisa disintesis tidak punya delay #. Kalau kamu merasa butuh delay di kode yang akan disintesis, yang sebenarnya kamu butuhkan adalah counter yang menghitung mundur mengikuti clock: begitulah hardware sungguhan "menunggu".
$time vs $realtime
Ada dua cara membaca waktu simulasi saat ini:
$timemengembalikan integer 64-bit dalam satuan timescale yang sedang berlaku.$realtimemengembalikanrealdalam satuan timescale yang sedang berlaku, tapi dengan presisi penuh.
Untuk logging di testbench, $time hampir selalu cukup. Pakai $realtime hanya kalau kamu butuh presisi di bawah satu tick di pernyataan cetak.
Tips Praktis
- Selalu deklarasikan
`timescaledi awal setiap file.1ns / 1psadalah default yang aman. - Pakai
#delayhanya di testbench. Jadikan ketiadaannya di kode yang bisa disintesis sebagai aturan tetap. - Sesuaikan periode clock dengan frekuensi targetmu. Kalau kamu menyimulasikan desain 50 MHz, pakai periode clock 20 ns; periode yang tidak cocok bisa menyembunyikan bug yang peka terhadap timing.
- Untuk stimulus berbasis hitungan siklus, pakai
@(posedge clk)alih-alih#. Cara ini tetap andal saat periode clock-nya berubah.
Selanjutnya
Sekarang kamu sudah melihat setiap dokumen di tutorial Verilog ini. Dari dasar-dasar bahasa (wire vs reg, module, operator), melalui blok prosedural dan alur kontrol, masuk ke desain sinkron dan state machine, sampai akhirnya tool testbench yang membuktikan semuanya berfungsi. Saatnya membangun sesuatu: playground di sebelah dokumentasi ini memakai simulator yang sama dengan yang kita pakai sejak awal, siap untuk module apa pun yang kamu rancang.
Pertanyaan yang sering diajukan
Apa arti `timescale 1ns / 1ps di Verilog?
Direktif itu memberi tahu simulator: 'satu satuan waktu di file ini adalah satu nanodetik, dan waktu dilacak dengan presisi pikodetik.' Setelah direktif itu, #5 menunggu 5 ns, #1.5 menunggu 1,5 ns (dibulatkan ke pikodetik), dan $time dilaporkan dalam nanodetik. Angka pertama adalah satuannya; angka kedua adalah presisinya.
Apakah setiap file Verilog butuh `timescale?
Praktik terbaiknya: ya. Cakupan direktif ini berakhir di `timescale berikutnya atau di akhir kompilasi, jadi file tanpa direktif ini mewarisi apa pun yang dideklarasikan file yang lebih dulu diproses compiler. Akibatnya timing tidak deterministik dari satu build ke build lain. Taruh `timescale 1ns / 1ps di awal setiap file sumber (ini konvensi yang paling umum), dan kamu tidak akan pernah terkejut.
Apa arti #5 di Verilog?
#5 memajukan waktu simulasi sebanyak 5 satuan waktu. Satuannya berasal dari direktif `timescale yang sedang aktif. Dengan `timescale 1ns / 1ps, #5 adalah 5 nanodetik. Dengan `timescale 1us / 1ns, #5 adalah 5 mikrodetik. Angkanya boleh pecahan: #1.5 berfungsi kalau presisimu lebih halus daripada satuannya.
Apakah #delay bisa disintesis di Verilog?
Tidak. #delay hanya berpengaruh pada simulasi; tool sintesis mengabaikan atau menolaknya. Timing di hardware sungguhan berasal dari sinyal clock dan delay propagasi gerbang, bukan dari pernyataan #. Pakai # sebebasnya di testbench; jangan pernah menulisnya di RTL yang akan disintesis.