Menu

Parameter Verilog: Membuat Module yang Bisa Dikonfigurasi

Cara memakai parameter dan localparam untuk mendefinisikan konstanta saat compile, membuat lebar dan kedalaman berparameter, dan menimpa nilainya saat membuat instance module.

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

Konstanta dengan Sedikit Kejutan

parameter adalah konstanta: compiler menentukan nilainya dan menanamkannya ke dalam desain sebelum simulasi dimulai. Kejutannya, siapa pun yang membuat instance module bisa mengubah nilainya. File sumber module yang sama bisa menghasilkan rangkaian dengan ukuran berbeda, tergantung bagaimana pemakainya mengatur parameternya.

Begitulah cara membangun IP yang bisa dipakai ulang. Module FIFO dengan parameter WIDTH dan DEPTH bisa melayani setiap tim di sebuah perusahaan. Counter dengan parameter WIDTH memakai sumber yang sama, entah menghitung sampai 16 atau sampai 4 miliar.

Deklarasi Parameter Dasar

Tiga potong sintaks baru:

  1. Blok parameter: #( parameter WIDTH = 8 ) di antara nama module dan daftar port. Nilai default 8 adalah nilai yang dipakai module saat tidak ada yang menimpanya.
  2. Tempat pemakaian: output reg [WIDTH-1:0] count. Parameter hanyalah konstanta: kita memasukkannya ke rentang bit. Sumber module yang sama menghasilkan output 8-bit atau 16-bit tergantung WIDTH.
  3. Sintaks penimpaan: counter #(.WIDTH(16)) dut16(...) saat instantiasi. Blok #(...) ditaruh sebelum nama instance, setelah nama module. Parameter yang tidak kamu sebutkan tetap memakai nilai default-nya.

localparam: Konstanta Internal

Ada konstanta yang tidak ingin kamu biarkan ditimpa oleh pemakai module. Encoding state adalah contoh klasiknya:

localparam membuat IDLE, RUNNING, DONE tersedia di dalam module, tapi tidak bisa ditimpa saat instantiasi. Itu pilihan yang tepat: mengubah nilai state mana yang berarti IDLE dari luar module akan sangat menakutkan.

Pakai parameter untuk hal-hal yang sebaiknya bisa dikonfigurasi pemakai (lebar, kedalaman, opsi perilaku) dan localparam untuk sisanya. Pola yang umum adalah menurunkan localparam dari parameter:

parameter WIDTH = 32;
localparam WIDTH_M1 = WIDTH - 1;   // computed once; not overrideable

Lebar Berparameter dalam Praktik

Pemakaian parameter yang paling umum adalah membuat lebar bus menjadi fleksibel. Ini adder yang bekerja di lebar berapa pun:

Satu file sumber, dua instance, dua lebar berbeda, tanpa copy-paste. Itulah seluruh manfaat parameter.

Banyak Parameter, Penimpaan Bernama

Untuk module yang lebih besar, sering kali kamu punya beberapa parameter. Timpa berdasarkan nama, dengan urutan bebas:

module fifo #(
    parameter WIDTH = 8,
    parameter DEPTH = 16,
    parameter AFULL = DEPTH - 2
)(
    input  wire             clk,
    input  wire             reset,
    // ... ports ...
);
    // ...
endmodule

// At the call site:
fifo #(.WIDTH(32), .DEPTH(1024)) cmd_queue (.clk(clk), .reset(reset), ...);

Kamu tidak harus menimpa setiap parameter; yang tidak disebutkan tetap memakai nilai default-nya. Default AFULL di contoh dihitung dari DEPTH, artinya kalau kamu menimpa DEPTH, AFULL otomatis ikut. Ketergantungan seperti ini juga bisa ditangani localparam kalau kamu tidak ingin pemakai bisa menimpa AFULL secara terpisah.

Kesalahan yang Umum

Lupa # saat menimpa. counter (.WIDTH(16)) dut(...) terlihat seperti penimpaan, tapi Verilog membaca (.WIDTH(16)) sebagai koneksi port. Kamu butuh counter #(.WIDTH(16)) dut(...).

Memakai parameter untuk nilai yang tidak cukup konstan. Parameter ditentukan saat elaborasi, sebelum ada sinyal apa pun. Kamu tidak bisa membuat parameter dari sinyal saat runtime: kalau nilainya bergantung pada apa yang dilakukan sebuah input saat simulasi, itu bukan parameter, melainkan logika.

Tertukar parameter dan localparam di daftar port. Hanya parameter yang masuk ke blok #(...) di bagian atas. localparam berada di dalam isi module. Compiler akan memberi tahu kalau kamu menukarnya.

Selanjutnya

Sekarang kamu bisa membuat module yang ukurannya ditentukan saat compile. Dua dokumen berikutnya membahas aturan menulis konstanta literal (8'h1F, 4'b1010, 32'd100) dan nilai x serta z yang muncul saat sinyal tidak digerakkan atau diperebutkan. Setelah itu kita lanjut ke operator: semua yang bisa kamu lakukan dengan vektor dan parameter yang sudah kamu lihat.

Pertanyaan yang sering diajukan

Apa itu parameter di Verilog?

parameter adalah konstanta saat compile yang dideklarasikan di dalam module. Ia bisa dipakai di mana pun konstanta diperbolehkan: lebar bus, kedalaman memori, encoding state, nilai default. Yang terpenting, setiap instance module bisa menimpa parameter itu, sehingga file sumber yang sama bisa menghasilkan, misalnya, counter 8-bit di satu tempat dan counter 32-bit di tempat lain.

Apa perbedaan parameter dan localparam di Verilog?

Nilai parameter bisa ditimpa dari luar module saat instance-nya dibuat. Nilai localparam tidak bisa; ia hanya konstanta internal. Pakai localparam untuk encoding state dan konstanta turunan yang tidak ingin diutak-atik oleh pemakai module.

Bagaimana cara menimpa parameter di Verilog?

Saat membuat instance module, tambahkan blok penimpaan parameter sebelum nama instance: counter #(.WIDTH(16)) my_inst (.clk(clk), .count(count));. Sintaks .WIDTH(16) mengatur parameter tertentu itu; parameter yang tidak kamu sebutkan tetap memakai nilai default-nya. Beberapa penimpaan dipisahkan dengan koma di dalam #(...).

Apa itu module berparameter?

Module yang menyediakan satu atau lebih deklarasi parameter yang bisa ditimpa oleh pemakainya. FIFO berparameter bisa punya parameter WIDTH dan DEPTH, sehingga sumber yang sama menghasilkan FIFO 32-bit sedalam 16 di satu tempat dan FIFO 8-bit sedalam 1024 di tempat lain. Begitulah library blok IP yang bisa dipakai ulang ditulis.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai