Menu

Verilog Continuous Assignment: assign İfadesi

assign nasıl çalışır - tanımladığı her zaman doğru olan ilişki, neyi sürebilir, neyi süremez ve prosedürel kodla kıyaslandığında parladığı kalıplar.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

assign Kalıcı Bir Gerçeği Tanımlar

Bir wire tanımı bir sinyal oluşturur. Bir assign, onu neyin sürdüğünü tanımlar. İlişki süreklidir: sağ tarafta ne varsa, sol taraf ona eşittir, simüle edilen zamanın her noktasında:

wire y;
assign y = a & b;

Bu çift satırın ima ettiği iki şey:

  • y, devrede bir wire olarak var olur.
  • y her zaman a ve b'nin bitwise AND'idir. Herhangi bir girişi değiştir ve y takip eder.

Güncellemeyi tetikleyen bir saat veya olay yoktur. Simülatör a veya b'nin değiştiğini görür, y'yi kirli olarak işaretler ve ifadeyi tekrar değerlendirir. Donanımda bu birkaç AND gate'ine eşlenir: kombinasyonel, durumsuz, anında.

Örtük Form

Tanımlamayı ve atamayı tek satırda birleştirebilirsin:

wire y = a & b;

Bu, yukarıdaki iki satırla aynıdır. Bu kapsam dışındaki kimsenin umurunda olmayan inline wire'lar için kullanışlıdır. Birçok stil kılavuzu aslında örtük formu tercih eder çünkü tanımlamayı denkleminin yanına koyar.

assign Neyi Sürebilir

assign hedefi bir net tipi olmalıdır - düz Verilog'da bu wire'dır (veya tri, wand, wor gibi daha nadir kuzenlerinden biri). Bir reg olamaz. Hedefini yanlışlıkla reg olarak tanımladıysan:

reg y;
assign y = a & b;   // HATA: reg, assign ile sürülemez

Derleyici sana söyleyecektir. Ya hedefi wire'a değiştir, ya da mantığı reg'in yasal hedef olduğu bir always @(*) bloğuna taşı.

Sağ taraf bir değere değerlendirilen herhangi bir şey olabilir: literaller, sinyaller, parametreler, operatör ifadeleri, fonksiyon çağrıları. Birden çok giriş genişliğini karıştırabilir; standart genişletme kuralları uygulanır.

assign vs always Ne Zaman Kullanılır

İkisi de kombinasyonel mantık üretebilir. Seçim çoğunlukla kodun nasıl okunduğuyla ilgili:

  • İlişki tek bir ifade olduğunda assign en iyisidir. Adder'lar, ?: ile yapılan basit mux'lar, mask'ler, parity bit'leri, tek satırda yazabileceğin her şey.
  • Prosedürel ifadelere ihtiyacın olduğunda always @(*) en iyisidir. Çok yönlü case ifadeleri, iç içe if/else if, isimli ara reg'lerden fayda gören her şey. Bunu Always Block bölümünde kapsıyoruz.

İşte aynı 4-to-1 mux iki şekilde yazılmış:

Her iki modül de aslında aynı multiplexer'a sentezlenir. assign sürümü bir satır kod; always sürümü altı. Dört case için yakın; on altı case için case bloğu açıkça okumak için daha kolaydır.

Yaygın Kalıplar

Düz Kombinasyonel Mantık

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

Bir ifade, bir wire. assign'ın ekmek ve tereyağı.

2-to-1 Mux

assign out = sel ? a : b;

Tek koşullu ifade - sentezleyici bunu tek bir 2-to-1 mux'a çevirir. "a ve b arasında seç"in en temiz yazımı.

Bit Paketleme

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

Bir assign'ın sağında concatenation, flag'leri bir status byte'ına paketlemenin yoludur. Sonuç sürekli olarak hesaplanır ve sürülür.

Tri-State Çıkış

assign data_pin = output_enable ? data_out : 1'bz;

output_enable yüksek olduğunda pin'i sür. Düşük olduğunda yüksek empedansa bırak. Bu, birden çok sürücünün bir wire'ı paylaşabileceği chip pin'lerindeki kanonik kalıptır.

Eşzamanlılık: Birden Çok Assign Sıralı Değildir

Sürekli alakalı kalan bir hatırlatma: aynı modüldeki birden çok assign ifadesi hepsi paralel olarak çalışır. Bir dizi değildirler:

