Menguasai Blok Always pada Verilog: Sintaks, Blocking vs Non-Blocking, serta Ekstensi SystemVerilog

目次

1. Pendahuluan

Apa peran blok always dalam Verilog?

Dalam Verilog HDL, bahasa deskripsi perangkat keras yang banyak digunakan dalam desain sirkuit digital, blok always memainkan peran penting. Alih‑alih mendeskripsikan perilaku perangkat keras seperti perangkat lunak, Verilog merepresentasikan rangkaian dengan mendefinisikan “di bawah kondisi apa sinyal berubah”. Di antara kondisi‑kondisi tersebut, blok always adalah konstruksi dasar yang digunakan untuk mendeskripsikan tindakan apa yang harus dijalankan ketika kondisi tertentu terjadi.

Mengapa kita memerlukan blok always?

Dalam Verilog, ada dua jenis utama perilaku sirkuit yang dapat Anda deskripsikan:
  • Logika kombinatorial : output berubah segera ketika input berubah
  • Logika sekuensial : output berubah sinkron dengan sinyal clock atau peristiwa timing
Pernyataan assign sederhana tidak dapat menangani kondisi kompleks atau elemen memori. Di sinilah blok always berperan. Sebagai contoh, untuk mendeskripsikan percabangan kondisional atau perilaku flip‑flop, Anda memerlukan blok always dengan struktur kontrol seperti if atau case.

Pola umum blok always

Blok always memiliki beberapa pola penggunaan umum tergantung pada jenis sirkuit yang dirancang:
  • always @(*) → Digunakan untuk logika kombinatorial
  • alwaysposedge clk) → Logika sekuensial yang dipicu pada tepi naik clock
  • always @(posedge clk or negedge rst) → Logika sekuensial dengan reset asinkron atau kontrol yang lebih kompleks
Dengan demikian, memahami blok always, sintaks inti Verilog, adalah langkah pertama yang penting bagi perancang perangkat keras.

Tujuan artikel ini

Artikel ini memberikan panduan komprehensif tentang blok always dalam Verilog, mencakup sintaks dasar, penggunaan praktis, jebakan umum, dan ekstensi SystemVerilog.
  • Pelajari cara menulis blok always yang benar
  • Pahami mengapa kesalahan sintesis terjadi
  • Klarifikasi perbedaan antara = dan <=
  • Hindari kesalahan pemula yang umum
Kami bertujuan menjadikan panduan ini praktis dan mudah dipahami bagi siapa saja yang memiliki pertanyaan tersebut.

2. Sintaks Dasar dan Jenis Blok always

Sintaks dasar blok always

Dalam Verilog, sebuah blok always mengeksekusi pernyataan secara berulang berdasarkan daftar sensitivitas tertentu. Sintaks dasarnya adalah:
always @(sensitivity list)
begin
  // statements
end
Bagian kunci di sini adalah “daftar sensitivitas,” yang menentukan sinyal mana yang memicu eksekusi ketika berubah.

Menggunakan always @(*) untuk logika kombinatorial

