Menu

Nilai X dan Z di Verilog: Sinyal Unknown dan Impedansi Tinggi

Sinyal Verilog punya empat kemungkinan nilai, bukan dua. Inilah arti sebenarnya dari x (tidak diketahui) dan z (impedansi tinggi) di simulasi, dan cara melakukan debug pada keduanya.

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

Logika Dua Keadaan vs Empat Keadaan

Di software, sebuah bit bernilai 0 atau 1. Di Verilog, sebuah bit bisa bernilai salah satu dari empat nilai:

  • 0: kabel digerakkan ke low.
  • 1: kabel digerakkan ke high.
  • x: nilai kabel tidak diketahui. Simulator tidak bisa memastikannya.
  • z: kabel dalam keadaan impedansi tinggi. Tidak ada yang menggerakkannya.

Model empat keadaan itu ada karena hardware punya masalah yang sama. Kabel sungguhan bisa terhubung ke low, terhubung ke high, tidak terdefinisi (digerakkan dua sumber yang saling berebut), atau mengambang (tidak ada penggerak sama sekali). Simulator harus memodelkan keempatnya agar berguna.

Bagaimana x Muncul

Jalankan kode ini dan lihat output-nya:

a dideklarasikan tapi tidak pernah ditulis, jadi nilainya tetap x. Menjumlahkan x + 5 menghasilkan x: aritmetika apa pun dengan nilai tidak diketahui menghasilkan nilai tidak diketahui. Di output, tempat aaaa itu terisi x semua.

Sumber x yang umum di desainmu:

  • reg yang dideklarasikan tapi tidak pernah di-reset (kebanyakan Verilog yang bisa disintesis memakai reset eksplisit untuk membersihkannya).
  • Pernyataan case tanpa default, yang menerima nilai input yang tidak cocok dengan case mana pun.
  • wire yang kehilangan satu-satunya penggerak setelah refactor.
  • Rantai if/else di mana satu cabang tidak memberi nilai ke sinyal yang diberi nilai oleh cabang lain (menahan x kalau tidak tercakup).
  • Membaca melewati ujung vektor atau array.

Penyebaran X: Sedikit x Merusak Segalanya

Yang kejam dari x adalah sifatnya yang menyebar. Satu bit x di sebuah operand membuat seluruh hasilnya menjadi x:

Perhatikan bahwa 0 & x bernilai 0 (AND dengan 0 selalu 0) dan 1 | x bernilai 1 (OR dengan 1 selalu 1). Simulator bersikap pesimis bit demi bit, tapi tetap menghormati identitas logika. Aritmetika dan perbandingan tidak semurah hati itu.

Inilah kenapa satu register yang belum diinisialisasi bisa membuat seluruh bus output menjadi xxxx. Telusuri mundur dari x mana pun dan kamu akan menemukan sumbernya.

Bagaimana z Muncul

z adalah nilai kabel yang tidak digerakkan oleh siapa pun:

Ada dua pola di potongan kode itu:

  • floating hanya dideklarasikan dan tidak pernah digerakkan. Nilai default-nya z.
  • data_out adalah tri-state yang disengaja. Saat enable bernilai low, output-nya secara eksplisit dilepas ke z. Begitulah cara penggerak bus "melepaskan" kabel agar penggerak lain bisa mengambil alih.

Di logika internal, z hampir selalu salah. Di pin dua arah atau bus bersama, z justru tepat.

Membandingkan dengan == vs ===

Operator kesamaan biasa == mengembalikan x kalau salah satu operand punya bit x atau z:

=== (dan pasangannya !==) melakukan perbandingan ketat bit demi bit, termasuk x dan z. Pakai operator ini setiap kali kamu perlu menguji apakah sesuatu bernilai x/z di testbench. === tidak bisa disintesis, tapi di dalam blok initial di testbench hal itu tidak masalah.

System function $isunknown(expr) adalah cara paling bersih untuk bertanya "apakah ekspresi ini punya bit x atau z?": hasilnya 1 kalau ya, 0 kalau tidak.

Memakai x sebagai Don't-Care yang Disengaja

Pola yang kontroversial tapi sah: 'x di case default sebuah state machine memberi tahu synthesizer "state ini tidak terjangkau, optimalkan sesukamu":

