Antarmuka Sebuah Module
Daftar port module adalah antarmuka-nya: semua yang bisa dilihat dan disentuh dunia luar. Di dalam module, isinya menghitung output dari input. Port adalah kabel yang melintasi batas module.
Deklarasi modern bergaya ANSI menuliskan arah, tipe, dan lebar secara langsung:
module my_module(
input wire clk,
input wire reset,
input wire [7:0] data_in,
output reg [7:0] data_out,
output wire valid
);
// body
endmodule
Itulah seluruh bentuknya. Setiap port punya:
- Arah:
input,output, atauinout. - Tipe:
wireataureg(ataulogicdi SystemVerilog). - Lebar: rentang seperti
[7:0], atau satu bit kalau tidak ditulis. - Nama: identifier yang akan kamu pakai di dalam isi module.
Tiga Arah Port
input: Digerakkan dari Luar
Input selalu bertipe wire. Penggeraknya berada di luar module, entah sinyal dari module di tingkat atas atau reg milik testbench. Di dalam module ini, kamu bisa membaca input di ekspresi, tapi tidak pernah boleh memberinya nilai:
module reader(input wire [7:0] data);
initial $display("data = %h", data);
endmodule
Menulis data = ... di dalam module akan menjadi error.
output: Digerakkan dari Dalam
Output digerakkan oleh sesuatu di dalam module ini. Tipenya bisa wire (digerakkan oleh assign atau output sub-module) atau reg (digerakkan dari always/initial).
module driver(
input wire a,
input wire b,
input wire clk,
output wire y, // wire - driven by assign
output reg q // reg - driven by always
);
assign y = a & b; // OK because y is wire
always @(posedge clk)
q <= a; // OK because q is reg
endmodule
Mencoba memberi nilai ke y di dalam blok always, atau menggerakkan q dengan assign, akan menghasilkan compile error. Pilihan kata kunci harus cocok dengan penggeraknya.
inout: Dua Arah
Port inout adalah kabel yang bisa digerakkan bergantian oleh module itu sendiri atau oleh apa pun yang terhubung di luar. Port ini muncul di batas chip: jalur SDA I²C, pin GPIO dua arah, bus data bersama. Di dalam module, kamu mengatur arahnya dengan pola tri-state:
module bidir_pin(
input wire data_out,
input wire output_enable,
output wire data_in,
inout wire pin
);
assign pin = output_enable ? data_out : 1'bz;
assign data_in = pin;
endmodule
pin adalah kabel yang dipakai bersama. Saat output_enable bernilai high, module menggerakkan pin ke data_out. Saat low, module melepas pin ke impedansi tinggi (z), sehingga penggerak eksternal bisa memakainya. data_in selalu mengamati apa pun yang sedang ada di pin.
inout jarang dipakai di logika yang murni internal. Kalau kamu membangun kontroler memori, inti CPU, atau pipeline pemrosesan gambar, mungkin kamu tidak akan pernah membutuhkannya. Ini fitur untuk lingkar I/O di batas chip.
Port Satu Bit vs Banyak Bit
Rentang lebar bersifat opsional; hilangkan untuk port satu bit:
input wire valid, // 1 bit
input wire [7:0] data, // 8 bits
input wire [31:0] addr, // 32 bits
Kamu bisa memakai parameter untuk lebar, dan begitulah cara kerja module berparameter:
module bus #(
parameter WIDTH = 32
)(
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
assign out = in;
endmodule
Gaya ANSI vs Verilog-1995
Sesekali kamu akan melihat kode lama yang memisahkan daftar port dan deklarasinya:
// Old Verilog-1995 style - DON'T do this in new code
module foo(clk, data_in, data_out);
input clk;
input [7:0] data_in;
output reg [7:0] data_out;
// ...
endmodule
Daftar port hanya berisi nama; setiap port lalu dideklarasikan terpisah di dalam isi module. Gaya ini bertele-tele, rawan error "disebut di daftar port tapi tidak pernah dideklarasikan", dan butuh ketikan dua kali lebih banyak. Gaya ANSI-2001 (yang dipakai di seluruh dokumentasi ini) menggantikan keduanya:
module foo(
input wire clk,
input wire [7:0] data_in,
output reg [7:0] data_out
);
// ...
endmodule
Pakai gaya ANSI. Tool sudah mendukungnya sejak 2001.
Contoh Lengkap
Satu module itu punya:
- Sebuah parameter (
WIDTH). - Input untuk clock, reset, load enable, data, dan shift enable.
- Output
reg(data_out) yang digerakkan di dalam blokalways. - Output
wire(msb_out) yang digerakkan oleh penugasan kontinu. - Deklarasi lengkap bergaya ANSI yang mencantumkan arah, tipe, dan lebar setiap port secara langsung.
Begitulah bentuk hampir setiap module yang bisa disintesis yang akan kamu tulis.
Selanjutnya
Dokumen berikutnya, Instantiasi Module, menunjukkan cara memakai module ini di dalam desain yang lebih besar. Shifter yang baru kamu tulis tidak berguna sendirian; ia baru bermanfaat saat ada yang membuat instance-nya dan menghubungkannya ke sebuah sistem.
Pertanyaan yang sering diajukan
Apa saja tiga arah port di Verilog?
input, output, dan inout. input digerakkan dari luar module. output digerakkan dari dalam module. inout bersifat dua arah, berguna untuk bus tri-state di mana module menggerakkan sekaligus membaca pin yang sama. Sebagian besar port internal adalah input atau output; inout hanya muncul di pin chip.
Apa perbedaan output wire dan output reg?
output wire berarti output digerakkan oleh penugasan kontinu atau oleh output sub-module, yaitu semua hal di luar blok always. output reg berarti output digerakkan dari blok prosedural (initial atau always). Kata kunci itu menentukan apakah kamu bisa memberi nilai ke sinyal tersebut dari dalam always, bukan apakah hardware hasil sintesisnya berisi flip-flop.
Apa itu gaya ANSI untuk port Verilog?
Gaya ANSI mendeklarasikan arah dan tipe setiap port langsung di daftar port: module foo(input wire [7:0] data, output reg [7:0] result);. Gaya Verilog-1995 yang lebih lama hanya mencantumkan nama di daftar port lalu mendeklarasikannya ulang di dalam module. Selalu pakai gaya ANSI di kode baru: lebih pendek, lebih kecil kemungkinan error, dan menjadi standar di semua tool modern.
Apakah satu module Verilog bisa punya banyak input dan output?
Bisa. Module boleh punya port sebanyak yang kamu butuhkan, dengan kombinasi arah apa pun. Pisahkan dengan koma di daftar port. Urutan di daftar port menentukan urutan koneksi berdasarkan posisi saat instantiasi, tapi hampir selalu kamu memakai koneksi bernama (.port(signal)) agar tidak bergantung pada urutan.