Menu

Dasar Testbench Verilog: Cara Memverifikasi Module

Cara menulis testbench Verilog: pembangkitan clock, urutan reset, stimulus, pengamatan, dan kerangka standar yang menggerakkan setiap simulasi yang akan kamu jalankan.

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

Apa Sebenarnya Testbench Itu

Testbench hanyalah sebuah module Verilog. Bedanya dengan module yang bisa disintesis ada pada isinya:

  • Ia tidak punya port: ia adalah puncak hierarki simulasi.
  • Ia membuat instance dari design under test.
  • Ia menggerakkan input DUT dari blok initial dan always.
  • Ia mengamati output DUT dengan $display, $monitor, atau dengan menyimpan VCD.
  • Ia mengakhiri simulasi dengan $finish.

Itulah seluruh tugasnya. Tidak ada kata kunci khusus "testbench"; cara mengenali sebuah testbench adalah dengan membaca apa yang dilakukannya.

Kerangka Standar

Itulah seluruh polanya. Lima bagian, mudah di-copy-paste, mudah disesuaikan.

Untuk DUT kombinasional (seperti adder ini), kamu tidak butuh clock. Untuk DUT sekuensial, kamu butuh, dan itu lapisan berikutnya.

Membangkitkan Clock untuk DUT Sekuensial

Saat DUT punya input clk, testbench harus menghasilkannya. Satu baris yang standar:

reg clk = 0;
always #5 clk = ~clk;

Itu membalik clk setiap 5 satuan waktu. Setiap pembalikan adalah setengah periode clock, jadi periode penuhnya 10 satuan (satu siklus = high selama 5 + low selama 5). Kalau timescale-mu 1ns / 1ps (default di kebanyakan simulator), itu clock 100 MHz.

Pilih setengah periodenya sesuai yang ingin kamu modelkan. Untuk clock 10 MHz dengan timescale yang sama, pakai #50. Untuk clock 200 MHz, #2.5 (atau ubah timescale-nya).

Urutan Reset

Desain sinkron butuh reset yang ditahan high selama beberapa siklus setelah waktu 0, lalu dilepas. Bentuk konvensionalnya:

reg reset = 1;     // start asserted

initial begin
    // Hold reset for a few clocks.
    #20 reset = 0;
end

Itu menahan reset tetap high sampai waktu 20, lalu menurunkannya. Saat reset turun, clock sudah berjalan beberapa siklus, setiap flip-flop sudah menangkap nilai reset, dan desainnya berada di state yang jelas.

Untuk reset aktif low (reset_n alih-alih reset), balik nilai awalnya:

reg reset_n = 0;   // active-low: 0 means asserted

initial begin
    #20 reset_n = 1;
end

Testbench Sekuensial Lengkap

Menggabungkan clock, reset, dan stimulus:

Itu testbench lengkap untuk counter 4-bit. Tekan Jalankan dan kamu akan melihat counter keluar dari reset, menghitung naik selama enable aktif, berhenti sejenak saat enable turun, lanjut lagi saat enable naik, lalu berhenti.

Tiga hal tentang strukturnya yang perlu diperhatikan:

  1. Tiga pusat aktivitas yang terpisah: pembangkit clock (satu always), stimulus (satu initial), dan pemantau (always yang lain). Masing-masing punya satu tugas.
  2. Delay # di blok stimulus diukur dalam satuan waktu, bukan siklus clock. Kalau periode clock-mu 10 satuan, maka #10 tepat satu siklus. Beberapa testbench memakai @(posedge clk) sebagai gantinya, yang maju satu siklus berapa pun periodenya.
  3. Pemantau memakai $display dari blok always @(posedge clk). Itu mencetak di setiap siklus. Untuk output yang lebih canggih, beralihlah ke $monitor (dibahas berikutnya).

Stimulus Berbasis Siklus

Kadang "tunggu N siklus" lebih enak dibaca daripada "tunggu N satuan waktu":

initial begin
    @(posedge clk);     // wait for next clock edge
    reset = 0;

    repeat (5) @(posedge clk);   // wait 5 more cycles
    enable = 1;

    repeat (8) @(posedge clk);
    enable = 0;

    repeat (10) @(posedge clk);
    $finish;