case (state)
    IDLE:    next_state = go ? RUNNING : IDLE;
    RUNNING: next_state = done ? IDLE : RUNNING;
    default: next_state = 'x;   // unreachable
endcase

Synthesizer bisa memakai x itu untuk menggabungkan state dan mengurangi jumlah gerbang. Di simulasi, kalau penalaranmu keliru dan default-nya ternyata tercapai, kamu akan melihat x menyebar dari next_state dan bug-nya langsung terlihat.

Pakai ini hanya kalau kamu sudah memikirkan dengan matang apakah default-nya memang tidak terjangkau. Kalau belum, isi default dengan state yang aman.

Resep Debug yang Umum

Kamu sedang menatap waveform yang penuh x. Resepnya:

  1. Cari x paling awal. Telusuri waveform mundur dalam waktu. Sinyal pertama yang menjadi x adalah yang paling dekat dengan sumbernya.
  2. Cari penggeraknya. Buka kode sumbernya. Apa yang memberi nilai ke sinyal ini? Sebuah assign? Sebuah blok always?
  3. Periksa input penggerak itu. Kalau sisi kanan (RHS) penggeraknya punya x, penyebarannya berjalan sebagaimana mestinya: bug-nya ada di hulu.
  4. Kalau input penggeraknya bersih tapi menghasilkan x, penggeraknya tidak lengkap. case tanpa default, if tanpa else, register tanpa reset.

Sebagian besar bug badai x berujung pada salah satu dari: reset yang hilang, default yang hilang, atau sub-module yang tidak terhubung.

Selanjutnya

Sekarang kamu punya cerita tipe data yang lengkap: wire/reg, vektor, parameter, literal angka, dan model logika empat keadaan. Bab berikutnya mulai memakai semuanya untuk membangun ekspresi: operator dari segala jenis, termasuk operator tingkat bit yang tidak masuk akal di dunia software.

Pertanyaan yang sering diajukan

Apa arti x di Verilog?

x adalah nilai tidak diketahui. Sinyal yang bernilai x bisa 0 atau 1, dan simulator tidak bisa memastikannya. Nilai ini muncul saat sinyal belum digerakkan, saat dua penggerak berebut, saat register dibaca sebelum reset, atau di mana pun perilaku tak terdefinisi kalau tidak begitu akan menyebar diam-diam. Anggap x sebagai tanda bug; nilai ini hampir tidak pernah berarti seperti yang kamu inginkan.

Apa arti z di Verilog?

z adalah nilai impedansi tinggi: kabelnya sama sekali tidak digerakkan. Ini keadaan yang sah untuk output tri-state (bus data, pin dua arah), tapi pada sinyal internal z biasanya sebuah kesalahan yang artinya 'tidak ada yang terhubung di sini'. Synthesizer menolak sebagian besar pola z di luar output enable tri-state yang eksplisit.

Kenapa output Verilog-ku xxxx?

Hampir selalu karena ada sinyal yang tidak digerakkan oleh apa pun, atau karena sebuah operasi menyebarkan x dari sinyal lain. Telusuri mundur: sinyal mana yang x, apa yang mengisinya, apakah penggeraknya aktif? Penyebab yang umum adalah case default yang hilang di pernyataan case, register yang tidak di-reset, dan wire yang kehilangan penggeraknya setelah refactor.

Bagaimana cara mengecek x atau z di Verilog?

Pakai operator ===, yang membandingkan bit demi bit secara persis, termasuk x dan z. a === 1'bx bernilai benar saat a memang x. Operator == biasa mengembalikan x kalau salah satu operand punya bit x, artinya a == 1'bx tidak pernah memberi jawaban yang kamu inginkan. Ada juga $isunknown(a), yang mengembalikan boolean dengan rapi.

Bisakah memakai x sebagai default di Verilog?

Bisa, dan ini teknik yang disengaja di pernyataan case: default: out = 'x; memberi tahu synthesizer 'aku jamin case ini tidak pernah terjadi, optimalkan sesukamu'. Risikonya, kalau ternyata terjadi di simulasi, x akan menyebar dan kamu melihat bug-nya. Pakai ini saat kamu sudah membuktikan bahwa default-nya memang tidak terjangkau, bukan sebagai cara untuk menghindari menulis case-nya.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai