Menu

If-Else di Verilog: Logika Kondisional di Blok Prosedural

Cara kerja if/else di dalam blok always, jebakan latch yang sering menjerat pemula, dan hardware priority encoder yang dihasilkan rantai else if.

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

Sintaks yang Familier, Cara Berpikir yang Berbeda

if/else terlihat persis seperti di C:

if (condition) begin
    // ... statements ...
end else begin
    // ... statements ...
end

Tapi aturannya berbeda karena Verilog bukan software. Dua hal yang perlu diingat:

  1. if/else hanya ada di dalam blok prosedural. Kamu tidak bisa menulis if yang berdiri sendiri di tingkat module.
  2. Hasil sintesis if/else bergantung pada jenis bloknya. Di blok kombinasional, ia menjadi multiplexer atau priority encoder. Di blok yang dikendalikan clock, ia menjadi flip-flop dengan logika pembaruan kondisional.

Di Dalam Blok Kombinasional

Blok kombinasional always @(*) berjalan ulang setiap kali a, b, atau c berubah. Rantai if/else memilih satu cabang, memberi nilai ke max, lalu blok selesai. Karena max selalu diberi nilai (setiap jalur punya penugasan), synthesizer menghasilkan logika kombinasional murni, tanpa latch.

Perhatikan bahwa max dideklarasikan sebagai reg meskipun tidak ada flip-flop di hardware-nya. Aturannya sama seperti biasa: apa pun yang diberi nilai di dalam always harus bertipe reg.

Jebakan Latch

Inilah bug paling umum di kode kombinasional pemula:

// WRONG - infers a latch
always @(*) begin
    if (enable)
        out = data;
    // no else! when `enable` is low, what does `out` do?
end

Synthesizer membaca "saat enable bernilai low, out tidak diberi nilai" dan memutuskan bahwa out harus mengingat nilai sebelumnya. Mengingat nilai butuh sel penyimpanan, jadi tool menyisipkan latch. Latch di desain sinkron menyebabkan masalah timing, sulit di-reset, dan hampir tidak pernah seperti yang kamu maksud.

Dua cara memperbaikinya:

Keduanya menghasilkan hardware kombinasional yang sama: mux 2-ke-1. Pola "default di awal" lebih mudah dikembangkan saat kamu punya banyak penugasan kondisional ke sinyal yang sama.

Di Dalam Blok yang Dikendalikan Clock

Perhatikan apa yang berbeda dari kasus kombinasional:

  • Bloknya always @(posedge clk): wilayah flip-flop.
  • Penugasannya memakai <= (non-blocking).
  • Tidak ada else untuk kasus "bukan reset dan bukan enable". Itu tidak masalah. Di blok yang dikendalikan clock, saat tidak ada cabang yang berjalan, flip-flop hanya menahan nilai sebelumnya, persis seperti yang dilakukan flip-flop secara fisik. Tidak ada latch yang disimpulkan karena sinyalnya memang sudah register.

Inilah satu-satunya tempat di mana menghilangkan else itu aman. Di luar blok yang dikendalikan clock, selalu tangani setiap jalur.

Rantai else if: Priority Encoder

Rantai pernyataan else if punya prioritas implisit: kondisi yang lebih awal mengalahkan yang lebih belakang:

requests[0] punya prioritas tertinggi: kalau bit itu aktif, grant-nya 0, apa pun nilai bit-bit bernomor lebih tinggi. Synthesizer mengubah rantai itu menjadi mux bertingkat: cek bit 0 dulu, lalu bit 1, lalu bit 2, lalu bit 3. Setiap tingkat menambah sedikit delay.

Kalau kondisi-kondisinya saling eksklusif, misalnya saat mendekode input one-hot, pernyataan case (dokumen berikutnya) menghasilkan hardware yang lebih datar dan lebih cepat daripada rantai else if. Pakai bentuk case saat tidak ada kebutuhan prioritas yang sebenarnya.

if Tanpa else di Kode yang Dikendalikan Clock

Blok yang dikendalikan clock tidak butuh else, karena "tahan nilai sebelumnya" adalah perilaku default-nya. Begitulah cara membangun enable:

always @(posedge clk) begin
    if (load) target <= incoming;
    // no else: when load is low, target keeps its value
end

Itu adalah register dengan load enable. Sebagian besar register pipeline, counter, dan register konfigurasi memakai pola ini.

begin/end dan Pernyataan Tunggal

Seperti di C, kamu boleh menghilangkan begin/end untuk satu pernyataan:

if (a) out = 1;
else   out = 0;

Untuk lebih dari satu pernyataan, pakai bloknya:

if (a) begin
    out = 1;
    flag = 1;
end else begin
    out = 0;
    flag = 0;
end

Kedua pola itu bisa dicampur dengan bebas. Panduan gaya umumnya menyarankan selalu memakai begin/end agar menambah pernyataan kedua tidak merepotkan.

Selanjutnya

Dokumen berikutnya, Pernyataan Case, membahas case, alat yang tepat untuk dekode banyak arah (state machine, pemilihan berdasarkan opcode, tabel ROM). Setelah itu, loop for, yang sedikit berbeda dari saudaranya di software karena dibuka saat elaborasi.

Pertanyaan yang sering diajukan

Bagaimana cara kerja pernyataan if di Verilog?

if (cond) statement; menjalankan statement saat cond bernilai bukan nol. Kamu bisa membungkus beberapa pernyataan dengan begin ... end. Tambahkan else statement; untuk cabang alternatifnya, atau rangkai dengan else if (other_cond) .... if/else hanya ada di dalam blok prosedural, yaitu initial atau always, bukan di tingkat atas module.

Apa itu inferred latch di Verilog?

Latch yang dibuat tool sintesis tanpa kamu minta, karena blok always kombinasionalmu tidak memberi nilai ke sebuah sinyal di setiap jalur. Tool melihat 'kalau a maka out = 1' tanpa else, lalu memutuskan kasus yang tidak diberi nilai harus mengingat nilai sebelumnya, dan menghasilkan latch. Latch hampir selalu salah; solusinya, beri setiap sinyal nilai default di awal blok atau tambahkan else yang eksplisit.

Bagaimana cara menghindari inferred latch di Verilog?

Di blok kombinasional always @(*), pastikan setiap reg output diberi nilai di setiap jalur kode. Pola yang paling rapi adalah mengatur nilai default di awal blok, lalu menimpanya secara kondisional. Compiler biasanya memberi peringatan saat menyimpulkan latch; perlakukan peringatan itu sebagai error.

Hardware apa yang dihasilkan rantai if-else di Verilog?

Sebuah priority encoder. if pertama punya prioritas tertinggi, else if berikutnya hanya dicek kalau yang pertama salah, dan seterusnya. Di hardware, itu menjadi rantai mux dengan urutan prioritas yang sudah tertanam. Kalau kondisi-kondisinya saling eksklusif, pernyataan case dengan logika yang sama sering disintesis menjadi hardware yang lebih datar dan lebih jelas dibaca.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai