🔁 SystemVerilog Döngü ve Kontrol Akışı Yapıları#
SystemVerilog, hem RTL tasarımı hem de testbench yazımı için güçlü ve esnek döngü yapıları ve kontrol mekanizmaları sunar. Bu yapılar, C dili gibi klasik programlama dillerine benzese de, simülasyon odaklıdır ve donanım modelleme ihtiyaçlarına göre tasarlanmıştır.
🔄 SystemVerilog’ta Döngü Tipleri#
1. for
Döngüsü#
C tarzı klasik sayaçlı döngü.
for (int i = 0; i < 10; i++) begin
$display("i = %0d", i);
end
- Sabit sayıda tekrarlanacak işlemler için uygundur
- Sayaç değişkeni ister içinde ister dışında tanımlanabilir
2. while
Döngüsü#
Koşul doğru olduğu sürece çalışır.
int i = 0;
while (i < 5) begin
$display("i = %0d", i);
i++;
end
- RTL’de dikkatli kullanılmalı: sınırsız döngülerden kaçının
3. do...while
Döngüsü#
En az bir kez çalışır, ardından koşulu kontrol eder.
int i = 0;
do begin
$display("i = %0d", i);
i++;
end while (i < 3);
- Döngü gövdesini mutlaka bir kez çalıştırmak istiyorsanız kullanışlıdır
4. foreach
Döngüsü#
Dizi elemanları üzerinde döngü kurmak için özel yapıdır (packed/unpacked/dinamik/associative dizilerde çalışır).
int arr[5] = '{0, 1, 2, 3, 4};
foreach (arr[i]) begin
$display("arr[%0d] = %0d", i, arr[i]);
end
- Dizi içinde dolaşımı kolaylaştırır
- Testbench’lerde yaygın olarak kullanılır
5. repeat
Döngüsü#
Döngü gövdesini belirtilen sayıda tekrar eder.
repeat (4) begin
$display("Repeat bloğu çalışıyor");
end
- Sayaç gerektirmeyen sabit tekrarlar için uygundur
- Sayı sabitse sentezlenebilir
6. forever
Döngüsü#
Sonsuza kadar çalışır, dış müdahale olmazsa durmaz.
forever begin
@(posedge clk);
$display("Clock tick");
end
- Saat tabanlı simülasyonlarda, testbenchlerde kullanılır
- RTL’de doğrudan sentezlenemez (koruyucu kontrol mekanizması gerekebilir)
🧭 Kontrol Akışı Yapıları#
break
#
Bulunulan döngüden hemen çıkar.
for (int i = 0; i < 10; i++) begin
if (i == 5) break;
$display("i = %0d", i);
end
💡 Belirli bir koşulda döngüyü sonlandırmak istiyorsanız kullanılır.
continue
#
Geçerli döngü adımını atlar ve bir sonraki adıma geçer.
for (int i = 0; i < 5; i++) begin
if (i == 2) continue;
$display("i = %0d", i);
end
💡 Belirli değerleri veya koşulları atlamak için idealdir.
return
#
Bir task veya function içinden çıkmak için kullanılır, değer döndürme imkanı da sağlar.
function int square(int x);
if (x < 0)
return 0;
return x * x;
endfunction
- Döngüyü değil, sadece function/task yapısını sonlandırır
⚠️ Donanım Tasarımında Uyarılar#
- Sınırsız
while
,do...while
veyaforever
döngülerinden RTL içinde kaçının break
vecontinue
yapıları RTL’de sentezlenemez — bunun yerine FSM yapıları kullanın- Bu yapılar çoğunlukla testbench, UVM, ve davranışsal modelleme içindir
✅ Özet Tablo#
Anahtar Kelime | Amaç | Sentezlenebilir mi? | Yaygın Kullanım |
---|---|---|---|
for | Sayaçlı döngü | ✅ (sınırlıysa) | Sayaç tabanlı işlemler |
while | Koşullu döngü | ⚠️ (sonsuzdan kaçın) | Testbench akışı |
do...while | En az bir kez çalışır | ❌ | Davranışsal modeller |
foreach | Dizi üzerinde döngü | ❌ | Testbench, dizi erişimi |
repeat | Belirli sayıda tekrar | ✅ (sabit sayı varsa) | Protokol, senkronizasyon |
forever | Sonsuz döngü | ❌ (RTL için riskli) | Saat tabanlı simülasyon |
break | Döngüyü anında bitir | ❌ | Döngüden erken çıkış |
continue | Geçerli adımı atla | ❌ | Bazı değerleri atlamak |
return | Function/task’ten çıkış | ✅ | Koşullu çıkışlar |
SystemVerilog’un kontrol akışı yapıları özellikle testbench yazımında esnek ve sezgisel kodlar yazmanıza olanak tanır. RTL yazarken ise tüm döngülerin sınırlı ve deterministik olduğundan emin olun.
module tb_loops_and_flow;
// For loop
initial begin
for (int i = 0; i < 3; i++)
$display("for loop i = %0d", i);
end
// While loop
initial begin
int j = 0;
while (j < 2) begin
$display("while loop j = %0d", j);
j++;
end
end
// Do...while loop
initial begin
int k = 0;
do begin
$display("do-while k = %0d", k);
k++;
end while (k < 2);
end
// Foreach loop
int arr[3] = '{10, 20, 30};
initial begin
foreach (arr[i])
$display("arr[%0d] = %0d", i, arr[i]);
end
// Repeat loop
initial begin
repeat (2)
$display("repeat loop running");
end
// Forever loop (terminated after short sim)
initial begin
int cnt = 0;
forever begin : forever_loop
#5 $display("forever loop cnt = %0d", cnt++);
if (cnt == 2) break;
end
end
// Break and continue
initial begin
for (int m = 0; m < 5; m++) begin
if (m == 2) continue;
if (m == 4) break;
$display("loop with break/continue m = %0d", m);
end
end
// Return example
initial begin
int val = square(-4);
$display("square(-4) = %0d", val);
end
function int square(int x);
if (x < 0)
return 0;
return x * x;
endfunction
endmodule