📦 package
Nedir?#
SystemVerilog’ta package
, tip tanımları, sabitler, fonksiyonlar ve task’ler gibi yeniden kullanılabilir nesneleri bir araya toplayan bir yapıdır. C++ veya Java’daki namespace (isim alanı) mantığına benzer şekilde çalışır ve kodun modülerliğini, okunabilirliğini ve paylaşılabilirliğini artırır.
🧱 Temel package
Söz Dizimi#
package my_pkg;
typedef enum logic [1:0] {IDLE, RUN, STOP} state_t;
int global_counter;
function int add(int a, b);
return a + b;
endfunction
endpackage
🚀 package
Nasıl Kullanılır?#
Bir paketi kullanmak için ya tüm içeriği import edebiliriz ya da sadece ihtiyacımız olan kısmı:
🔹 1. Tüm İçeriği Import Etmek#
import my_pkg::*;
Bu yöntem tüm tanımları doğrudan erişilebilir hale getirir (
state_t
,add()
, vb.).
🔹 2. Belirli Tanımı Import Etmek#
import my_pkg::state_t;
Daha güvenli ve okunabilir bir yöntemdir. Sadece
state_t
görünür hale gelir.
🔹 3. Doğrudan Paket Adı Üzerinden Kullanmak (Scoped Access)#
state_t s;
s = my_pkg::IDLE;
Bu yöntem isim çakışmalarını önlemek için idealdir.
🧠 Neden Package Kullanmalıyım?#
Avantaj | Açıklama |
---|---|
Kod tekrarını azaltır | Ortak typedef, parametre, sabit ve fonksiyonlar tek yerde |
Testbench’te standartlaşma | UVM gibi ortamlarda ortak yapı tanımlarına olanak tanır |
Büyük projelerde düzen | Her modül kendi package ‘ını kullanabilir |
Tip güvenliği sağlar | Her package kendine ait namespace içerir |
🧪 Kullanım Örneği: Tasarım + Testbench#
// my_defs_pkg.sv
package my_defs_pkg;
typedef logic [31:0] word_t;
typedef enum {REQ, RESP} tx_type_t;
endpackage
// dut.sv
import my_defs_pkg::*;
module dut(input word_t a, b, output word_t sum);
assign sum = a + b;
endmodule
// testbench.sv
import my_defs_pkg::*;
initial begin
word_t a = 32'h10;
word_t b = 32'h20;
tx_type_t mode = REQ;
...
end
🛠️ package
İçinde Neler Tanımlanabilir?#
Tanım Türü | Destekleniyor |
---|---|
typedef , enum , struct | ✅ Evet |
parameter , localparam | ✅ Evet |
function , task | ✅ Evet |
interface , module | ❌ Hayır (ancak dışarıda çağrılır) |
⚠️ Dikkat Edilmesi Gerekenler#
package
module değil, derleme zamanı yapısıdır. İçindealways
,initial
blokları kullanılamaz.import
ifadesi dosyanın en başında kullanılmalıdır.- Aynı isimli tanımlar farklı
package
’larda olabilir — namespace çakışması olmaz.
🧠 package
vs include
#
Özellik | package | include |
---|---|---|
Modüler yapı | ✅ Evet | ❌ Sadece metin yapıştırma |
Namespace desteği | ✅ Var | ❌ Yok |
Derleme zamanı | ✅ Derleyici tarafından tanınır | ❌ Preprocessor çalıştırır |
Hata izolasyonu | ✅ Daha kolay | ❌ Hata takibi zor |
✅ Özet#
package
, tekrar kullanılabilir veri tipleri ve sabitler tanımlamak için idealdir.import
ile global erişim sağlanır.my_pkg::X
şeklinde erişim, namespace çakışmalarını önler.- UVM gibi doğrulama ortamlarında
package
kullanımı endüstri standardıdır.
// Tavsiye edilen kullanım
import my_util_pkg::my_function;
import uvm_pkg::*;
Hazır, okunabilir, modüler ve yeniden kullanılabilir SystemVerilog projeleri için package
yapısı vazgeçilmezdir.
// Best practice
import my_util_pkg::my_function;
import uvm_pkg::*;
Packages help you write cleaner, safer, and more modular SystemVerilog code.
// === File: my_pkg.sv ===
package my_pkg;
typedef enum logic [1:0] {IDLE, RUN, STOP} state_t;
int global_counter;
function int add(int a, b);
return a + b;
endfunction
endpackage
// === File: dut.sv ===
import my_pkg::*;
module dut(input logic clk,
input logic [3:0] a, b,
output logic [4:0] result,
output my_pkg::state_t state);
assign result = add(a, b);
assign state = RUN;
endmodule
// === File: tb_pkg_demo.sv ===
import my_pkg::*;
module tb_pkg_demo;
logic clk = 0;
logic [3:0] a = 4'd7, b = 4'd9;
logic [4:0] result;
state_t current_state;
// Clock generation
always #5 clk = ~clk;
// DUT instantiation
dut u_dut (
.clk(clk),
.a(a),
.b(b),
.result(result),
.state(current_state)
);
initial begin
#10;
$display("Result = %0d", result);
$display("State = %s", current_state.name());
#10 $finish;
end
endmodule
📘 Modül İçinde Sınırlı package
Import Kullanımı#
SystemVerilog 2012 ile birlikte, bir package
‘i doğrudan bir modül, interface veya fonksiyon tanımı içinde import
edebilirsin.
Bu şekilde yapılan import
, sadece ilgili kapsamda (scope) geçerli olur, dosyanın tamamını etkilemez.
Bu yöntem özellikle isim çakışmalarını önlemek ve modülerliği artırmak açısından büyük projelerde oldukça faydalıdır.
✅ Örnek: Modül İçinde Scoped import
Kullanımı#
module tb_pkg_demo import my_pkg::*;
logic [3:0] a = 4'd5, b = 4'd3;
logic [4:0] result;
state_t s;
initial begin
result = add(a, b);
s = RUN;
$display("Result = %0d, State = %s", result, s.name());
end
endmodule
🔎 Burada
my_pkg
paketindeki tüm semboller sadecetb_pkg_demo
modülünün içinde görünür olur. Diğer modüller buimport
’tan etkilenmez.