Menu

Pernyataan Case di Verilog: Dekode Banyak Arah dengan Benar

Cara kerja case untuk dekode banyak arah yang rapi, default yang tidak boleh kamu lewatkan, dan perbedaan antara case, casex, dan casez.

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

Percabangan Banyak Arah

case adalah konstruksi percabangan datar di Verilog. Kamu memberinya sebuah ekspresi; ia memilih cabang yang cocok:

case (expression)
    pattern_1: statement_1;
    pattern_2: statement_2;
    pattern_3: begin
        statement_3a;
        statement_3b;
    end
    default: default_statement;
endcase

Strukturnya mirip switch di C, tapi:

  • Tidak ada break: setiap cabang otomatis berakhir saat cabang berikutnya dimulai.
  • Polanya bisa berupa vektor, bukan hanya integer.
  • Synthesizer mengubah seluruhnya menjadi mux datar (atau decoder one-hot kalau polanya memungkinkan).

Contoh Lengkap: Mux 4-ke-1

Isi case punya empat pola eksplisit ditambah default. Synthesizer melihat input 2-bit yang dipetakan ke salah satu dari empat nilai dan menghasilkan multiplexer 4-ke-1. Rapi, datar, cepat.

Kenapa Kamu Butuh default

Untuk case kombinasional, menghilangkan default adalah jebakan yang sama dengan if tanpa else: nilai input apa pun yang tidak cocok membuat out tidak diberi nilai, dan synthesizer menyimpulkan latch.

Untuk sel 2-bit, pola-pola di atas sudah mencakup keempat nilai yang mungkin, jadi secara teori default tidak diperlukan. Dalam praktiknya:

  1. Synthesizer tidak selalu bisa membuktikan bahwa case-nya sudah lengkap.
  2. Pemilihnya mungkin bernilai x atau z di simulasi, yang tidak cocok dengan case eksplisit mana pun.
  3. Menambahkan case baru nanti bisa membuat perilaku default-nya tidak terdefinisi.

Selalu tulis default. Untuk state machine dan logika mux di mana kamu tahu default-nya tidak terjangkau, memberi nilai 'x:

default: out = 8'bx;

…memberi tahu synthesizer "ini don't-care, optimalkan sesukamu" dan memunculkan x merah yang mencolok di simulasi kalau case yang tidak terjangkau itu entah bagaimana tercapai. Itulah yang terbaik dari kedua sisi.

State Machine dengan case

Pemakaian klasik case adalah logika transisi state dari finite state machine:

Blok case (state) adalah logika transisi state-nya. Setiap cabang menentukan state berikutnya dan berapa lama tinggal di sana. default tidak terjangkau di sini (kita mencakup RED/GREEN/YELLOW secara lengkap di ruang 2-bit), tapi tetap ada sebagai jaring pengaman: kalau state entah bagaimana menjadi 2'd3, FSM kembali dengan rapi ke RED alih-alih membentuk latch.

Finite State Machine membahas pola ini lebih dalam.

Beberapa Pola per Cabang

Kamu bisa mencantumkan beberapa pola yang berbagi satu pernyataan, dipisahkan koma:

case (opcode)
    4'h0, 4'h1, 4'h2: result = a + b;
    4'h3, 4'h4:       result = a - b;
    4'h8:             result = a & b;
    default:          result = 8'd0;
endcase

Itu berarti dua opcode yang sama-sama berarti "kurang", tiga yang berarti "tambah". Synthesizer meng-OR-kan pola-pola itu untuk komparatornya.

casez dan casex: Pencocokan Don't-Care

Kadang kamu ingin mencocokkan pola dengan sebagian bit yang tidak ditentukan, misalnya "opcode apa pun yang diawali 010":

casez (opcode)
    8'b010?_????: instruction = ALU_OP;
    8'b110?_????: instruction = LOAD_OP;
    8'b1110_????: instruction = JUMP_OP;
    default:      instruction = UNKNOWN;
endcasez

casez memperlakukan ? (dan z) di pola sebagai don't-care. Setiap ? cocok dengan 0 atau 1. Berguna untuk mendekode format instruksi di mana beberapa posisi bit tidak dipakai oleh kelas opcode tertentu.

