Menu

Verilog Always Block: Kombinasyonel ve Sıralı Mantık

always bloklarının nasıl çalıştığı, kombinasyonel always @(*) ile saatli always @(posedge clk) arasındaki fark ve her birinin hangi donanımı ürettiğini belirleyen kurallar.

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

Davranışsal Verilog'un İş Atı

assign, tek denklemli kombinasyonel mantığı tanımlar. if/else, case veya bellek gerektiren bir şey olduğu anda always'e uzanırsın. Bir always bloğu, belirli sinyaller değiştiğinde tekrar çalışan bir prosedürel kod parçasıdır. Yeniden çalışmayı tetikleyen sinyaller sensitivity list'tir.

En sık göreceğin iki always şekli vardır:

  1. always @(*) - blokta okunan herhangi bir sinyal değiştiğinde tekrar çalışır. Kombinasyonel mantık kurar.
  2. always @(posedge clk) - yalnızca clk'nin yükselen kenarında tekrar çalışır. Saatli sıralı mantık (flip-flop) kurar.

Diğer formlar da vardır (@(a or b), @(negedge clk), @(posedge clk or negedge reset_n)), ama yukarıdaki ikisi yazacağın neredeyse her sentezlenebilir bloğu kapsar.

Kombinasyonel always @(*)

Fark etmen gereken üç şey:

  • out, reg'dir. always içinde atanan her şey reg olmalıdır. Bu anahtar sözcük "bu bir flip-flop'tur" anlamına gelmez; burada yalnızca "prosedürel bir bloktan yazılıyorum" demektir.
  • always @(*). * ifadesi "okuduğum bir şey her değiştiğinde uyan" der. Simülatör sensitivity list'i otomatik çıkarır. Listeyi elle de yazabilirsin - always @(sel) - ama @(*) daha güvenlidir çünkü bir sinyali unutmak klasik bir hata kaynağıdır.
  • Saat yok. Bu blok kombinasyonel mantığı tanımlar. Sentezleyici, out'u doğrudan sel'den hesaplayan bir mantık parçası üretir - flip-flop yok, saat ucuna gerek yok.

default durumu sözdizimi olarak isteğe bağlı olsa da ruhen değildir. Onu atlarsan, belirtilmemiş bir giriş değeri out'un önceki değerini korumasına neden olur - bu da istenmeyen bir latch olarak sentezlenir. Her zaman default ekle.

Sıralı always @(posedge clk)

Kombinasyonel sürümden temel farkları:

  • always @(posedge clk). Blok yalnızca clk'nin yükselen kenarında tekrar çalışır. Kenarlar arasında hiçbir şey olmaz.
  • Non-blocking atama <=. Saatli bir bloğun içinde doğru operatör budur. "Zaman adımı sonunda count'a yeni değerini al" demektir, ki bu tam olarak bir flip-flop'un davranışıdır. Nedeni ve alternatifi Blocking vs Non-blocking bölümündedir.
  • default gerekmez. if her iki dalı da (reset ve reset değil) kapsar. Latch riski yok.

Sentezleyici bu şekli görür - saatli sensitivity, non-blocking atama - ve 4 bitlik bir register (dört flip-flop) artı count + 1'i hesaplayan kombinasyonel mantık ve reset ile artış arasından seçen mux'ı üretir.

Sentez Ayrımı

Aynı modül kaynağı, always bloğunun şekline göre tamamen farklı iki donanım parçasını tanımlayabilir:

BlokDonanım
always @(*) y = expr;Saf kombinasyonel mantık. Bellek yok.
always @(posedge clk) y <= expr;Flip-flop. expr'i saat döngüsü başına bir kez yakalar.
always @(*) if (en) y = expr;Latch - genellikle bir hata. "else" durumu eski değeri tutar.
always @(posedge clk) if (en) y <= expr;Enable'lı flip-flop. Yalnızca en yüksekken yakalar.

Üçüncü durum latch tuzağıdır. Latch, girişi onaylanmadığında çıkışını koruyan saydam bir bellek hücresidir - belirli tasarımlarda kullanışlı, kaza eseri ortaya çıktığında neredeyse her zaman bir hata. Çoğu sentez aracı, istemediğin bir latch çıkardığında yüksek sesle uyarır. Uyarıyı hata olarak değerlendir.

Sensitivity List Varyantları

