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 kombinatorialalwaysposedge clk) → Logika sekuensial yang dipicu pada tepi naik clockalways @(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 naiknegedge : 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 Sirkuit | always | Perilaku |
|---|
| Kombinasi | always @(*) | Output diperbarui segera berdasarkan masukan |
| Berurutan | always @(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
| Fitur | Memblokir (=) | Non-blokir (<=) |
|---|
| Urutan eksekusi | Berurutan, satu demi satu | Dievaluasi secara bersamaan, diperbarui bersama |
| Penggunaan umum | Logika kombinatorial | Logika berurutan |
| Perbarui waktu | Segera diterapkan | Diterapkan setelah tepi jam |
| Jebakan umum | Generasi latch yang tidak diinginkan | Nilai 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
| Problem | Penyebab | Solution |
|---|
| Output tidak diperbarui | Sinyal yang hilang dalam daftar sensitivitas | Gunakan @(*) untuk deteksi otomatis |
| Latch dihasilkan | Tidak semua cabang menetapkan nilai | Selalu sertakan else atau default |
| Perilaku tak terdefinisi | Pernyataan case tidak memiliki kondisi | Tambahkan default cabang |
| Kontrol yang terlalu kompleks | Terlalu banyak sinyal dalam satu blok | alwaysalwaysalways |
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
| Construct | Tujuan | Equivalent in Verilog | Fitur |
|---|
always_comb | Logika kombinatorial | always @(*) | Daftar sensitivitas otomatis, deteksi latch |
always_ff | Sandal jepit | always @(posedge clk) | Penugasan yang lebih aman, sinkron jam |
always_latch | Pengunci | always @(*) | 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.| Perbandingan | always @(posedge clk) | always_ff |
|---|
| Sensitivitas | Harus ditentukan secara manual | Diperiksa secara otomatis |
| Kesalahan penugasan | Penugasan blocking mungkin dapat dikompilasi | Penugasan tidak valid menyebabkan kesalahan |
| Keterbacaan | Mungkin mengaburkan maksud rangkaian | Jelas 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.