Pada logika kombinatorial, output harus diperbarui segera setiap kali input berubah. Dalam kasus ini, gunakan @(*) sebagai daftar sensitivitas.
always @(*) begin
  if (a == 1'b1)
    y = b;
  else
    y = c;
end
Artinya, setiap kali a, b, atau c berubah, blok always dijalankan dan menghitung ulang y.

Keuntungan menggunakan @(*)

  • Secara otomatis menyertakan semua sinyal yang direferens dalam daftar sensitivitas
  • Mencegah ketidaksesuaian antara hasil simulasi dan sintesis

Menggunakan always @(posedge clk) untuk logika sekuensial

Pada logika sekuensial, perubahan status terjadi sinkron dengan sinyal clock. Dalam kasus ini, tentukan posedge clk dalam daftar sensitivitas.
always @(posedge clk) begin
  q <= d;
end
Di sini, nilai d ditangkap ke dalam q pada tepi naik clock. Operator <= mewakili penugasan non‑blocking, yang merupakan standar untuk logika sekuensial.

posedge vs negedge

  • posedge : dipicu pada tepi naik
  • negedge : dipicu pada tepi turun
Pilih tepi yang sesuai tergantung pada kebutuhan desain.

always @(posedge clk or negedge rst) dengan reset asinkron

Pada rangkaian yang lebih kompleks, fungsi reset sering diperlukan. Sebuah blok dengan reset asinkron dapat ditulis sebagai:
always @(posedge clk or negedge rst) begin
  if (!rst)
    q <= 1'b0;
  else
    q <= d;
end

Dengan deskripsi ini, q langsung di‑reset ketika rst rendah, jika tidak ia menangkap d pada tepi clock.

Logika Kombinatorial vs Sekuensial

Jenis SirkuitalwaysPerilaku
Kombinasialways @(*)Output diperbarui segera berdasarkan masukan
Berurutanalways @(posedge clk)Beroperasi sinkron dengan jam

3. Jenis Penugasan dalam Blok always

Dua operator penugasan dalam Verilog

Di dalam blok always Verilog, Anda dapat menggunakan dua operator penugasan yang berbeda:
  • = : Penugasan blocking
  • <= : Penugasan non-blocking
Salah paham perbedaan ini dapat menyebabkan perilaku yang tidak terduga dan ketidaksesuaian antara simulasi dan sintesis, menjadikannya salah satu poin terpenting untuk dipelajari.

Penugasan blocking (=)

Penugasan blocking dieksekusi secara berurutan, satu perny setelah yang lain, mirip dengan alur kontrol perangkat lunak.
always @(*) begin
  a = b;
  c = a;
end
Di sini, a = b dieksekusi pertama, dan kemudian c = a menggunakan nilai a yang telah diperbarui. Urutan pernyataan secara langsung memengaruhi perilaku logika.

Kasus penggunaan umum Struktur kontrol ( if , case ) dalam logika kombinasi*

  • Logika yang tidak memerlukan penyimpanan status

Penugasan non-blocking (<=)

Penugasan non-blocking berarti semua pernyataan dievaluasi secara bersamaan dan diperbarui bersama, mencerminkan sifat paralel perangkat keras.
always @(posedge clk) begin
  a <= b;
  c <= a;
end
Baik a <= b maupun c <= a dievaluasi pada saat yang sama dan diperbarui setelah tepi clock. Oleh karena itu, c menerima nilai sebelumnya dari a.

Kasus penggunaan umum

  • Logika berurutan (register, flip-flop)
  • Propagasi status yang akurat di antara banyak sinyal

Perbandingan Penugasan Blocking vs Non-blocking

FiturMemblokir (=)Non-blokir (<=)
Urutan eksekusiBerurutan, satu demi satuDievaluasi secara bersamaan, diperbarui bersama
Penggunaan umumLogika kombinatorialLogika berurutan
Perbarui waktuSegera diterapkanDiterapkan setelah tepi jam
Jebakan umumGenerasi latch yang tidak diinginkanNilai tidak diperbarui atau disebarkan seperti yang diharapkan

Apa yang terjadi jika Anda mencampurnya?

Anda harus menghindari mencampur = dan <= dalam blok yang sama atau pada sinyal yang sama. Misalnya:
always @(posedge clk) begin
  a = b;
  a <= c;
end
Kode ini menugaskan ke a dua kali dengan metode yang berbeda, membuat nilai akhir yang disimpan ambigu, yang mungkin tampak benar dalam simulasi tetapi gagal di perangkat keras.

Pedoman penggunaan

  • Gunakan = di dalam blok always @(*) (kombinasi)
  • Gunakan <= di dalam blok always @(posedge clk) (berurutan)
Mengikuti aturan sederhana ini membantu mencegah banyak kesalahan umum.

4. Kesalahan Umum dan Praktik Terbaik dengan Blok always

Kesalahan pada daftar sensitivitas

Daftar sensitivitas yang salah dapat menyebabkan bug tersembunyi

Dalam Verilog, daftar sensitivitas (@(...)) harus secara eksplisit mencakup semua sinyal yang memicu eksekusi. Berikut contoh di mana hanya sebagian sin yang dimasukkan:
always @(a) begin
  if (b)
    y = 1'b1;
  else
    y = 1'b0;
end
Kode ini tidak merespon perubahan pada b. Akibatnya, ketika b berubah, y tidak akan diperbarui, menyebabkan bug.

Solusi: gunakan @(*)

Untuk menghindari kehilangan sinyal dalam daftar sensitivitas, gunakan @(*) sebagai berikut:
always @(*) begin
  if (b)
    y = 1'b1;
  else
    y = 1'b0;
end
@(*) secara otomatis mencakup semua sinyal yang direferensikan dalam blok, meningkatkan baik pemeliharaan maupun keandalan.

Generasi latch yang tidak diinginkan

Cabang if/case yang hilang menghasilkan latch

Jika tidak semua kasus menugaskan nilai, alat sintesis menyimpulkan bahwa variabel harus “menahan” nilainya, menghasilkan latch:
always @(*) begin
  if (enable)
    y = d; // y is undefined when enable == 0
end
Meskipun terlihat baik, latch disisipkan karena y tidak diperbarui ketika enable bernilai 0.

Solusi: selalu menugaskan nilai

always @(*) begin
  if (enable)
    y = d;
  else
    y = 1'b0; // y is always defined
end
Dengan menugaskan nilai secara eksplisit di setiap kasus, Anda dapat mencegah latch yang tidak diinginkan.

Kondisional yang terlalu kompleks

Pernyataan if atau case yang rumit dapat menyebabkan perilaku tidak terdefinisi atau logika yang hilang jika tidak semua kondisi tercakup.

Kesalahan umum: tidak ada default dalam pernyataan case

always @(*) begin
  case(sel)
    2'b00: y = a;
    2'b01: y = b;
    2'b10: y = c;
    // 2'b11 not handled → y may be undefined
  endcase
end

Solusi: tambahkan klausa default

always @(*) begin
  case(sel)
    2'b00: y = a;
    2'b01: y = b;
    2'b10: y = c;
    default: y = 1'b0; // safety net
  endcase
end
Menambahkan default memastikan bahwa output selalu terdefinisi, meningkatkan ketahanan desain.

Mengendalikan beberapa sinyal dalam satu blok

Saat mengendalikan beberapa sinyal dalam satu blok always, urutan penugasan dan kasus yang hilang dapat menciptakan ketergantungan yang tidak diinginkan. Pada desain yang kompleks, pertimbangkan memisahkan logika ke dalam beberapa blok always untuk kejelasan dan keamanan.

Ringkasan jebakan umum

ProblemPenyebabSolution
Output tidak diperbaruiSinyal yang hilang dalam daftar sensitivitasGunakan @(*) untuk deteksi otomatis
Latch dihasilkanTidak semua cabang menetapkan nilaiSelalu sertakan else atau default
Perilaku tak terdefinisiPernyataan case tidak memiliki kondisiTambahkan default cabang
Kontrol yang terlalu kompleksTerlalu banyak sinyal dalam satu blokalwaysalwaysalways

5. Ekstensi always dalam SystemVerilog

always_comb: untuk logika kombinatorial

Ikhtisar

always_comb bekerja serupa dengan always @(*) tetapi secara eksplisit menunjukkan logika kombinatorial.
always_comb begin
  y = a & b;
end

Manfaat utama

  • Secara otomatis menghasilkan daftar sensitivitas
  • Alat memperingatkan ketika latch yang tidak diinginkan terinferensi
  • Mencegah konflik dengan variabel yang telah didefinisikan sebelumnya

Contoh (Verilog vs SystemVerilog)

// Verilog
always @(*) begin
  y = a | b;
end

// SystemVerilog
always_comb begin
  y = a | b;
end

always_ff: untuk logika sekuensial (flip-flop)

Ikhtisar

always_ff dirancang untuk logika sekuensial yang digerakkan oleh clock, memerlukan kondisi tepi eksplisit seperti posedge clk atau negedge rst.
always_ff @(posedge clk or negedge rst_n) begin
  if (!rst_n)
    q <= 1'b0;
  else
    q <= d;
end

Manfaat utama

  • Hanya mengizinkan penugasan non-blocking ( <= )
  • Alat memeriksa kebenaran daftar sensitivitas
  • Keterbacaan kode meningkat karena jelas bersifat sekuensial

always_latch: untuk logika berbasis latch

Ikhtisar

always_latch digunakan ketika Anda secara sengaja menggambarkan perilaku latch. Namun, pada kebanyakan desain, latch yang tidak diinginkan harus dihindari.
always_latch begin
  if (enable)
    q = d;
end

Hal yang perlu dicatat

  • Jika beberapa cabang melewatkan penugasan, latch secara eksplisit dibuat
  • Gunakan hanya ketika latch memang diperlukan### Ringkasan penggunaan SystemVerilog
ConstructTujuanEquivalent in VerilogFitur
always_combLogika kombinatorialalways @(*)Daftar sensitivitas otomatis, deteksi latch
always_ffSandal jepitalways @(posedge clk)Penugasan yang lebih aman, sinkron jam
always_latchPenguncialways @(*)Desain latch eksplisit, deteksi kesalahan

SystemVerilog menjadi standar

Dalam pengembangan modern, konstruksi SystemVerilog semakin direkomendasikan untuk keterbacaan dan keamanan. Dengan pemeriksaan sintaks yang lebih baik, penggunaan always_ff dan always_comb membantu mencegah masalah “terlihat benar tetapi tidak berfungsi”. Terutama dalam proyek berskala besar atau berbasis tim, konstruksi eksplisit membuat maksud desain menjadi jelas, meningkatkan tinjauan kode dan pemeliharaan.

6. FAQ: Pertanyaan Umum tentang Blok always

Bagian ini menjawab pertanyaan yang sering diajukan tentang blok always dalamilog dan SystemVerilog, berfokus pada kekhawatiran praktis yang sering muncul dalam proyek desain. Ini mencakup masalah umum bagi pemula hingga menengah yang terlihat dalam pengembangan dunia nyata.

Q1. Haruskah saya menggunakan if case di dalam blok always?

A. Itu tergantung pada jumlah dan kompleksitas kondisi:
  • Untuk 2–3 kondisi sederhana → if lebih mudah dibaca
  • Untuk banyak keadaan yang berbeda → case lebih jelas dan mengekspresikan maksud dengan lebih baik
Menggunakan case juga menegakkan harapan untuk mencakup semua kemungkinan kasus, membantu mengurangi kesalahan.

Q2. Apa yang terjadi jika saya melewatkan sinyal dalam daftar sensitivitas?

A. Jika daftar sensitivitas tidak lengkap, beberapa perubahan sinyal tidak akan memicu blok, sehingga output menjadi usang. Ini dapat menyebabkan ketidaksesuaian simulasi vs sintesis. Untuk mencegahnya, selalu gunakan @(*) atau SystemVerilog always_comb.

Q3. Mengapa latch yang tidak diinginkan muncul dalam desain saya?

A. Jika pernyataan if atau case tidak menugaskan nilai ke sebuah variabel dalam setiap jalur yang mungkin, alat sintesis menginferensikan bahwa nilai harus dipertahankan, dan membuat latch.

Contoh buruk:

always @(*) begin
  if (en)
    y = d; // y is held when en == 0
end

Solusi:

always @(*) begin
  if (en)
    y = d;
  else
    y = 1'b0; // always assigned
end

Q4. Bisakah saya mencampur = dan <= dalam blok yang sama?

A. Secara umum, tidak. Mencampur penugasan blocking dan non‑blocking dalam blok yang sama, terutama pada sinyal yang sama, dapat menyebabkan simulasi berhasil tetapi perangkat keras gagal.
  • Logika kombinatorial → gunakan = (blocking)
  • Logika sekvensial → gunakan <= (non‑blocking)

Aturan praktis:

Selalu gunakan gaya penugasan yang konsisten per sinyal.

Q5. Apa perbedaan antara always_ff dan always @(posedge clk)?

A. Secara fungsional, keduanya berperilaku sama, tetapi always_ff lebih aman dan lebih mudah dibaca.
Perbandinganalways @(posedge clk)always_ff
SensitivitasHarus ditentukan secara manualDiperiksa secara otomatis
Kesalahan penugasanPenugasan blocking mungkin dapat dikompilasiPenugasan tidak valid menyebabkan kesalahan
KeterbacaanMungkin mengaburkan maksud rangkaianJelas menunjukkan logika berurutan

Q6. Apakah boleh mengendalikan beberapa sinyal dalam satu blok always?

A. Itu memungkinkan, tetapi jika terlalu banyak sinyal yang dimasukkan, debugging dan pemeliharaan menjadi sulit. Pertimbangkan untuk memecah menjadi beberapa blok ketika:
  • Setiap output berperilaku secara independen
  • Anda mencampur logika sinkron dan asinkron

Q7. Apa yang terjadi jika saya menggunakan <= dalam logika kombinatorial?

A. Itu mungkin masih berfungsi dalam simulasi, tetapi selama sintesis, dapat menghasilkan logika yang tidak terduga. Tetap gunakan penugasan blocking (=) untuk logika kombinatorial.

7. Kesimpulan

Blok always adalah fondasi desain Verilog

Dalam desain perangkat keras Verilog, blok always adalah alat yang kuat yang memungkinkan Anda mendeskripsikan rangkaian kombinatorial maupun sekvensial. Ini tidak hanya memperluas kemungkinan desain Anda tetapi juga memperjelas alur kontrol dan timing. Baik bagi pemula maupun profesional, always adalah pengetahuan penting.

Poin-poin penting

  • Perbedaan dan penggunaan always @(*) vs always @(posedge clk)
  • Perbedaan antara penugasan = (blocking) dan <= (non‑blocking)
  • Cara menghindari kesalahan umum seperti pembuatan latch dan daftar sensitivitas yang tidak lengkap
  • Ekstensi SystemVerilog (always_comb, always_ff, always_latch) untuk desain yang lebih aman
  • Jawaban praktis untuk pertanyaan umum dunia nyata (FAQ)

Presisi menentukan kualitas

Dalam deskripsi perangkat keras, apa yang Anda tulis persis apa yang diimplementasikan. Bahkan kesalahan kecil dapat menjadi bug perangkat keras. Karena always menjadi pusat perilaku, ketepatan, tipe penugasan yang benar, dan cakupan kondisi yang lengkap sangat penting.

Langkah selanjutnya: maju ke desain tingkat tinggi

Setelah Anda menguasai blok always, Anda dapat melanjutkan ke:
  • Desain Finite State Machine (FSM)
  • Arsitektur pipelining dan streaming
  • Pengembangan IP core dan implementasi FPGA
Anda juga dapat memperluas keahlian dengan mempelajari SystemVerilog dan VHDL, menjadikan Anda fleksibel di berbagai lingkungan desain.

Pemikiran akhir untuk perancang perangkat keras

Dalam desain sirkuit, bukan hanya tentang “membuatnya berfungsi.” Yang dibutuhkan adalah perilaku yang benar, ketahanan untuk perubahan di masa depan, dan kejelasan untuk pengembangan tim. Melalui artikel ini, kami berharap Anda memperoleh pengetahuan dasar tentang blok always serta apresiasi terhadap praktik desain yang aman dan dapat diandalkan.