Yazılım Benzeri
Verilog'un for döngüsü C'ninkinin bir kopyasıdır:
for (i = 0; i < 8; i = i + 1) begin
// gövde
end
Aynı üç parça: initializer, condition, increment. Gövde koşul tuttuğu sürece tekrar çalışır.
Bir testbench'te bu, yazılımdan beklediğin gibi davranır. Simülatör her iterasyonu sırayla adımlar:
Dört iterasyon, dört satır çıktı. Sürpriz yok.
Sürpriz, bir for döngüsünü sentezlenebilir koda koyduğunda gelir.
Açma (Unroll)
Sentezlenebilir bir always bloğundaki bir for döngüsü donanımda bir çalışma zamanı döngüsü olmaz. Sentezleyici onu elaboration zamanında açar - onu gövdenin N kopyasına genişletir, burada N iterasyon sayısıdır:
Bu bir döngü gibi görünüyor. Simülasyonda, simülatör sekiz iterasyon boyunca döner. Sentezde, döngü data[0]'dan data[7]'ye kadar sekiz paralel kontrol olarak açılır, hepsi aynı anda gerçekleşir. Sentezleyici şunu görür:
count = 0;
if (data[0]) count = count + 1;
if (data[1]) count = count + 1;
if (data[2]) count = count + 1;
...
if (data[7]) count = count + 1;
…ve sonra diziyi bir adder tree'ye dönüştürür. Çalışma zamanı davranışı "8 bitin hepsine aynı anda bak ve kaç tanesinin 1 olduğunu say"dır, tek bir kombinasyonel taramada.
İçerme: sentezlenebilir Verilog'da bir for döngüsü bedava değildir. 64 iterasyonlu bir döngü donanımda gövdenin 64 kopyası olur. Gövde karmaşıksa, az önce büyük bir kombinasyonel blok kurdun. N küçük olduğunda (bir avuç ile birkaç düzine arası) döngüleri kullan. Daha büyük sayılar için, genellikle saatli bir counter ve bir state machine istersin.
Sabit Sınırlar Gereklidir
Sentezleyici, yalnızca N'yi elaboration zamanında biliyorsa döngüyü açabilir. Bu, döngü sınırlarının sabit olması gerektiği anlamına gelir:
// Çalışır - sınır sabit
for (i = 0; i < 8; i = i + 1) ...
// Çalışır - sınır bir parametre
for (i = 0; i < WIDTH; i = i + 1) ...
// Sentezlenmez - sınır çalışma zamanı sinyaline bağlı
for (i = 0; i < dynamic_count; i = i + 1) ...
Son form yine de simülasyonda çalışabilir, ama sentezleyici onu reddeder. Gerçekten bir çalışma zamanı sayılı döngüye ihtiyacın varsa, onu saatli bir state machine ve bir counter register ile kurarsın - donanımda yazılımdaki gibi değişken-trip-count döngüler yoktur.
generate for vs Prosedürel for
Ayrı ama ilgili bir yapı, genvar kullanan ve always blokları dışında yaşayan generate for'dur:
genvar i;
generate
for (i = 0; i < 8; i = i + 1) begin : g
bit_inverter inv(.x(in[i]), .y(out[i]));
end
endgenerate
Bu 8 instance bit_inverter çıkarır (Module Instantiation bölümünde kapsanır). Yapısal - "bu alt modülün 8 kopyasını yap" diyorsun - davranışsal değil.
Hızlı ayrım:
- Prosedürel
for(alwaysiçinde) - tek bir davranışsal blok içindeki ifadeleri açar. - Generate
for(alwaysdışında) - tüm yapısal yapıları çoğaltır: instance'lar,assignifadeleri, adlandırılmış bloklar.
Çoğalttığın şeyle eşleşeni kullan.
for'un Parladığı Yer: Vektör İşlemleri
Döngüler, bir vektörün her biti için aynı işlemi yaptığında en iyileridir. Population count, parity, byte reversal, lookup-table üretme:
32 iterasyon, her biri bir bit ataması yapıyor - 32 elle yazılmış wire ataması yazmaktan çok daha okunaklı. Sentezleyici temiz açar.
while, repeat, forever
for'un ötesinde, Verilog'un üç başka döngü yapısı vardır - çoğunlukla testbench'ler için:
// Bir koşul başarısız olana kadar çalıştır
while (~done) begin
@(posedge clk);
cycles = cycles + 1;
end
// N kez çalıştır - bir sayaca ihtiyacın olmadığında for'dan daha basit
repeat (8) @(posedge clk);
// Sonsuza kadar çalıştır - saat üreticileri, izleme döngüleri
always #5 clk = ~clk;
forever begin
@(posedge clk);
$display("count=%0d", count);
end
while, repeat ve forever yalnızca dar durumlarda sentezlenebilir (özellikle sabit bir sayım ve saatli bir gövde ile repeat). Testbench'lerde bunlar kullanışlı araçlardır; sentezlenebilir RTL'de sayılan bir for artı açık bir state machine'i tercih et.
Testbench'lerde Prosedürel for
Bir testbench'te for döngüleri yazılımın yaptığı gibi davranır. Bunları özgürce kullan:
İç içe döngüler, iki 2 bitlik girişin her kombinasyonunu süpürür. Simülatör iterasyonları sırayla çalıştırır. Açma kaygısı yok - testbench'ler sentezlenmez.
Yaygın Hatalar
Sentezlenebilir kodda sabit olmayan bir sınırla bir for döngüsü kullanmak. Sentezleyici reddedecektir. Sınır çalışma zamanıysa, bir counter ve bir state machine kur.
Döngü gövdesinin paralel donanım olduğunu unutmak. Gövdesinde bir çarpıcı olan 64 iterasyonlu bir döngü 64 paralel çarpıcıdır - muhtemelen istediğin bu değil. Geniş datapath'ler için, tek bir çarpıcı kur ve onu sırayla besle.
integer i ile i adlı bir reg'i karıştırmak. İkisi farklı scope'lardır; integer döngünün içinde kazanır. Karışıklığı önlemek için net isimler seç.
Sırada Ne Var
Artık Verilog'un sunduğu her prosedürel yapıya sahipsin. Bir sonraki bölüm her şeyi dijital tasarımcıların gerçekten gönderdiği kalıplara çeker: Clocked Logic - flip-flop'lar, register'lar ve pipeline'lar - ve Finite State Machines - birden çok çalışma modu olan herhangi bir kontrolör için standart deyim.
Sıkça Sorulan Sorular
Verilog'da for döngüleri nasıl çalışır?
Sözdizimsel olarak C gibi görünürler: for (i = 0; i < N; i = i + 1) statement;. Ama sentezlenebilir kod için, döngü elaboration zamanında unrolled (açılır) - sentezleyici onu gövdenin N kopyasına genişletir. Donanımda çalışma zamanı döngü sayacı veya döngüleme yoktur. Testbench'ler için, simülatör onları sırayla adımlayabildiği için for döngüleri yazılım kuzenleri gibi davranır.
Verilog'da bir for döngüsü sentezlenebilir mi?
Evet, ama yalnızca döngü sınırları elaboration zamanında bilinen sabitler olduğunda. Sentezleyici döngüyü gövdenin N paralel kopyasına açar. Sınırlar bir çalışma zamanı sinyaline bağlıysa, döngü sentezlenebilir değildir - onu saatli bir sıralı tasarıma dönüştürmek zorundasın.
Verilog'da for ile generate for arasındaki fark nedir?
Bir always bloğunun içindeki bir for döngüsü, açarak sentezleyen bir prosedürel yapıdır. Bir generate for döngüsü (genvar ile), yapısal donanımı çıkaran açık bir elaboration zamanı yapısıdır - birden çok modül instance, birden çok wire, birden çok assign ifadesi. Prosedürel bloklar içinde for kullan; yapıyı çoğaltmak için dışarıda generate for kullan.
Verilog'un while döngüsü var mı?
Evet - while (condition) statement;. Yalnızca sentezleyici sınırlı sayıda iterasyonla sonlandığını kanıtlayabildiğinde sentezlenebilir. Pratikte bu nadirdir, bu yüzden while çoğunlukla testbench'lerde ve simülasyon-yalnızca kodda görünür. Sentezlenebilir iterasyon için, bunun yerine sayılan bir for döngüsü kullan.