Daha az yaygın bazı sensitivity list'leri göreceksin:

  • always @(a or b or c) - açık liste. Verilog-2001, , ayırıcısını ekledi: always @(a, b, c). İkisi de çalışır.
  • always @(posedge clk or negedge reset_n) - asenkron reset. Blok, yükselen saat kenarında veya düşen reset kenarında çalışır. Reset'in sonraki saati beklemeden hemen etkili olması gereken durumlarda kullanılır.
  • always @(negedge clk) - düşen-kenar saatleme. Nadirdir; bazı tasarımlar yükselen yerine düşen kenarda yakalayan "negatif-kenar-tetiklemeli" flip-flop'lar için kullanır.

Yeni tasarımlarda kombinasyonel için always @(*), sıralı için always @(posedge clk) tercih et. Asenkron reset'e yalnızca tasarım gerçekten gerektirdiğinde uzan.

İki Blok, İki Donanım Parçası

Aynı modüldeki birden çok always bloğu birbirinden bağımsızdır - her biri kendi donanım parçası olur:

Saatli blok bir flip-flop register üretir. Kombinasyonel blok bir XOR gate üretir. Yan yana yaşarlar; ikisi de diğerinden haberdar değildir. İki çıkış tamamen farklı takvimlerde değişir.

always Bloklarının Yapamayacakları

Çekici görünen ama izin verilmeyen birkaç şey:

  • Bir wire'a atama: hedef reg olmalı. Derleyici zorlar.
  • Aynı reg'e iki farklı always bloğundan atama: simülasyonda tanımsız davranış üretir ve sentezlenmez. Sinyal başına tek sürücü.
  • Aynı kombinasyonel blokta aynı sinyali okuyup yazmak, geri besleme döngüsü oluşturacak şekilde: always @(*) x = x + 1; simülatörün çözemediği sıfır gecikmeli bir döngüdür.

İlk ikisini derleyici yakalar. Üçüncüsü bazen yalnızca simülasyon sırasında bir takılma olarak ortaya çıkar.

Sırada Ne Var

Bir sonraki doc - Initial Block - always'in kardeşini kapsar: simülasyon başlangıcında tam olarak bir kez çalışan bir blok. Testbench'lerin iş atıdır. Ondan sonra, saatli bloğunun istediğin gibi çalışıp çalışmadığını belirleyen blocking ve non-blocking atama kuralları gelecek.

Sıkça Sorulan Sorular

Verilog'da always block nedir?

always, sensitivity list'indeki sinyaller her değiştiğinde yeniden çalışan bir prosedürel blok başlatır. İki çeşidi vardır: always @(*) kombinasyonel mantık kurar (herhangi bir giriş değiştiğinde tekrar çalışır), always @(posedge clk) sıralı mantık kurar (clk'nin her yükselen kenarında çalışır). Bir always bloğunun gövdesinde if, case, for ve prosedürel atamalar bulunabilir.

always @(*) ile always @(posedge clk) arasındaki fark nedir?

always @(*) blokta okunan herhangi bir sinyale duyarlıdır; belleksiz kombinasyonel mantık üretir. always @(posedge clk) yalnızca clk'nin yükselen kenarına duyarlıdır; saat döngüsü başına bir kez durumu yakalayan flip-flop'lar üretir. Birincisinde ne saat ne register vardır; ikincisinde her ikisi de vardır.

Verilog'da sensitivity list nedir?

@ sonrasındaki, always bloğunun ne zaman tekrar çalışacağını belirleyen sinyal listesidir. @(*), 'blokta okunan her sinyal' için kısaltmadır. @(posedge clk) yalnızca clk'nin yükselen kenarında çalışır. @(posedge clk or negedge reset_n) ikisinden birinde çalışır - asenkron reset için kullanılır. Sensitivity list'i yanlış yazmak, sim/synthesis uyuşmazlığının en yaygın kaynaklarından biridir.

always block içinde bir wire'a atama yapabilir misin?

Hayır. always blokları sadece reg'e (veya SystemVerilog'da logic'e) atama yapabilir. Derleyici bunu zorlar. Bir wire'ın prosedürel mantığın çıktısı olmasını istiyorsan, ara bir reg tanımla, onu always içinde sür ve dışarıdan wire'ı reg'den assign ile sür - ya da wire'ı doğrudan reg'e çevir.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA