Menu

$display dan $monitor di Verilog: Mencetak dari Testbench

Cara kerja $display, $write, dan $monitor: format specifier yang akan kamu pakai, perbedaan di antara ketiganya, dan kapan masing-masing menjadi alat yang tepat.

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

Keluarga printf ala Verilog

Ada tiga system task untuk mencetak ke stdout simulator:

  • $display: mencetak sekali, menambahkan baris baru.
  • $write: mencetak sekali, tanpa baris baru.
  • $monitor: mencetak otomatis setiap kali sinyal yang dipantau berubah.

Ketiganya menerima format string dan daftar argumen, persis seperti printf. Format specifier-nya mirip, tapi khas Verilog.

$display: Pilihan Default

$display adalah andalan utamanya:

Kamu akan melihat kira-kira seperti ini:

Hello, world.
byte_val  = ab
byte_val  = 10101011
byte_val  = 171
byte_val  = 171 (no padding)
multi: nibble=1010 count=42

Catatan:

  • %d memberi padding sampai lebar default berdasarkan ukuran operand. Untuk reg 8-bit, itu 3 karakter (cukup untuk 255). Spasi di depannya bisa terlihat jelek di output berbentuk tabel; pakai %0d untuk menghilangkannya.
  • %h, %b, %o juga punya padding serupa secara default. Kebanyakan kode testbench memakai varian %0 saat perataan itu tidak berguna.
  • Baris baru di akhir ditambahkan otomatis. Jangan taruh \n di akhir format string $display, karena kamu akan mendapat baris kosong.

Format Specifier

Daftar yang didukung Verilog:

SpecifierArti
%bbiner
%ddesimal (signed kalau sinyalnya signed)
%h atau %xhex
%ooktal
%csatu karakter ASCII (8 bit terendah)
%sstring
%twaktu simulasi
%mnama hierarkis dari scope saat ini
%%karakter % literal
%0Xtanpa padding di depan, untuk %b, %d, dan lainnya

%b, %d, %h, %o adalah empat yang akan kamu pakai 95% dari waktu. %t yang paling umum berikutnya, setiap kali kamu ingin baris log dengan cap waktu.

$write: Tanpa Baris Baru

$write sama persis dengan $display, hanya saja tidak menambahkan baris baru:

Output:

abc
done

Berguna untuk membangun satu baris dari isi sebuah loop:

$write("[");
for (integer i = 0; i < 8; i = i + 1) $write("%h ", arr[i]);
$display("]");

$monitor: Mencetak Otomatis saat Berubah

$monitor mendaftarkan daftar pantauan. Simulator mengevaluasi ulang dan mencetak setiap kali sinyal apa pun yang disebut di format string berubah:

Kamu akan melihat tiga baris, satu untuk setiap perubahan input. Tidak perlu memanggil $display secara manual setelah setiap perubahan stimulus, karena $monitor yang melakukannya.

Dua keterbatasannya:

  • Hanya satu $monitor yang bisa aktif. Memanggilnya lagi akan mengganti daftar pantauan sebelumnya. Pakai $monitoroff dan $monitoron untuk menonaktifkan sementara dan mengaktifkannya kembali.
  • Perubahan dalam langkah waktu yang sama digabung menjadi satu cetakan. Kalau a dan b sama-sama berubah pada waktu 5, monitor mencetak sekali dengan kedua nilai baru, bukan dua kali.

Kapan Memakai Masing-Masing

  • $display: sebagian besar output testbench. Panggil secara eksplisit setelah stimulus, setelah transisi state yang penting, atau di dalam blok always @(posedge clk) yang mengambil sampel.
  • $write: saat kamu ingin membangun satu baris dari loop atau beberapa potongan kecil.
  • $monitor: saat kamu ingin memantau sekumpulan kecil sinyal terus-menerus dan hanya melihat output saat sinyalnya berubah. Berguna untuk debug awal; lebih sulit dipakai di skrip regresi karena jumlah total baris output-nya tidak deterministik.

Untuk kebanyakan alur kerja, $display sudah mencakup semuanya. Pakai $monitor hanya kalau output yang dipicu perubahan secara terus-menerus memang benar-benar yang kamu inginkan.

Bekerja dengan Waktu

$time mengembalikan waktu simulasi saat ini sebagai integer 64-bit. Pasangkan dengan %0t:

$display("at %0t: signal flipped", $time);

Output-nya terlihat seperti at 25: signal flipped (satuannya bergantung pada timescale-mu).

Kalau kamu butuh presisi di bawah satu tick (jarang), pakai $realtime, yang mengembalikan real.

%t otomatis memformat waktu dengan lebar default yang dipilih simulator. %0t menghilangkan padding-nya.

Mengambil Sampel di Tepi Clock

Idiom yang rapi untuk memantau desain sekuensial: blok always @(posedge clk) terpisah yang mencetak sekali per siklus:

Pola sampling ini menjamin satu baris log per clock, sangat cocok untuk pengujian regresi yang mencocokkan pola di output.

Mencatat Log ke File

Buka file dengan $fopen, lalu catat dengan $fdisplay (yang bekerja seperti $display tapi menulis ke file handle):

integer fd;
initial begin
    fd = $fopen("results.txt", "w");
    $fdisplay(fd, "test=%s status=%s", test_name, status);
    $fclose(fd);
end

$fopen mengembalikan handle 32-bit; berikan sebagai argumen pertama ke $fdisplay, $fwrite, $fstrobe, dan seterusnya. Selebihnya, fungsi-fungsi itu identik dengan saudaranya yang mencetak ke konsol.

Selanjutnya

$display dan kawan-kawannya memberimu log teks. Untuk debug visual, yaitu mengamati sinyal sebagai tegangan dari waktu ke waktu, kamu butuh waveform VCD. Dokumen berikutnya, Dumpfile dan VCD, membahas $dumpfile dan $dumpvars, dua panggilan yang mengubah simulasimu menjadi waveform grafis yang bisa kamu telusuri.

Pertanyaan yang sering diajukan

Apa perbedaan $display dan $monitor di Verilog?

$display mencetak sekali, langsung, saat dijalankan, seperti printf di C. $monitor mendaftarkan daftar pantauan; setiap kali ada sinyal di daftar itu yang berubah, pesan berformatnya otomatis dicetak. Hanya satu $monitor yang bisa aktif pada satu waktu; memanggilnya lagi akan mengganti daftar pantauan sebelumnya.

Format specifier apa saja yang didukung $display di Verilog?

Yang umum: %b (biner), %d (desimal), %h (hex), %o (oktal), %c (satu karakter dari byte terendah), %s (string), %t (waktu simulasi), %m (nama instance hierarkis). Pakai bentuk %0d untuk menghilangkan padding di depan: %d memberi padding sampai lebar default, %0d tanpa padding sama sekali.

Apa itu $write di Verilog?

$write mirip $display, tapi tidak menambahkan baris baru. Berguna saat kamu ingin membangun satu baris output dari beberapa panggilan. $display di akhir baris (tanpa argumen atau dengan baris baru di ujungnya) menutup baris itu.

Bagaimana cara mencetak waktu simulasi di Verilog?

Pakai $time (atau $realtime untuk resolusi di bawah satu tick) dengan format specifier %t: $display("at time %t: ...", $time);. Pakai %0t untuk menghilangkan padding default-nya. Untuk hitungan satuan waktu sebagai integer biasa, %0d dengan $time juga bisa: $display("t=%0d", $time);.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai