Verilog vs SystemVerilog
Gün 1: SystemVerilog'a Giriş ve Veri Tipleri | İki dil arasındaki temel farklar ve SV'nin getirdiği yenilikler
Bu derste klasik Verilog ile modern SystemVerilog'u yan yana koyarak; veri tiplerinde, döngü yapılarında ve tip dönüşümlerinde getirilen kolaylıkları somut örneklerle karşılaştıracağız.
Verilog'un Sınırları ve SystemVerilog'un Yanıtı
Verilog, donanım tanımlamak için tasarlanmış olgun bir dildir; ancak gündelik kullanımda yazımı uzatan ve hata yapmaya açık bazı kısıtları vardır:
- reg / wire ayrımı: Verilog'da bir sinyalin
regmi yoksawiremı olacağına bağlama göre karar vermek gerekir. SystemVerilog bunu büyük ölçüde tek birlogictipiyle çözer. - Sınırlı tip seti: Verilog esasen
reg,wire,integerverealetrafında döner. SystemVerilog isebit,byte,shortint,int,longintgibi genişliği net belirli tipler sunar. - Hantal döngü sözdizimi: Verilog'da döngü değişkenini ayrıca tanımlamak ve
i = i + 1gibi yazmak gerekir.
Daha İfadeli Kontrol Yapıları
SystemVerilog, yazılım dillerine yaklaşan kontrol yapıları getirir:
- for döngüsünde yerel tanımlama:
for (int i = 0; i < 4; i++)ile döngü değişkeni döngünün içinde tanımlanır ve++/--operatörleri kullanılabilir. - do-while döngüsü ile gövde en az bir kez çalışır.
- foreach ile bir dizinin tüm elemanları indeks yönetmeden gezilir.
- Tip dönüşümleri (casting):
int'(r)veya8'(i)sözdizimiyle tipler ve bit genişlikleri arasında açık (explicit) dönüşüm yapılır.
Kaynak Kod
// =============================================================================
// GUN 1 - Konu 2: Verilog vs. SystemVerilog Farklari
// =============================================================================
module verilog_vs_sv;
// -------------------------------------------------------------------------
// VERILOG TARZI (Eski Yontem)
// -------------------------------------------------------------------------
reg [7:0] verilog_data; // reg ve wire ayrimi gerekli
wire [7:0] verilog_wire;
integer verilog_int; // 32-bit, her zaman signed
reg verilog_array [0:3]; // Kisitli dizi destegi
// -------------------------------------------------------------------------
// SYSTEMVERILOG TARZI (Modern Yontem)
// -------------------------------------------------------------------------
logic [7:0] sv_data; // Tek tip: hem reg hem wire yerine
int sv_int; // Kompakt 32-bit signed
bit [7:0] sv_fast; // 2-state, daha hizli simulasyon
byte sv_byte; // 8-bit signed
shortint sv_short; // 16-bit signed
longint sv_long; // 64-bit signed
// SystemVerilog: Gelismis donguler
initial begin
$display("=== Verilog vs. SystemVerilog Karsilastirmasi ===\n");
// --- Verilog tarzi dongu ---
$display("[Verilog] Klasik for dongusu:");
begin : verilog_loop
integer i;
for (i = 0; i < 4; i = i + 1) begin
$display(" i = %0d", i);
end
end
// --- SystemVerilog tarzi dongu ---
$display("\n[SystemVerilog] Gelismis for dongusu:");
for (int i = 0; i < 4; i++) begin // Dongu icinde tanimlama, ++ operatoru
$display(" i = %0d", i);
end
// --- SystemVerilog: do-while ---
$display("\n[SystemVerilog] do-while dongusu:");
begin
int count = 3;
do begin
$display(" count = %0d", count);
count--;
end while (count > 0);
end
// --- SystemVerilog: foreach ---
$display("\n[SystemVerilog] foreach dongusu:");
begin
int arr [5] = '{10, 20, 30, 40, 50};
foreach (arr[i])
$display(" arr[%0d] = %0d", i, arr[i]);
end
// --- SystemVerilog: case ---
$display("\n[SystemVerilog] case:");
begin
int sel = 2;
case (sel)
0: $display(" Secim: A");
1: $display(" Secim: B");
2: $display(" Secim: C");
3: $display(" Secim: D");
endcase
end
// --- SystemVerilog: Otomatik tip donusumu ---
$display("\n[SystemVerilog] Tip donusumleri:");
begin
real r = 3.14;
int i = int'(r); // Casting
bit [7:0] b = 8'(i); // Bit genisligi casting
$display(" real=%f -> int=%0d -> bit[7:0]=%0d", r, i, b);
end
$display("\n=== Karsilastirma Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
- Modülün başında iki bölüm vardır. Verilog tarzı kısımda
reg [7:0] verilog_data,wire [7:0] verilog_wire,integer verilog_intvereg verilog_array [0:3]tanımları, eski yöntemin tip ayrımını ve sınırlı dizi desteğini gösterir. - SystemVerilog tarzı kısımda
logic [7:0] sv_datatek tiplereg/wireihtiyacını karşılar.int,bit [7:0],byte,shortintvelongintise genişlikleri net belirli tiplerdir (byte=8,shortint=16,int=32,longint=64 bit, tümü signed). verilog_loopadlıbegin : ... endbloğu Verilog'un klasikfor (i = 0; i < 4; i = i + 1)yazımını; hemen ardından gelenfor (int i = 0; i < 4; i++)ise döngü içinde tanımlama ve++operatörünü gösterir.do begin ... end while (count > 0)bloğundacount3'ten başlar vecount--ile azalır;do-whileolduğu için gövde koşul kontrol edilmeden önce çalışır.int arr [5] = '{10, 20, 30, 40, 50};dizisiforeach (arr[i])ile gezilir; buradaiindeksi otomatik üretilir.case (sel)bloğusel = 2olduğu için"Secim: C"dalını seçer.- Son blokta
real r = 3.14;değeriint'(r)ile tam sayıya, ardından8'(i)ile 8-bit genişliğe dönüştürülür. Dikkat:int'(r)ondalık kısmı atmaz, en yakın tam sayıya yuvarlar.3.14için sonuç3'tür ama3.7olsaydı4elde ederdiniz. Kesme (truncation) istiyorsanız$rtoi(r)sistem fonksiyonunu kullanın.
Önemli Noktalar
- Yeni tasarımlarda sürdürülen sinyaller için
reg/wireyerinelogickullanmak hem okunabilirliği artırır hem de yanlış tip seçimi hatalarını azaltır. - Genişliği önemli olan değişkenlerde
integeryerine boyutu net olanint,byte,shortint,longinttiplerini tercih edin. fordöngüsünde değişkeni döngü içinde tanımlamak (for (int i...)) kapsamı (scope) daraltır ve yan etkileri azaltır.- Tip dönüşümlerinde açık casting (
int'(...),8'(...)) kullanmak, gizli/otomatik dönüşümlerden kaynaklanan sürprizleri önler.real→intdönüşümünde değer yuvarlanır (int'(2.5)→3); kesme için$rtoi(), tersineint→realiçin$itor()kullanılır. 8'(i)gibi genişlik casting'i, değer hedef genişliğe sığmıyorsa üst bitleri sessizce keser (8'(300)→44). Bu kesmeyi bilinçli yaptığınızı kodda yorumla belirtmek iyi bir alışkanlıktır.$displayiçindeki\nkaçış karakteri çıktıyı biçimlendirmek için kullanılır; bu hem Verilog'da hem SystemVerilog'da geçerlidir.
Hızlı Karşılaştırma Tablosu
| Konu | Verilog-2001 | SystemVerilog |
|---|---|---|
| Sinyal tipi | reg / wire ayrımı zorunlu |
Tek tip: logic |
| Tam sayılar | integer (32-bit, 4-state) |
byte, shortint, int, longint (2-state), int unsigned... |
| Döngü değişkeni | Önceden tanımlanmalı | for (int i = 0; ...) ile yerinde tanım |
| Artırma | i = i + 1 |
i++, i += 2 |
| Dizi gezme | İndeks aritmetiği elle | foreach (arr[i]) |
| Koşullu döngü | while |
while, do...while |
| Tip dönüşümü | Örtük (implicit) | Açık: int'(x), 8'(x), $cast |
| Blok başlangıcı | begin ... end |
begin ... end + break/continue desteği |
| Metin | Bit vektörü | string tipi ve metodları |
Sık Yapılan Hatalar
int'(x)'in kestiğini sanmak: Yukarıda vurgulandığı gibi yuvarlar. Bu, zamanlama hesaplarında (int'(period/2)) bir çevrimlik kaymalara yol açabilir.- Döngü değişkenini modül seviyesinde tanımlamak:
integer i;modül düzeyinde tanımlanıp birden fazlaalways/initialbloğunda paylaşılırsa süreçler birbirininideğerini bozar.for (int i...)bu riski sıfırlar. do...whileilewhile'ı karıştırmak:do...whilegövdeyi en az bir kez çalıştırır. Koşul baştan yanlışsawhilehiç çalışmaz; bu fark "bir kez mutlaka dene" senaryolarında (örneğin ilk polling denemesi) kritiktir.
Kendinizi Deneyin
real r = 3.7;yapıpint'(r)ve$rtoi(r)sonuçlarını yan yana yazdırın. Farkı açıklayın.foreachdöngüsünü,arrdizisinin yalnızca çift indeksli elemanlarını basacak şekilde değiştirin (ipucu:if (i % 2 == 0)veyacontinue).case (sel)bloğunadefault:dalı ekleyin vesel = 7verin. SystemVerilog'dakiunique casevepriority caseanahtar kelimelerini araştırıp farklarını not alın.
Hızlı Kontrol: byte b = 8'(200); yazdığınızda b hangi değeri yazdırır?
byte 8-bit işaretli olduğundan 200 (ikilik 1100_1000) işaretli yorumlandığında -56 olur. İşaretsiz 0–255 aralığı istiyorsanız bit [7:0] veya byte unsigned kullanın.