casex memperluasnya dengan memperlakukan x sebagai don't-care juga. casex berbahaya karena sinyal yang belum diinisialisasi (yang bernilai x di simulasi) cocok dengan setiap case, sehingga menghasilkan perilaku yang mengejutkan. Kebanyakan panduan gaya modern menyarankan casez dan melarang casex.

Di SystemVerilog kamu juga mendapat case inside, versi yang paling rapi dari semuanya (menerima rentang dan daftar), tapi Verilog biasa berhenti di casez.

case vs Rantai if/else if

Kedua konstruksi itu sama-sama bisa mengungkapkan keputusan banyak arah, tapi disintesis menjadi hardware yang berbeda:

  • case adalah percabangan datar. Synthesizer bisa menghasilkan decoder one-hot, pohon mux yang seimbang, atau struktur datar lainnya. Waktu evaluasinya konstan.
  • if/else if adalah rantai prioritas. Synthesizer menghasilkan susunan bertingkat di mana setiap tingkat menambah delay. Lebih lambat secara logaritmik.

Secara fungsi keduanya tumpang tindih. Secara gaya: pakai case setiap kali kondisinya menyangkut nilai satu ekspresi. Pakai if/else if saat ada prioritas yang sebenarnya atau saat kondisinya melibatkan sinyal yang berbeda-beda.

// Better as case:
if      (sel == 2'd0) out = a;
else if (sel == 2'd1) out = b;
else if (sel == 2'd2) out = c;
else                  out = d;

// Better as if/else if:
if      (urgent_event)  next_state = HANDLE_URGENT;
else if (timer_expired) next_state = TIMEOUT;
else if (data_ready)    next_state = PROCESS;
else                    next_state = state;

Tiga kondisi pertama semuanya soal "berapa nilai sel?": case terbaca lebih alami dan disintesis lebih datar. Tiga yang kedua adalah event independen dengan prioritas yang jelas: if/else if lebih cocok.

Selanjutnya

Dokumen terakhir di bab ini, Loop For, membahas for di Verilog dan hal mengejutkan yang terjadi saat kamu memakainya di kode yang bisa disintesis. Setelah itu kita benar-benar masuk ke logika sekuensial dan FSM.

Pertanyaan yang sering diajukan

Apa itu pernyataan case di Verilog?

case (expr) ... endcase adalah konstruksi percabangan banyak arah di Verilog. Ia mengevaluasi ekspresinya sekali lalu menuju cabang mana pun yang cocok. Ini pilihan yang lazim untuk state machine, decoder opcode, pemilih mux, dan apa pun yang memilih di antara beberapa opsi yang saling eksklusif.

Apa perbedaan case, casex, dan casez di Verilog?

case mencocokkan bit demi bit secara persis, termasuk nilai x dan z. casez memperlakukan z (dan ?) di item case sebagai don't-care. casex memperlakukan x dan z sebagai don't-care. Pencocokan don't-care berguna untuk pola opcode yang beberapa posisi bitnya tidak relevan, tapi casex berbahaya di simulasi karena sinyal yang belum diinisialisasi (x) bisa tanpa sengaja cocok dengan setiap case.

Kenapa pernyataan case di Verilog butuh default?

Tanpa default, tool sintesis melihat kemungkinan tidak ada case yang cocok, memutuskan sinyal output harus menahan nilai sebelumnya, lalu menyimpulkan latch yang tidak diinginkan. Cabang default menangani setiap nilai yang tidak cocok, biasanya dengan mengisi output dengan nilai yang aman atau menandai case itu tidak terjangkau dengan penugasan x. Selalu sertakan.

Kapan sebaiknya memakai case dan kapan if-else di Verilog?

Pakai case saat kondisinya saling eksklusif dan percabangannya bergantung pada nilai satu ekspresi: state machine, decoder opcode, pemilih mux. Pakai if/else saat ada urutan prioritas yang sebenarnya atau kondisinya melibatkan sinyal yang berbeda-beda. case disintesis menjadi hardware yang lebih datar dan lebih cepat daripada rantai else if yang panjang.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai