Menguasai Blok Always Verilog: Sintaks, Blocking vs Non-Blocking, dan Sambungan SystemVerilog

目次

1. Pengenalan

Apakah peranan blok always dalam Verilog?

Dalam Verilog HDL, bahasa penerangan perkakasan yang digunakan secara meluas dalam reka bentuk litar digital, blok always memainkan peranan penting. Daripada menerangkan tingkah laku perkakasan seperti perisian, Verilog mewakili litar dengan mentakrifkan “di bawah keadaan apa isyarat berubah”. Antara ini, blok always adalah konstruk dasar yang digunakan untuk menerangkan tindakan apa yang perlu dilaksanakan apabila keadaan tertentu berlaku.

Mengapa kita perlukan blok always?

Dalam Verilog, terdapat dua jenis tingkah laku litar utama yang boleh anda terangkan:
  • Logik gabungan : output berubah serta-merta apabila input berubah
  • Logik siri : output berubah selaras dengan isyarat jam atau peristiwa masa
Penetapan assign yang ringkas tidak boleh mengendalikan keadaan kompleks atau elemen ingatan. Inilah di mana blok always masuk. Sebagai contoh, untuk menerangkan percabangan bersyarat atau tingkah laku flip-flop, anda memerlukan blok always dengan struktur kawalan seperti if atau case.

Corak biasa blok always

Blok always mempunyai beberapa corak penggunaan biasa bergantung pada jenis litar yang direka:
  • always @(*) → Digunakan untuk logik gabungan
  • always @(posedge clk) → Logik siri yang dicetuskan pada naik semula jam
  • always @(posedge clk or negedge rst) → Logik siri dengan reset asinkron atau kawalan lebih kompleks
Oleh itu, memahami blok always, sintaks teras Verilog, adalah langkah pertama yang penting untuk pereka perkakasan.

Tujuan artikel ini

Artikel ini menyediakan panduan komprehensif kepada blok always dalam Verilog, meliputi sintaks asas, penggunaan praktikal, kesilapan biasa, dan sambungan SystemVerilog.
  • Belajar cara betul menulis blok always
  • Faham mengapa ralat sintesis berlaku
  • Jelaskan perbezaan antara = dan <=
  • Elakkan kesilapan pemula biasa
Kami bertujuan menjadikannya panduan praktikal dan mudah difahami untuk sesiapa yang mempunyai soalan sedemikian.

2. Sintaks Asas dan Jenis Blok always

Sintaks asas blok always

Dalam Verilog, blok always melaksanakan pernyataan berulang berdasarkan senarai kepekaan khusus. Sintaks asasnya ialah:
always @(sensitivity list)
begin
  // statements
end
Bahagian utama di sini ialah “senarai kepekaan,” yang mentakrifkan isyarat mana yang mencetuskan pelaksanaan apabila ia berubah.

Menggunakan always @(*) untuk logik gabungan

