EDA Playground'da Dene

Virtual Interface

Gün 5: Arayüzler, Assertion ve Coverage | Sınıflar içinden fiziksel arayüze erişim

Kaynak Kod

// =============================================================================
// GUN 5 - Konu 3: Virtual Interface (Interface'e Class'tan Erişim)
// =============================================================================

interface simple_if(input logic clk);
  logic       valid;
  logic       ready;
  logic [7:0] data;

  // Clocking block sinyalleri clock edge'i ile senkronize eder
  clocking cb @(posedge clk);
    default input #1step output #0;
    output valid, data;
    input  ready;
  endclocking

  modport tb  (clocking cb, input clk);
  modport dut (input clk, valid, data, output ready);
endinterface

// --- Class: Virtual Interface kullanan Driver ---
class Driver;
  virtual simple_if.tb vif;  // Virtual interface handle
  int txn_count = 0;

  function new(virtual simple_if.tb vif);
    this.vif = vif;
  endfunction

  task drive(input logic [7:0] data);
    @(vif.cb);
    vif.cb.valid <= 1;
    vif.cb.data  <= data;
    
    // Senkron bir şekilde ready'i bekle
    do begin
      @(vif.cb);
    end while (vif.cb.ready !== 1'b1);
    
    vif.cb.valid <= 0;
    txn_count++;
    $display("  [%0t][Driver] Sent: data=0x%02h (#%0d)", $time, data, txn_count);
  endtask

  task reset();
    vif.cb.valid <= 0;
    vif.cb.data  <= 0;
    @(vif.cb);
    $display("  [%0t][Driver] Reset applied", $time);
  endtask
endclass

// --- Class: Monitor ---
class Monitor;
  virtual simple_if.tb vif;
  int observed_count = 0;
  logic [7:0] observed_data [$];

  function new(virtual simple_if.tb vif);
    this.vif = vif;
  endfunction

  task run();
    $display("  [Monitor] Listening started");
    forever begin
      @(vif.cb);
      // === equality check kullan! X ve Z geldiğinde false positive durum olabilir
      if (vif.cb.valid === 1'b1 && vif.cb.ready === 1'b1) begin
        observed_count++;
        observed_data.push_back(vif.cb.data);
        $display("  [%0t][Monitor] Observed: data=0x%02h (#%0d)",
                 $time, vif.cb.data, observed_count);
      end
    end
  endtask
endclass

// Simple DUT
module simple_dut(simple_if.dut sif);
  always @(posedge sif.clk) begin
    sif.ready <= sif.valid;  // Ready - 1 cycle delay
  end
endmodule

// Top-level
module virtual_interface;
  logic clk = 0;
  always #5 clk = ~clk;

  simple_if sif(clk);
  simple_dut dut(sif);

  Driver  drv;
  Monitor mon;
  
  initial begin
    $dumpfile("dump.vcd"); $dumpvars;
  end
  
  initial begin
    $display("=== Virtual Interface ===\n");

    drv = new(sif);
    mon = new(sif);

    // Monitor'ü çalıştır
    fork
      mon.run();
    join_none

    // Reset sequence
    drv.reset();
    #20;

    // Send data
    for (int i = 0; i < 8; i++) begin
      drv.drive(i * 16 + 'hA0);
    end

    // Monitor'un son transaction'ı da algılaması için biraz beklet!
    // ÖNEMLİ NOT: Beklesek bile algılamayacak, sizce neden?
    // fixed.sv'de cevabı var, bu dosyanın içeriğini silip onu yapıştırabilirsin.
    #50;
    $display("\n  --- Results ---");
    $display("  Driver sent     : %0d", drv.txn_count);
    $display("  Monitor observed: %0d", mon.observed_count);
    $display("  Observed data   : %p", mon.observed_data);

    $display("\n=== End of Virtual Interface ===");
    $finish;
  end
endmodule