Menu

Penugasan Kontinu Verilog: Pernyataan assign

Cara kerja assign: hubungan yang selalu berlaku yang digambarkannya, apa yang bisa dan tidak bisa digerakkannya, dan pola-pola di mana ia unggul dibandingkan kode prosedural.

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

assign Menggambarkan Kebenaran yang Permanen

Deklarasi wire membuat sebuah sinyal. assign menggambarkan apa yang menggerakkannya. Hubungannya terus-menerus: apa pun yang ada di sisi kanan, sisi kiri sama dengannya, di setiap titik waktu simulasi:

wire y;
assign y = a & b;

Dua hal yang tersirat dari pasangan baris itu:

  • y ada sebagai kabel di dalam rangkaian.
  • y setiap saat bernilai AND bitwise dari a dan b. Ubah salah satu input, dan y mengikuti.

Tidak ada clock dan tidak ada event yang memicu pembaruan. Simulator melihat a atau b berubah, menandai y perlu dihitung ulang, lalu mengevaluasi ulang ekspresinya. Di hardware, ini menjadi beberapa gerbang AND: kombinasional, tanpa state, seketika.

Bentuk Implisit

Kamu bisa menggabungkan deklarasi dan penugasan dalam satu baris:

wire y = a & b;

Itu sama saja dengan dua baris di atas. Berguna untuk kabel lokal yang tidak dipedulikan siapa pun di luar scope ini. Banyak panduan gaya justru lebih menyukai bentuk implisit karena deklarasinya langsung berada di sebelah persamaannya.

Apa yang Bisa Digerakkan assign

Target assign harus bertipe net. Di Verilog biasa, itu artinya wire (atau salah satu kerabatnya yang lebih jarang seperti tri, wand, wor). Targetnya tidak boleh reg. Kalau kamu tidak sengaja mendeklarasikan target sebagai reg:

reg y;
assign y = a & b;   // ERROR: cannot drive reg with assign

Compiler akan memberi tahu. Ubah targetnya menjadi wire, atau pindahkan logikanya ke blok always @(*) di mana reg adalah target yang sah.

Sisi kanan bisa berupa apa pun yang menghasilkan nilai: literal, sinyal, parameter, ekspresi operator, pemanggilan fungsi. Lebar input boleh dicampur; aturan pelebaran standar berlaku.

Kapan Memakai assign vs always

Keduanya bisa menghasilkan logika kombinasional. Pilihannya sebagian besar soal bagaimana kode itu terbaca:

  • assign paling cocok saat hubungannya berupa satu ekspresi. Adder, mux sederhana yang dibuat dengan ?:, mask, bit paritas, apa pun yang bisa ditulis dalam satu baris.
  • always @(*) paling cocok saat kamu butuh pernyataan prosedural. Pernyataan case dengan banyak cabang, if/else if bersarang, apa pun yang terbantu oleh reg perantara yang diberi nama. Kita membahasnya di Blok Always.

Ini mux 4-ke-1 yang sama, ditulis dengan dua cara:

Kedua module disintesis menjadi multiplexer yang pada dasarnya sama. Versi assign hanya satu baris kode; versi always enam baris. Untuk empat cabang selisihnya tipis; untuk enam belas cabang, blok case jelas lebih mudah dibaca.

Pola yang Umum

Logika Kombinasional Biasa