Dalam logik gabungan, output mesti dikemas kini serta-merta setiap kali input berubah. Dalam kes ini, gunakan @(*) sebagai senarai kepekaan.
always @(*) begin
  if (a == 1'b1)
    y = b;
  else
    y = c;
end
Ini bermakna setiap kali a, b, atau c berubah, blok always dilaksanakan dan mengira semula y.

Kelebihan menggunakan @(*)

  • Secara automatik memasukkan semua isyarat yang dirujuk dalam senarai kepekaan
  • Mencegah ketidakpadanan antara hasil simulasi dan sintesis

Menggunakan always @(posedge clk) untuk logik siri

Dalam logik siri, perubahan keadaan berlaku selaras dengan isyarat jam. Dalam kes ini, nyatakan posedge clk dalam senarai kepekaan.
always @(posedge clk) begin
  q <= d;
end
Di sini, nilai d dikunci ke dalam q pada naik semula jam. Pengendali <= mewakili penetapan tidak menyekat, yang merupakan standard untuk logik siri.

posedge vs negedge

  • posedge : dicetuskan pada naik semula
  • negedge : dicetuskan pada turun semula
Pilih tepi yang sesuai bergantung pada keperluan reka bentuk.

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

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

Dengan penerangan ini, q direset serta-merta apabila rst rendah, sebaliknya ia menangkap d pada tepi jam.

Litar Gabungan vs Litar Siri

Jenis LitaralwaysKelaku
Kombinasialways @(*)Keluaran dikemas kini serta‑merta berdasarkan input
Berurutanalways @(posedge clk)Beroperasi selaras dengan jam

3. Jenis Penetapan dalam Blok always

Dua operator penetapan dalam Verilog

Di dalam blok always Verilog, anda boleh menggunakan dua operator penetapan yang berbeza:
  • = : Penetapan blocking
  • <= : Penetapan non-blocking
Salah faham perbezaan ini boleh menyebabkan kelakuan yang tidak dijangka danketidakserasian antara simulasi dan sintesis**, menjadikannya salah satu titik paling penting untuk dipelajari.

Penetapan blocking (=)

Penetapan blocking dilaksanakan secara berurutan, satu pernyataan selepas yang lain, serupa dengan aliran kawalan perisian.
always @(*) begin
  a = b;
  c = a;
end
Di sini, a = b dilaksanakan terlebih dahulu, dan kemudian c = a menggunakan nilai a yang telah dikemas kini. Susunan pernyataan secara langsung mempengaruhi kelakuan logik.

Kes penggunaan biasa

  • Struktur kawalan ( if , case ) dalam logik kombinasi
  • Logik yang tidak memerlukan penyimpanan keadaan

Penetapan non-blocking (<=)

Penetapan non-blocking bermakna semua pernyataan dinilai secara serentak dan dikemas kini bersama, mencerminkan sifat paralel perkakasan.
always @(posedge clk) begin
  a <= b;
  c <= a;
end
Kedua-dua a <= b dan c <= a dinilai pada masa yang sama dan dikemas kini selepas tepi jam. Oleh itu, c menerima nilai a yang sebelumnya.

Kes penggunaan biasa

  • Logik berurutan (daftar, flip-flop)
  • Penyebaran keadaan tepat merentasi pelbagai isyarat

Perbandingan Penetapan Blocking vs Non-blocking

CiriMenyekat (=)Tidak menyekat (<=)
Urutan pelaksanaanBerurutan, satu demi satuDinilai serentak, dikemas kini bersama
Penggunaan biasaLogik kombinasiLogik berurutan
Kemas kini masaSegera diterapkanDiterapkan selepas tepi jam
Kesilapan biasaPenjanaan latch yang tidak diinginiNilai tidak dikemas kini atau disebarkan seperti yang dijangkakan

Apa yang berlaku jika anda mencampurkannya?

Anda harus mengelakkan pencampuran = dan <= dalam blok yang sama atau pada isyarat yang sama. Contohnya:
always @(posedge clk) begin
  a = b;
  a <= c;
end
Kod ini menetapkan a dua kali menggunakan kaedah yang berbeza, menjadikan nilai akhir yang disimpan tidak jelas, yang mungkin kelihatan betul dalam simulasi tetapi gagal dalam perkakasan.

Garis panduan penggunaan

  • Gunakan = dalam blok always @(*) (kombinasi)
  • Gunakan <= dalam blok always @(posedge clk) (berurutan)
Mengikuti peraturan mudah ini membantu mengelakkan banyak kesilapan umum.

4. Perangkap Umum dan Amalan Terbaik dengan Blok always

Kesilapan dalam senarai sensitiviti

Senarai sensitiviti yang tidak betul boleh menyebabkan pepijat tersembunyi

Dalam Verilog, senarai sensitiviti (@(...)) mesti menakan secara eksplisit semua isyarat yang memicu pelaksanaan. Berikut ialah contoh di mana hanya sebahagian isyarat yang disertakan:
always @(a) begin
  if (b)
    y = 1'b1;
  else
    y = 1'b0;
end
Kod ini tidak bertindak balas kepada perubahan pada b. Akibatnya, apabila b berubah, y tidak akan dikemas kini, menyebabkan pepijat.

Penyelesaian: gunakan @(*)

Untuk mengelakkan kehilangan isyarat dalam senarai sensitiviti, gunakan @(*) seperti berikut:
always @(*) begin
  if (b)
    y = 1'b1;
  else
    y = 1'b0;
end
@(*) secara automatik menyertakan semua isyarat yang dirujuk dalam blok, meningkatkan kebolehselenggaraan dan kebolehpercayaan.

Penjanaan latch yang tidak diingini

Ketiadaan cabang if/case menghasilkan latch

Jika tidak semua kes menetapkan nilai, alat sintesis mengandaikan bahawa pembolehubah mesti “menyimpan” nilainya, menghasilkan latch:
always @(*) begin
  if (enable)
    y = d; // y is undefined when enable == 0
end
Walaupun kelihatan baik, latch dimasukkan kerana y tidak dikemas kini apabila enable adalah 0.

Penyelesaian: sentiasa tetapkan nilai

always @(*) begin
  if (enable)
    y = d;
  else
    y = 1'b0; // y is always defined
end
Dengan menetapkan nilai secara eksplisit dalam setiap kes, anda dapat mengelakkan latch yang tidak diingini.

Syarat yang terlalu kompleks

Pernyataan if atau case yang rumit boleh menyebabkan kelakuan tidak ditakrifkan atau logik yang hilang jika tidak semua syarat diliputi.

Kesilapan biasa: tiada 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

Penyelesaian 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
Menambah default memastikan output sentiasa ditakrifkan, meningkatkan ketahanan reka bentuk.

Mengawal pelbagai isyarat dalam satu blok

Apabila mengawal pelbagai isyarat dalam satu blok always yang sama, susunan penugasan dan kes yang terlepas boleh menghasilkan kebergantungan yang tidak diingini. Dalam reka bentuk yang kompleks, pertimbangkan memecah logik kepada beberapa blok always untuk kejelasan dan keselamatan.

Ringkasan perangkap umum

ProblemPuncaSolution
Output tidak dikemas kiniIsyarat yang hilang dalam senarai sensitivitiGunakan @(*) untuk pengesanan automatik
Latch dijanaTidak semua cabang memberikan nilaiSentiasa sertakan else atau default
Kelakuan tidak ditakrifkanPenyataan kes tiada syaratTambah default cawangan
Kawalan yang terlalu kompleksTerlalu banyak isyarat dalam satu blokSila berikan potongan HTML Bahasa Inggeris yang anda ingin terjemahkan ke dalam Bahasa Melayu (Malaysia). Saya akan memecahkannya kepada beberapa blok `always` seperti yang diminta.

5. Sambungan always dalam SystemVerilog

always_comb: untuk logik kombinasi

Gambaran keseluruhan

always_comb berfungsi serupa dengan always @(*) tetapi secara jelas menunjukkan logik kombinasi.
always_comb begin
  y = a & b;
end

Manfaat utama

  • Secara automatik menjana senarai sensitiviti
  • Alat memberi amaran apabila latch yang tidak diingini dijana
  • Mencegah konflik dengan pembolehubah yang telah ditakrifkan sebelumnya

Contoh (Verilog vs SystemVerilog)

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

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

always_ff: untuk logik berurutan (flip‑flop)

Gambaran keseluruhan

always_ff direka untuk logik berurutan yang dipacu jam, memerlukan syarat tepi yang jelas 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 membenarkan penugasan tidak‑blok ( <= )
  • Alat memeriksa ketepatan senarai sensitiviti
  • Kebolehbacaan kod meningkat kerana jelas berurutan

always_latch: untuk logik berasaskan latch

Gambaran keseluruhan

always_latch digunakan apabila anda secara sengaja menggambarkan kelakuan latch. Walau bagaimanapun, dalam kebanyakan reka bentuk, latch yang tidak diingini harus dielakkan.
always_latch begin
  if (enable)
    q = d;
end

Perkara yang perlu diingat

  • Jika beberapa cabang melangkau penugasan, latch akan dicipta secara eksplisit
  • Hanya gunakan apabila latch memang diperlukan

Ringkasan penggunaan SystemVerilog

ConstructTujuanEquivalent in VerilogCiri-ciri
always_combLogik kombinasialways @(*)Senarai sensitiviti automatik, pengesanan latch
always_ffSeliparalways @(posedge clk)Penetapan selaras jam, lebih selamat
always_latchPenguncialways @(*)Reka bentuk latch eksplisit, pengesanan ralat

SystemVerilog semakin menjadi piawaian

Dalam pembangunan moden, konstruksi SystemVerilog semakin disarankan untuk kebolehbacaan dan keselamatan. Dengan pemeriksaan sintaks yang lebih baik, penggunaan always_ff dan always_comb membantu mengelakkan isu “kelihatan betul tetapi tidak berfungsi”. Terutama dalam projek berskala besar atau berpasukan, konstruksi yang jelas menjadikan niat reka bentuk lebih terang, meningkatkan semakan kod dan kebolehselenggaraan.

6. Soalan Lazim: Soalan Umum Mengenai Blok always

Bahagian ini menjawab soalan-soalan yang kerap ditanya mengenai blok always dalam Verilog dan SystemVerilog, menumpukan pada kebimbangan praktikal yang sering timbul dalam projek reka bentuk. Ia merangkumi isu-isu umum bagi peringkat pemula hingga pertengahan yang dilihat dalam pembangunan dunia sebenar.

S1. Haruskah saya menggunakan if atau case di dalam blok always?

J. Ia bergantung pada bilangan dan kerumitan syarat:
  • Untuk 2–3 syarat mudah → if lebih mudah dibaca
  • Untuk pelbagai keadaan berbeza → case lebih jelas dan menyatakan niat dengan lebih baik
Menggunakan case juga menegakkan jangkaan untuk meliputi semua kes yang mungkin, membantu mengurangkan kesilapan.

S2. Apa yang berlaku jika saya terlepas isyarat dalam senarai sensitiviti?

J. Jika senarai sensitiviti tidak lengkap, beberapa perubahan isyarat tidak akan memicu blok, menyebabkan output menjadi lapuk. Ini boleh menyebabkan perbezaan antara simulasi dan sintesis. Untuk mengelakkan ini, sentiasa gunakan @(*) atau always_comb dalam SystemVerilog.

S3. Mengapa latch yang tidak diingini muncul dalam reka bentuk saya?

J. Jika pernyataan if atau case tidak menugaskan nilai kepada pembolehubah dalam setiap laluan yang mungkin, alat sintesis menganggap nilai tersebut perlu dipertahankan, dan mencipta latch.

Contoh buruk:

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

Penyelesaian:

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

S4. Bolehkah saya mencampur = dan <= dalam blok yang sama?

A. Secara umum, tidak. Campuran penugasan blok dan bukan blok dalam blok yang sama, terutamanya pada isyarat yang sama, boleh menyebabkan simulasi berfungsi tetapi perkakasan gagal.
  • Logik kombinasional → gunakan = (blok)
  • Logik sekuensial → gunakan <= (bukan blok)

Peraturan ibu jari:

Sentiasa gunakan gaya penugasan yang konsisten setiap isyarat.

Q5. Apakah perbezaan antara always_ff dan always @(posedge clk)?

A. Secara fungsional, ia bertindak sama, tetapi always_ff lebih selamat dan lebih mudah dibaca.
Perbandinganalways @(posedge clk)always_ff
SensitivitiMesti ditentukan secara manualDiperiksa secara automatik
Ralat penugasanPenetapan blok mungkin dapat dikompilPenetapan tidak sah menyebabkan ralat
KebolehbacaanMungkin mengaburkan niat litarJelas menunjukkan logik berurutan

Q6. Adakah boleh mengawal pelbagai isyarat dalam satu blok always?

A. Ia mungkin, tetapi jika terlalu banyak isyarat disertakan, penyahpepijatan dan penyelenggaraan menjadi sukar. Pertimbangkan memisahkan kepada pelbagai blok apabila:
  • Setiap output bertindak secara bebas
  • Anda campur logik sinkron dan asinkron

Q7. Apakah yang berlaku jika saya gunakan <= dalam logik kombinasional?

A. Ia mungkin masih berfungsi dalam simulasi, tetapi semasa sintesis, ia boleh mencipta logik tidak dijangka. Patuh kepada penugasan blok (=) untuk logik kombinasional.

7. Kesimpulan

Blok always adalah asas reka bentuk Verilog

Dalam reka bentuk perkakasan Verilog, blok always adalah alat kuat yang membolehkan anda menerangkan litar kombinasional dan sekuensial. Ia bukan sahaja meluaskan kemungkinan reka bentuk anda tetapi juga menjelaskan aliran kawalan dan masa. Untuk pemula dan profesional, always adalah pengetahuan penting.

Pengambilan utama

  • Perbezaan dan penggunaan always @(*) vs always @(posedge clk)
  • Perbezaan antara = (blok) dan <= (bukan blok) penugasan
  • Cara mengelak kesilapan biasa seperti penjanaan latch dan senarai kepekaan tidak lengkap
  • Sambungan SystemVerilog ( always_comb , always_ff , always_latch ) untuk reka bentuk lebih selamat
  • Jawapan praktikal kepada soalan dunia sebenar biasa (FAQ)

Ketepatan menentukan kualiti

Dalam penerangan perkakasan, apa yang anda tulis adalah tepat apa yang dilaksanakan. Walaupun kesilapan kecil boleh menjadi kesilapan perkakasan. Oleh kerana always adalah pusat kepada tingkah laku, ketepatan, jenis penugasan yang betul, dan liputan keadaan lengkap adalah kritikal.

Langkah seterusnya: maju ke reka bentuk tahap lebih tinggi

Setelah anda menguasai blok always, anda boleh terus ke:
  • Reka bentuk Finite State Machine (FSM)
  • Pipelining dan arkitektur streaming
  • Membangunkan IP cores dan pelaksanaan FPGA
Anda juga boleh meluaskan kemahiran anda dengan belajar SystemVerilog dan VHDL, menjadikan anda boleh menyesuaikan diri merentasi persekitaran reka bentuk yang berbeza.

Fikiran akhir untuk pereka perkakasan

Dalam reka bentuk litar, ia bukan hanya tentang “membuatnya berfungsi.” Apa yang diperlukan adalah tingkah laku betul, ketahanan untuk perubahan masa depan, dan kejelasan untuk pembangunan pasukan. Melalui artikel ini, kami harap anda memperoleh pengetahuan asas blok always dan penghargaan untuk amalan reka bentuk selamat dan boleh dipercayai.