assign y = a & b;     // her zaman var olur
assign z = a | b;     // ayrıca her zaman var olur, bağımsız olarak

Dosyadaki sıra alakasızdır. Her iki denklem de aynı anda doğrudur. Sentezleyici AND gate'ini OR gate'inin soluna veya sağına yerleştirebilir; önemli değil, her iki gate de sürekli çalışır.

Sıralı görünümlü davranış istiyorsan, bir always bloğuna (ve muhtemelen bir saate) uzanıyorsundur. Bu farklı bir bölüm.

Birden Çok Sürücü: Bus Kalıbı

Bir wire'ın birden fazla assign'ı hedefleyebilir, ama tri-state bus'lar dışında bunu neredeyse hiç istemezsin. Bir wire için savaşan iki sürücü tanımsız davranış üretir:

assign y = a;
assign y = b;   // KÖTÜ - iki sürücü, simülatör birini seçer veya x'ler

Meşru kalıp: her sürücü inaktif olduğunda z'ye bırakır ve herhangi bir anda en fazla biri aktiftir.

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

Bu çalışır çünkü herhangi bir anda iki ternary'den en fazla biri z olmayan bir değer üretir. Wire'ın gerçek değeri hangi sürücünün bırakmadığıdır.

Dahili mantıkta - bir chip pin'i veya paylaşılan on-chip bus olmayan her yerde - wire başına bir sürücü. Çok sürücülü hatalar debug etmesi nahoştur.

assign'ın Yapamayacakları

assign'ın yanlış araç olduğu bazı şeyler:

  • Depolama. assign kombinasyonel ilişkileri tanımlar; bir flip-flop tanıtamaz. Bir değerin saat döngüleri arasında hatırlanması gerekiyorsa, bu bir always @(posedge clk) bloğudur.
  • Çok adımlı prosedürel mantık. Bir assign içinde if/else veya case yazamazsın. En yakın elde ettiğin zincirlenmiş ?:'dir, ki bu üç daldan sonra çirkinleşir.
  • Bir prosedürel bloğun içinden register'ları sürmek. reg hedefleri prosedürel atama gerektirir, assign değil.

Sınırları bilmek, ne zaman always'e geçeceğine karar verme yoludur.

Sırada Ne Var

Artık Verilog'un yapısal tarafının tamamını gördün: modülleri tanımlamak, onları instantiate etmek ve kombinasyonel mantığı assign ile bağlamak. Bir sonraki bölüm prosedürel bloklara geçer - zamanın ve sıralamanın önemli olmaya başladığı initial ve always yapıları.

Sıkça Sorulan Sorular

Verilog'da continuous assignment nedir?

assign target = expression;, kalıcı, sürekli bir ilişki tanımlar: target her zaman expression'a eşittir. İfadedeki herhangi bir sinyal değiştiğinde, simülatör sağ tarafı tekrar değerlendirir ve target'ı günceller. Saat yok, olay yok - ilişki her zaman noktasında doğrudur.

Verilog'da assign ile neyi hedefleyebilirsin?

assign bir wire'ı sürebilir, ama asla bir reg'i süremez. Hedef bir net tipi olmalıdır. Bunun yerine bir always bloğunun içinde bir şeye atama yapman gerekiyorsa, onu reg olarak tanımla. Derleyici, x reg ise assign x = ...'i reddeder ve x wire ise always içinde x = ...'i reddeder.

Ne zaman assign ne zaman always block kullanmalıyım?

Basit kombinasyonel mantık için assign kullan - bir ifade, bir sinyal çıkışı, if/else'e gerek yok. Mantık prosedürel ifadeler gerektirdiğinde always @(*) kullan (bir case, bir if/else if zinciri, bir for döngüsü). İkisi de kombinasyonel donanım üretir; seçim okunabilirlikle ilgilidir.

Verilog'da aynı wire'a birden çok assign olabilir mi?

Yalnızca her sürücünün inaktif olduğunda wire'ı z'ye bıraktığı bir tri-state bus'ı modelliyorsan. Aynı anda wire'ı kesin değerlere sürmeye çalışan iki assign çekişme üretir - simülatör birini seçebilir, sinyali X'leyebilir, araca bağlıdır. Sıradan kombinasyonel mantık için, wire başına bir sürücü.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA