Clocking Block
Gün 5: Arayüzler, Assertion ve Coverage | Zamanlama blokları, setup/hold yönetimi, APB protokolü
🌟🌟Okuma Önerisi: Taming Testbench Timing
Bu derste clocking block (zamanlama bloğu) yapısını ve test ortamı ile DUT arasındaki yarış koşullarını (race condition) nasıl ortadan kaldırdığını öğreneceğiz. Örnek olarak basit bir APB protokolünü clocking block üzerinden süreceğiz.
Clocking Block Neden Gerekli?
Bir test ortamı (testbench), DUT ile aynı saat kenarında sinyal sürerse iki kritik problem ortaya çıkar:
- Yarış koşulu (race condition): TB sinyali tam saat kenarında değiştirir, DUT da aynı kenarda örnekler. Hangisinin önce çalışacağı belirsizdir; simülatöre göre sonuç değişebilir.
- Setup/Hold belirsizliği: Gerçek donanımda sinyaller saat kenarından belirli bir süre önce kararlı olmalı (setup) ve kenardan sonra bir süre korunmalıdır (hold). Bunu modellemeden yapılan testler gerçekçi değildir.
clocking block, bir saat olayına (@(posedge clk)) göre sinyallerin ne zaman örnekleneceğini (input) ve ne zaman sürüleceğini (output) merkezi olarak tanımlar. Böylece testbench, DUT'tan otomatik olarak güvenli bir zaman aralığında ayrılır.
Input/Output Skew ve 1step
Koddaki default input #1step output #1 satırı zamanlamanın kalbidir:
input #1step: Girişler, saat kenarından bir simülasyon adımı önce (yani Preponed bölgesinde) örneklenir. Bu, DUT henüz aynı kenarda değer değiştirmeden, kararlı eski değeri okumayı garanti eder; böylece yarış koşulu yok olur.output #1: Çıkışlar, saat kenarından 1 zaman birimi sonra sürülür. Bu, DUT'un girişleri kenarın hemen üzerinde değil, küçük bir gecikmeyle görmesini sağlar (hold benzeri davranış).
Test kodunda aif.cb.psel <= 1 gibi atamalar ve @(aif.cb) ile beklemeler, doğrudan ham sinyallere değil clocking block üzerinden yapıldığı için bu zamanlama kuralları otomatik uygulanır.
Kaynak Kod
// =============================================================================
// GUN 5 - Konu 2: Clocking Blocks (Zamanlama Bloklari)
// =============================================================================
interface apb_if(input logic clk);
logic psel;
logic penable;
logic pwrite;
logic [7:0] paddr;
logic [31:0] pwdata;
logic [31:0] prdata;
logic pready;
// Clocking Block: Testbench zamanlama yonetimi
// Sinyallerin ornekleme ve surme zamanlarini tanimlar
clocking cb @(posedge clk);
default input #1step output #1; // Input output skew
output psel;
output penable;
output pwrite;
output paddr;
output pwdata;
input prdata;
input pready;
endclocking
modport dut (
input clk, psel, penable, pwrite, paddr, pwdata,
output prdata, pready
);
endinterface
// Basit APB Slave (DUT rolunde)
module apb_slave(apb_if.dut apb);
logic [31:0] reg_file [256];
always @(posedge apb.clk) begin
apb.pready <= 0;
if (apb.psel && apb.penable) begin
if (apb.pwrite)
reg_file[apb.paddr] <= apb.pwdata;
else
apb.prdata <= reg_file[apb.paddr];
apb.pready <= 1;
end
end
endmodule
module clocking_block;
logic clk = 0;
always #5 clk = ~clk;
apb_if aif(clk);
apb_slave dut(aif);
// Clocking block ile surme
task apb_write(input logic [7:0] addr, input logic [31:0] data);
// Setup phase
aif.cb.psel <= 1;
aif.cb.pwrite <= 1;
aif.cb.paddr <= addr;
aif.cb.pwdata <= data;
aif.cb.penable <= 0;
@(aif.cb);
// Access phase
aif.cb.penable <= 1;
@(aif.cb);
wait(aif.cb.pready);
// Idle
aif.cb.psel <= 0;
aif.cb.penable <= 0;
$display(" [%0t] APB Write: Addr=0x%02h, Data=0x%08h", $time, addr, data);
endtask
task apb_read(input logic [7:0] addr, output logic [31:0] data);
aif.cb.psel <= 1;
aif.cb.pwrite <= 0;
aif.cb.paddr <= addr;
aif.cb.penable <= 0;
@(aif.cb);
aif.cb.penable <= 1;
@(aif.cb);
wait(aif.cb.pready);
data = aif.cb.prdata;
aif.cb.psel <= 0;
aif.cb.penable <= 0;
$display(" [%0t] APB Read: Addr=0x%02h, Data=0x%08h", $time, addr, data);
endtask
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
initial begin
logic [31:0] rdata;
$display("=== Clocking Block ===\n");
// Baslangic degerleri
aif.cb.psel <= 0;
aif.cb.penable <= 0;
#20;
// Yazma
apb_write(8'h00, 32'hAAAA_BBBB);
apb_write(8'h04, 32'hCCCC_DDDD);
// Okuma
apb_read(8'h00, rdata);
apb_read(8'h04, rdata);
#50;
$display("\n=== Clocking Block Sonu ===");
$finish;
end
endmodule
Kodun Açıklaması
interface apb_if(input logic clk): APB sinyallerini (psel,penable,pwrite,paddr,pwdata,prdata,pready) gruplar.clocking cb @(posedge clk): Tüm testbench zamanlamasını yöneten bloktur.default input #1step output #1ile varsayılan örnekleme/sürme gecikmeleri belirlenir. TB'nin sürdüğü sinyaller (psel,penable,pwrite,paddr,pwdata)output; DUT'tan okunanlar (prdata,pready)inputolarak tanımlanır.modport dut: DUT'un bakış açısını verir; TB'nin sürdüğü sinyalleriinput, ürettiklerinioutputalır. DUT clocking block'u kullanmaz, doğrudan ham sinyalleri kullanır.apb_slavemodülü:posedge apb.clkile çalışır. Her saattepready'yi varsayılan0yapar;apb.psel && apb.penable(APB access fazı) doğruysapwrite'a görereg_file'a yazar ya da oradanprdata'ya okur vepready'yi 1 yapar.apb_writetask'i: APB'nin iki fazını uygular. Önce setup faz (psel=1,penable=0) kurulup@(aif.cb)ile bir saat beklenir; sonra access faz (penable=1) sürülür vewait(aif.cb.pready)ile DUT onayı beklenir. Tüm atamalaraif.cb.*üzerinden, yani clocking block aracılığıyla yapılır.apb_readtask'i: Aynı setup/access akışını okuma için uygular vedata = aif.cb.prdataile veriyi clocking block'tan örneklenmiş olarak alır.clocking_block(top):clküretir,apb_if aif(clk)veapb_slave dut(aif)örneklenir. Başlangıç değerleri verildikten sonra iki yazma ve iki okuma işlemi yürütülür.
Önemli Noktalar
@(aif.cb)ile@(posedge clk)farkı: Clocking block olayını (@(aif.cb)) beklemek, ham saat kenarını beklemekten farklı olarak skew kurallarını devreye sokar ve yarış koşullarını engeller.- Clocking block sinyaline
<=ile yazın:aif.cb.psel <= 1gibi non-blocking atamalar, çıkış skew'ine (output #1) uygun şekilde değeri planlı zamanda sürer. Blocking atama (=) clocking block çıkışlarında uygun değildir. 1stepözel bir değerdir:#1step, zaman birimine bağlı olmayan en küçük adımdır ve Preponed bölgesinde örnekleme yaparak en güvenli giriş okumasını sağlar.- DUT clocking block kullanmaz: Zamanlama bloğu yalnızca testbench tarafının senkronizasyon aracıdır; DUT sentezlenebilir mantıkla ham sinyalleri kullanır.
- Tek merkezden zamanlama: Tüm gecikme kararlarının clocking block'ta toplanması, dağınık
#delayifadelerine kıyasla bakımı kolaylaştırır ve hata riskini azaltır.