typedef, enum ve struct
Gün 1: SystemVerilog'a Giriş ve Veri Tipleri | Kullanıcı tanımlı tipler: typedef, enum, struct, union
Bu derste kendi veri tiplerimizi nasıl tanımlayacağımızı öğreniyoruz: typedef ile takma adlar, enum ile anlamlı isimli sabitler, struct ile ilişkili verilerin gruplanması ve union ile aynı belleğin farklı görünümleri.
typedef: Tiplere İsim Vermek
typedef, mevcut bir tipe yeni bir ad vererek kodu hem okunabilir hem de bakımı kolay hâle getirir. Örneğin bir adres tipini her yerde logic [15:0] yazmak yerine addr_t olarak tanımlarsanız, genişliği değiştirmeniz gerektiğinde tek bir yeri düzenlemeniz yeter.
enum: Anlamlı Sabitler
enum, bir değişkenin alabileceği değerleri isimli sabitlerle sınırlar. Durum makineleri (FSM) ve opcode'lar için idealdir; 2'b01 yerine READ yazmak hem okunur hem de hataya kapalıdır. Enum tipleri zengin yerleşik metodlar sunar:
.name()→ değerin metin karşılığını verir.first()/.last()→ ilk ve son elemanı verir.next()/.prev()→ komşu elemanlara geçer.num()→ eleman sayısını verir
struct ve packed struct
struct, farklı tiplerdeki ilişkili alanları tek bir yapıda toplar (örneğin bir transaction'ın adres, veri ve geçerlilik bilgisi). Varsayılan struct unpacked'tir. struct packed ise alanları bitişik bitler halinde saklar; tek bir vektör gibi davrandığı için sentezlenebilir ve bit düzeyinde erişilebilir.
union: Aynı Belleğin Farklı Görünümleri
union packed, aynı bellek alanını farklı tipler üzerinden yorumlamaya izin verir; örneğin 16-bit bir değere hem tek vektör hem de iki ayrı byte olarak erişmek gibi.
Kaynak Kod
// =============================================================================
// GUN 1 - Konu 4: Kullanici Tanimli Tipler: typedef, enum, struct
// =============================================================================
module typedef_enum_struct;
// -------------------------------------------------------------------------
// TYPEDEF: Mevcut tiplere yeni isim verme
// -------------------------------------------------------------------------
typedef logic [7:0] byte_t;
typedef logic [31:0] word_t;
typedef logic [15:0] addr_t;
// -------------------------------------------------------------------------
// ENUM: Numaralandirilmis tipler
// -------------------------------------------------------------------------
typedef enum logic [1:0] {
IDLE = 2'b00,
READ = 2'b01,
WRITE = 2'b10,
ERROR = 2'b11
} state_e;
typedef enum logic [2:0] {
ADD, SUB, AND, OR, XOR, NOT, SHL, SHR
} opcode_e;
// -------------------------------------------------------------------------
// STRUCT: Yapilar - iliskili verileri gruplar
// -------------------------------------------------------------------------
typedef struct {
addr_t addr;
word_t data;
opcode_e op;
bit valid;
} transaction_t;
// PACKED STRUCT: Bitler ardisik saklanir, sentezlenebilir
typedef struct packed {
logic [3:0] tag;
logic [7:0] payload;
logic parity;
} packet_t;
// -------------------------------------------------------------------------
// UNION: Ayni bellegi paylasan tipler
// -------------------------------------------------------------------------
typedef union packed {
logic [15:0] word;
struct packed {
logic [7:0] high;
logic [7:0] low;
} bytes;
} reg16_t;
// Degisken tanimlamalari
state_e current_state;
opcode_e alu_op;
transaction_t txn;
packet_t pkt;
reg16_t register_val;
initial begin
$display("=== typedef, enum, struct Ornekleri ===\n");
// --- ENUM kullanimi ---
current_state = IDLE;
$display("[ENUM] Durum = %s (deger=%0b)", current_state.name(), current_state);
current_state = READ;
$display("[ENUM] Durum = %s (deger=%0b)", current_state.name(), current_state);
// Enum metodlari
alu_op = ADD;
$display("\n[ENUM Metodlari]");
$display(" Ilk = %s", alu_op.first().name());
$display(" Son = %s", alu_op.last().name());
$display(" Sonraki= %s", alu_op.next().name());
$display(" Eleman = %0d", alu_op.num());
// --- STRUCT kullanimi ---
txn.addr = 16'hABCD;
txn.data = 32'hDEAD_BEEF;
txn.op = ADD;
txn.valid = 1;
$display("\n[STRUCT] Transaction:");
$display(" Adres = 0x%04h", txn.addr);
$display(" Veri = 0x%08h", txn.data);
$display(" Islem = %s", txn.op.name());
$display(" Gecerli = %0b", txn.valid);
// Struct literal (toplu atama)
txn = '{addr: 16'h0010, data: 32'hCAFE_BABE, op: SUB, valid: 1};
$display("\n[STRUCT Literal] Transaction:");
$display(" Adres = 0x%04h, Veri = 0x%08h", txn.addr, txn.data);
// --- PACKED STRUCT ---
pkt = '{tag: 4'hA, payload: 8'hFF, parity: 1'b1};
$display("\n[PACKED STRUCT] Paket:");
$display(" Toplam bit = %0d", $bits(pkt));
$display(" Bit dizisi = %013b", pkt);
$display(" Tag=%h, Payload=%h, Parity=%b", pkt.tag, pkt.payload, pkt.parity);
// --- UNION ---
register_val.word = 16'hA5F0;
$display("\n[UNION] Register:");
$display(" Word = 0x%04h", register_val.word);
$display(" High = 0x%02h, Low = 0x%02h", register_val.bytes.high, register_val.bytes.low);
$display("\n=== typedef, enum, struct Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
typedef logic [7:0] byte_t;,word_tveaddr_tsatırları sık kullanılan genişlikler için takma adlar üretir. Bu adlar daha sonratransaction_tiçinde alan tipi olarak kullanılır.state_eenum'uIDLE,READ,WRITE,ERRORdurumlarınılogic [1:0]tabanında açık değerlerle (2'b00...2'b11) tanımlar.opcode_eise değer atamadan tanımlandığı için elemanlar0'dan başlayarak otomatik numaralandırılır (ADD=0,SUB=1 ...).transaction_tbir unpacked struct'tır veaddr,data,op,validalanlarını birleştirir.packet_tisestruct packedolduğu içintag,payload,parityalanları toplam 13 bit olarak bitişik saklanır.reg16_tbirunion packed'tir:word(16-bit) ile içtekibytesyapısınınhigh/lowalanları aynı belleği paylaşır.initialbloğunda öncecurrent_state = IDLE;veREADatanır,current_state.name()ile durumun ismi yazdırılır.- Enum metodları
alu_op = ADD;üzerinde gösterilir:alu_op.first().name(),.last().name(),.next().name()ve.num()sırasıyla ilk/son elemanı, sonrakini ve toplam eleman sayısını verir. txn.addr = 16'hABCD;gibi alan alan atama iletxn = '{addr: ..., data: ..., op: SUB, valid: 1};şeklindeki struct literal (toplu atama) karşılaştırılır.pkt = '{tag: 4'hA, payload: 8'hFF, parity: 1'b1};packed struct'a değer atar;$bits(pkt)toplam genişliği (13) verir ve%013bile bit dizisi basılır.register_val.word = 16'hA5F0;union'a yazıldığında, aynı bellekregister_val.bytes.high(A5) veregister_val.bytes.low(F0) olarak okunabilir.
Önemli Noktalar
enumdeğerlerini.name()ile yazdırmak, dökümlerde2'b10yerineWRITEgörmenizi sağlar; bu da hata ayıklamayı çok kolaylaştırır.- Sentezlenebilir ve bit düzeyinde paketlenmiş veri için
struct packedkullanın; salt testbench/modelleme amaçlı esnek gruplamalarda unpackedstructyeterlidir. struct literal('{...}) ile toplu atama, alanları tek tek atamaktan daha okunaklı ve hataya kapalıdır; alan adlarını yazmak sıralama hatalarını önler.union packedgüçlüdür ama dikkatli kullanılmalıdır: aynı belleğin farklı yorumları, alan genişlikleri ve bit sıralaması (endianness) konusunda net olmayı gerektirir.typedef'leri tek bir paket (package) ya da ortak dosyada toplamak, takım genelinde tutarlı tip kullanımını sağlar ve genişlik değişikliklerini tek noktadan yönetir.- Enum metodlarında
.next()son elemandayken başa döner (sarmalama); bu davranışı durum makinelerinde göz önünde bulundurun.