assign sum   = a + b;
assign carry = a[7] & b[7];
assign equal = (data == 8'hFF);

Satu ekspresi, satu wire. Pemakaian assign sehari-hari.

Mux 2-ke-1

assign out = sel ? a : b;

Satu ekspresi kondisional: synthesizer mengubahnya menjadi satu mux 2-ke-1. Cara paling bersih untuk menulis "pilih antara a dan b".

Pengemasan Bit

assign status = {error, overflow, ready, busy, 4'b0};

Concatenation di sisi kanan assign adalah cara mengemas flag ke dalam satu byte status. Hasilnya dihitung dan digerakkan terus-menerus.

Output Tri-State

assign data_pin = output_enable ? data_out : 1'bz;

Saat output_enable bernilai high, gerakkan pin-nya. Saat low, lepaskan ke impedansi tinggi. Ini pola baku di pin chip yang kabelnya mungkin dipakai bersama oleh beberapa penggerak.

Konkurensi: Beberapa Assign Bukan Urutan

Pengingat yang akan terus relevan: beberapa pernyataan assign di module yang sama semuanya berjalan paralel. Mereka bukan urutan:

assign y = a & b;     // exists at all times
assign z = a | b;     // also exists at all times, independently

Urutan di dalam file tidak berpengaruh. Kedua persamaan berlaku bersamaan. Synthesizer bisa saja menaruh gerbang AND di kiri gerbang OR atau di kanannya; itu tidak penting, kedua gerbang bekerja terus-menerus.

Kalau kamu ingin perilaku yang terlihat berurutan, yang kamu butuhkan adalah blok always (dan kemungkinan besar sebuah clock). Itu bab yang lain.

Banyak Penggerak: Pola Bus

Sebuah wire bisa menjadi target lebih dari satu assign, tapi hampir tidak pernah kamu menginginkannya, kecuali untuk bus tri-state. Dua penggerak yang berebut satu kabel menghasilkan perilaku yang tidak terdefinisi:

assign y = a;
assign y = b;   // BAD - two drivers, simulator picks one or x's it out

Pola yang sah: setiap penggerak melepas kabel ke z saat tidak aktif, dan paling banyak satu yang aktif pada satu waktu.

assign bus = device_a_active ? data_from_a : 1'bz;
assign bus = device_b_active ? data_from_b : 1'bz;

Itu berhasil karena pada waktu kapan pun, paling banyak satu dari dua ekspresi ternary itu menghasilkan nilai selain z. Nilai sebenarnya dari kabel itu berasal dari penggerak yang tidak sedang melepas.

Di logika internal, yaitu di mana pun selain pin chip atau bus bersama di dalam chip, satu penggerak untuk setiap wire. Bug karena banyak penggerak sangat menyebalkan saat debug.

Yang Tidak Bisa Dilakukan assign

Ada beberapa hal di mana assign adalah alat yang salah:

  • Penyimpanan. assign menggambarkan hubungan kombinasional; ia tidak bisa menghadirkan flip-flop. Kalau kamu butuh nilai yang diingat dari satu siklus clock ke siklus berikutnya, itu pekerjaan blok always @(posedge clk).
  • Logika prosedural bertahap. Kamu tidak bisa menulis if/else atau case di dalam assign. Yang paling mendekati adalah rantai ?:, yang jadi berantakan setelah lebih dari tiga cabang.
  • Menggerakkan register dari dalam blok prosedural. Target reg butuh penugasan prosedural, bukan assign.

Memahami batasannya membantumu memutuskan kapan harus beralih ke always.

Selanjutnya

Sekarang kamu sudah melihat seluruh sisi struktural Verilog: mendeklarasikan module, membuat instance-nya, dan menyusun logika kombinasional dengan assign. Bab berikutnya masuk ke blok prosedural, yaitu konstruksi initial dan always, di mana waktu dan urutan mulai berpengaruh.

Pertanyaan yang sering diajukan

Apa itu penugasan kontinu di Verilog?

assign target = expression; mendeklarasikan hubungan yang permanen dan terus-menerus: target selalu sama dengan expression. Setiap kali ada sinyal di ekspresi itu yang berubah, simulator mengevaluasi ulang sisi kanan dan memperbarui target. Tidak ada clock, tidak ada event: hubungan itu berlaku di setiap titik waktu.

Apa yang bisa menjadi target assign di Verilog?

assign bisa menggerakkan wire, tapi tidak pernah reg. Targetnya harus bertipe net. Kalau kamu perlu memberi nilai ke sesuatu dari dalam blok always, deklarasikan sebagai reg. Compiler akan menolak assign x = ... kalau x bertipe reg, dan menolak x = ... di dalam always kalau x bertipe wire.

Kapan sebaiknya memakai assign dan kapan blok always?

Pakai assign untuk logika kombinasional sederhana: satu ekspresi masuk, satu sinyal keluar, tanpa perlu if/else. Pakai always @(*) saat logikanya butuh pernyataan prosedural (sebuah case, rantai if/else if, loop for). Keduanya menghasilkan hardware kombinasional; pilihannya soal keterbacaan.

Apakah satu wire boleh punya beberapa assign di Verilog?

Hanya kalau kamu memodelkan bus tri-state di mana setiap penggerak melepas wire ke z saat tidak aktif. Dua assign yang mencoba menggerakkan wire ke nilai pasti pada waktu yang sama menghasilkan konflik (contention): simulator mungkin memilih salah satu, mungkin membuat sinyalnya menjadi X, tergantung tool-nya. Untuk logika kombinasional biasa, satu penggerak untuk setiap wire.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai