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:
yada sebagai kabel di dalam rangkaian.ysetiap saat bernilai AND bitwise dariadanb. Ubah salah satu input, danymengikuti.
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:
assignpaling 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. Pernyataancasedengan banyak cabang,if/else ifbersarang, apa pun yang terbantu olehregperantara 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.
assignmenggambarkan hubungan kombinasional; ia tidak bisa menghadirkan flip-flop. Kalau kamu butuh nilai yang diingat dari satu siklus clock ke siklus berikutnya, itu pekerjaan blokalways @(posedge clk). - Logika prosedural bertahap. Kamu tidak bisa menulis
if/elseataucasedi dalamassign. Yang paling mendekati adalah rantai?:, yang jadi berantakan setelah lebih dari tiga cabang. - Menggerakkan register dari dalam blok prosedural. Target
regbutuh penugasan prosedural, bukanassign.
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.