end

@(posedge clk) menunggu sampai tepi naik clock berikutnya. repeat (N) @(posedge clk); menunggu N siklus. Gaya ini tidak bergantung pada periode clock: kalau kamu mengubah frekuensi clock, stimulus tetap melakukan hal yang sama dalam hitungan siklus.

Untuk testbench awal, delay # lebih sederhana. Untuk testbench produksi yang mungkin dijalankan dengan beberapa kecepatan clock, gaya berbasis siklus lebih aman.

Pengujian yang Memeriksa Sendiri

Testbench sejauh ini mencetak apa yang terjadi, dan kamu yang harus membaca output-nya. Testbench yang memeriksa sendiri (self-checking) justru mengecek output-nya dan melaporkan lulus/gagal:

initial begin
    #1;
    a = 10; b = 20;
    #1;
    if (sum !== 30) begin
        $display("FAIL: 10 + 20 = %0d (expected 30)", sum);
        $finish;
    end
    a = 250; b = 5;
    #1;
    if (sum !== 255) begin
        $display("FAIL: 250 + 5 = %0d (expected 255)", sum);
        $finish;
    end

    $display("PASS");
    $finish;
end

Pakai !== (operator case inequality) agar aman, karena operator ini tidak mengembalikan x saat salah satu operand punya bit yang tidak diketahui. Polanya: gerakkan input, tunggu sampai stabil, bandingkan dengan nilai yang diharapkan, laporkan lulus atau gagal.

Pengujian yang memeriksa sendiri sangat berharga di suite regresi: ribuan pengujian bisa berjalan tanpa diawasi, dan hanya yang gagal yang perlu diperhatikan.

Selanjutnya

Sekarang kamu punya bentuk testbench yang cukup untuk module apa pun. Dokumen-dokumen berikutnya membahas alat yang dipakai di dalam testbench: Display dan Monitor untuk output teks yang lebih kaya, Dumpfile dan VCD untuk debug waveform secara grafis, dan Timescale dan Delay untuk mengatur dengan tepat bagaimana waktu simulasi berhubungan dengan waktu nyata.

Pertanyaan yang sering diajukan

Apa itu testbench di Verilog?

Testbench adalah module Verilog, biasanya tanpa port, yang satu-satunya tujuannya menguji design under test (DUT). Testbench membuat instance DUT, membangkitkan clock, menggerakkan stimulus lewat blok initial dan always, mengamati output dengan $display/$monitor, bisa juga menyimpan waveform VCD, dan mengakhiri simulasi dengan $finish.

Bagaimana cara membuat clock di testbench Verilog?

Pola standarnya hanya satu baris: always #5 clk = ~clk; (dengan reg clk = 0; yang sudah dideklarasikan sebelumnya). Baris itu membalik clk setiap 5 satuan waktu simulasi, sehingga periodenya 10 satuan (clock 100 MHz kalau timescale-mu dalam nanodetik). #5 adalah setengah periode: separuh waktu clk bernilai high, separuh lagi low.

Apa itu DUT di Verilog?

DUT adalah singkatan dari Design Under Test, yaitu module yang sedang diuji oleh testbench. Konvensinya, instance DUT di testbench dinamai dut atau u_dut: my_module dut(.clk(clk), .reset(reset), .in(in), .out(out));. Namanya hanya label; yang penting module itu dibuat instance-nya, port-nya terhubung ke sinyal testbench, dan testbench menggerakkan sinyal-sinyal itu.

Berapa lama simulasi Verilog sebaiknya berjalan?

Cukup lama untuk menguji semua yang ingin kamu verifikasi, lalu $finish. Kebanyakan testbench menetapkan batas waktu eksplisit (#1000 $finish) agar simulasi tidak macet menunggu event yang tidak pernah datang. Di dalam rentang waktu itu, gerakkan stimulus, biarkan DUT stabil, dan sebaiknya sertakan beberapa pernyataan if yang memeriksa sendiri dan mencetak FAIL kalau output-nya tidak sesuai harapan.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai