Menu

Timescale dan Delay di Verilog: Mengatur Waktu Simulasi

Cara direktif `timescale menentukan satuan #delay, aturan menggabungkan satuan yang berbeda di beberapa file, dan bagaimana delay berinteraksi dengan logika yang dikendalikan clock.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

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. 1ns berarti satu tick adalah satu nanodetik.
  • Presisi (angka kedua): seberapa halus simulasi melacak waktu di dalam satuan itu. 1ps berarti 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 periodePeriodeFrekuensi
#12 ns500 MHz
#2.55 ns200 MHz
#510 ns100 MHz
#1020 ns50 MHz
#2550 ns20 MHz
#50100 ns10 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:

  • $time mengembalikan integer 64-bit dalam satuan timescale yang sedang berlaku.
  • $realtime mengembalikan real dalam 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 `timescale di awal setiap file. 1ns / 1ps adalah default yang aman.
  • Pakai #delay hanya 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.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai