EDA Playground'da Dene

ALU Interface Tanımı

Gün 6: Bitirme Projesi - Bölüm 1 | Bitirme projesi: ALU interface ve clocking block

Interface (arayüz), testbench ile DUT arasındaki tüm sinyalleri tek bir çatı altında toplayan SystemVerilog yapısıdır. ALU doğrulama mimarimizde alu_if, sınıf tabanlı testbench'in (driver, monitor) sinyal seviyesindeki DUT'a bağlanmasını sağlayan köprüdür.

Interface ve Mimarideki Yeri

Sınıf tabanlı bir testbench'te driver ve monitor nesneleri statik modül portlarına doğrudan bağlanamaz. Aradaki bağlantıyı virtual interface kurar: çevre bileşenleri alu_if'in bir referansını (handle) tutar ve sinyallere bu referans üzerinden erişir.

Bu arayüz üç temel araç sunar:

  • Clocking block: Sinyallerin saate göre ne zaman örnekleneceğini/sürüleceğini tanımlar, böylece yarış koşullarını (race condition) ortadan kaldırır.
  • Modport: Her bileşenin hangi sinyallere hangi yönde (giriş/çıkış) erişebileceğini kısıtlar.
  • Ortak saat: clk dışarıdan (testbench top'tan) gelir ve tüm clocking block'ları tetikler.

Clocking Block Neden Önemli

drv_cb ve mon_cb clocking block'ları @(posedge clk) ile çalışır ve default input #1 output #1 skew (kayma) değerlerine sahiptir:

  • #1 input skew: Sinyaller saat kenarından 1 birim önce örneklenir; yani driver'ın o çevrimde sürdüğü değerler değil, kararlı eski değerler okunur.
  • #1 output skew: Driver çıkışları saat kenarından 1 birim sonra sürülür; bu, DUT'un girişleri kararlı şekilde görmesini sağlar.

drv_cb hem okuma hem yazma yaparken, mon_cb yalnızca okuma (input) yapar çünkü monitor pasif bir gözlemcidir ve sinyallere asla müdahale etmez.

Modport ile Erişim Kısıtlama

  • modport driver: drv_cb üzerinden veri sürer, rst_n'i doğrudan çıkış olarak kontrol eder.
  • modport monitor: mon_cb üzerinden yalnızca izler; sinyallere yazamaz.
  • modport dut: DUT'un gördüğü yön bilgisini tanımlar (girişler/çıkışlar).

Kaynak Kod

// =============================================================================
// GUN 6 - Konu 1: ALU Interface ve Clocking Block Tanimlamalari
// =============================================================================

interface alu_if(input logic clk);
  // Sinyaller
  logic        rst_n;
  logic        in_valid;
  logic [7:0]  operand_a;
  logic [7:0]  operand_b;
  logic [2:0]  opcode;
  logic        out_valid;
  logic [15:0] result;
  logic [3:0]  flags;

  // Testbench clocking block
  clocking drv_cb @(posedge clk);
    default input #1 output #1;
    output in_valid, operand_a, operand_b, opcode;
    input  out_valid, result, flags;
  endclocking

  // Monitor clocking block (sadece okuma)
  clocking mon_cb @(posedge clk);
    default input #1;
    input in_valid, operand_a, operand_b, opcode;
    input out_valid, result, flags;
  endclocking

  // Modport'lar
  modport driver  (clocking drv_cb, output rst_n, input clk);
  modport monitor (clocking mon_cb, input clk, rst_n);
  modport dut (
    input  clk, rst_n, in_valid, operand_a, operand_b, opcode,
    output out_valid, result, flags
  );
endinterface

Kodun Açıklaması

  • interface alu_if(input logic clk);: Arayüz, saatini dışarıdan parametre olarak alır. Böylece testbench top'taki tek bir saat üreteci hem DUT'u hem de tüm clocking block'ları besler.
  • Sinyal tanımları: DUT portlarıyla aynı isimde rst_n, in_valid, operand_a, operand_b, opcode (girişler) ve out_valid, result, flags (çıkışlar) tanımlanır.
  • clocking drv_cb: Driver'ın kullandığı clocking block. output in_valid, operand_a, operand_b, opcode ile sürülecek sinyalleri, input out_valid, result, flags ile okunacak sinyalleri belirtir.
  • clocking mon_cb: Monitor'ün kullandığı clocking block. Tüm sinyaller input'tur; monitor yalnızca gözlemler, hiçbir şey sürmez.
  • modport driver: drv_cb clocking block'unu sunar ve rst_n'i doğrudan output yapar. Driver, reset sırasında rst_n'e clocking block dışından erişebilsin diye bu ayrıcalık verilmiştir.
  • modport monitor: mon_cb ile salt-okuma erişimi sağlar.
  • modport dut: DUT modülünün port yönlerini tanımlar; sentez/bağlantı tarafında DUT'un nasıl bağlanacağını netleştirir.

Önemli Noktalar

  • Virtual interface sayesinde sınıf tabanlı bileşenler statik sinyallere erişebilir; driver virtual alu_if.driver, monitor virtual alu_if.monitor tipinde referans tutar.
  • Clocking block skew (#1) kullanımı, driver ve DUT arasındaki yarış koşullarını önler; sinyaller her zaman kararlı değerlerinden okunur/yazılır.
  • rst_n'in clocking block dışında, doğrudan output olması bilinçli bir tasarımdır: reset darbesi genellikle clocking semantiğinin dışında, doğrudan kontrol edilmek istenir.
  • Monitor'ün tüm sinyalleri input olması pasifliğini garanti eder; bir monitor asla DUT girişlerini değiştirmemelidir.
  • Sinyal isimlerinin DUT portlarıyla aynı tutulması, top seviyesinde .port(aif.port) bağlamayı sade ve hatasız kılar.
  • Driver ve monitor neden ayrı clocking block kullanır? Gün 5'te öğrendiğiniz kural: bir clocking block'un output sinyali okunamaz. Monitor in_valid, operand_a gibi driver'ın sürdüğü sinyalleri okumak zorunda olduğu için kendi tümü-input penceresine (mon_cb) ihtiyaç duyar. Tek clocking block ile bu mümkün olmazdı.
  • default input #1 ile #1step farkı: Bu projede #1 seçilmiştir; timescale 1ns/1ps ile bu 1 ns demektir ve saat periyodu 10 ns olduğu için güvenli bir aralıktır. Daha taşınabilir seçim #1step'tir (zaman biriminden bağımsız); projeyi farklı bir timescale ile derlerseniz #1'in anlamı değişir.

Sinyal Yönleri Matrisi

Sinyal DUT drv_cb (driver) mon_cb (monitor)
clk input olay kaynağı olay kaynağı
rst_n input modport üzerinden ham output input (modport)
in_valid, operand_a/b, opcode input output input
out_valid, result, flags output input input

Tabloyu okuma kuralı: bir sinyal tek bir sürücüye sahip olmalıdır. in_valid'in tek sürücüsü driver'dır (DUT ve monitor yalnızca okur); result'ın tek sürücüsü DUT'tur. Bu matrisi çizmek, modport hatalarını kodu yazmadan yakalamanın en hızlı yoludur.

Sık Yapılan Hatalar

  • rst_n'i clocking block'a koymak: Reset genellikle saatten bağımsız, asenkron bir sinyaldir; clocking block üzerinden sürülürse yalnızca saat kenarında değişir ve asenkron reset davranışı test edilemez. Bu yüzden modport'ta ham output olarak verilir.
  • Monitor modport'una drv_cb vermek: Derlenir ama monitor driver'ın sürdüğü sinyalleri okuyamaz (clocking output); ayrıca monitor kazara sürücü olabilir.
  • Interface'i alu_if aif(); ile saatsiz örneklemek: clk portu bağlanmazsa clocking block'lar hiç tetiklenmez; driver ilk @(vif.drv_cb)'de sonsuza kadar bekler.
  • DUT'u interface ile doğrudan bağlamayı beklemek: Bu projede DUT klasik port listesine sahiptir (alu dut (.clk(aif.clk), ...)); modport dut yalnızca yön belgelemesi ve istenirse alu dut(aif.dut) biçiminde bağlanacak bir DUT sarmalayıcısı için hazırdır.

Kendinizi Deneyin

  1. mon_cb'den input in_valid satırını silin. Hangi ders dosyası (monitor) derlenemez hale geldi? Hata mesajını not alın.
  2. default input #1 output #1 ifadesini #1step / #0 yapın; Gün 7'deki final testbench'i çalıştırdığınızda scoreboard sonuçları değişti mi? Neden değişmemesi gerekir?
  3. Interface'e logic busy; sinyali ekleyin (DUT'tan çıkış). Yalnızca interface'i ve mon_cb'yi güncelleyin; driver dosyasına dokunmanız gerekmediğini doğrulayın.
  4. Interface'in içine Gün 5'teki SVA bilginizle bir assertion yazın: @(posedge clk) disable iff (!rst_n) in_valid |=> out_valid. Nereye yazılır, kim denetler?
Hızlı Kontrol: Monitor'ün in_valid sinyalini okuyabilmesi için neden ayrı bir clocking block gerekir?

Çünkü in_valid, drv_cb içinde output olarak tanımlıdır ve clocking block output'ları okunamaz. mon_cb aynı sinyali input olarak tanımlar; monitor bu pencereden saat kenarında örneklenmiş değeri güvenle okur ve asla sürücü olamaz.