Lab 5: Interface + Coverage

Gün 5: Arayüzler, Assertion ve Coverage | Interface, Virtual Interface, Driver ve Coverage entegrasyonu

Kaynak Kod

// =============================================================================
// GUN 5 - Lab 5: Interface + Virtual Interface + Driver + Coverage
// =============================================================================

// Interface tanimi
interface mem_if(input logic clk);
  logic        rst_n;
  logic        cs;       // chip select
  logic        we;       // write enable
  logic [7:0]  addr;
  logic [31:0] wdata;
  logic [31:0] rdata;
  logic        ack;

  clocking cb @(posedge clk);
    default input #1 output #1;
    output cs, we, addr, wdata;
    input  rdata, ack;
  endclocking

  modport tb  (clocking cb, output rst_n, input clk);
  modport dut (input clk, rst_n, cs, we, addr, wdata, output rdata, ack);
endinterface

// Basit Bellek DUT
module memory_dut(mem_if.dut mif);
  logic [31:0] mem [256];

  always @(posedge mif.clk or negedge mif.rst_n) begin
    if (!mif.rst_n) begin
      mif.rdata <= 0;
      mif.ack   <= 0;
    end else if (mif.cs) begin
      if (mif.we) begin
        mem[mif.addr] <= mif.wdata;
      end else begin
        mif.rdata <= mem[mif.addr];
      end
      mif.ack <= 1;
    end else begin
      mif.ack <= 0;
    end
  end
endmodule

// Transaction sinifi
class MemTransaction;
  rand bit        we;
  rand bit [7:0]  addr;
  rand logic [31:0] wdata;
  logic [31:0]    rdata;
  int             id;
  static int      count = 0;

  constraint c_addr {
    addr inside {[0:63]};
  }

  constraint c_data {
    we -> wdata != 0;
    !we -> wdata == 0;
  }

  function new();
    id = count++;
  endfunction

  function void display(string prefix = "");
    $display("  %sTXN#%0d | %s | Addr=0x%02h | WData=0x%08h | RData=0x%08h",
             prefix, id, we ? "WR" : "RD", addr, wdata, rdata);
  endfunction
endclass

// Driver sinifi (virtual interface kullanan)
class MemDriver;
  virtual mem_if.tb vif;
  mailbox #(MemTransaction) mbx;
  int driven_count = 0;

  function new(virtual mem_if.tb vif, mailbox #(MemTransaction) mbx);
    this.vif = vif;
    this.mbx = mbx;
  endfunction

  task run();
    MemTransaction txn;
    forever begin
      mbx.get(txn);
      @(vif.cb);
      vif.cb.cs    <= 1;
      vif.cb.we    <= txn.we;
      vif.cb.addr  <= txn.addr;
      vif.cb.wdata <= txn.wdata;
      @(vif.cb);
      wait(vif.cb.ack);
      if (!txn.we)
        txn.rdata = vif.cb.rdata;
      vif.cb.cs <= 0;
      driven_count++;
      txn.display("[Driver] ");
    end
  endtask

  task reset();
    vif.rst_n = 0;
    vif.cb.cs    <= 0;
    vif.cb.we    <= 0;
    vif.cb.addr  <= 0;
    vif.cb.wdata <= 0;
    repeat(5) @(vif.cb);
    vif.rst_n = 1;
    @(vif.cb);
    $display("  [Driver] Reset tamamlandi");
  endtask
endclass

// Coverage sinifi
class MemCoverage;
  covergroup mem_cg with function sample(bit we, bit [7:0] addr, logic [31:0] data);
    cp_we: coverpoint we {
      bins read  = {0};
      bins write = {1};
    }

    cp_addr: coverpoint addr {
      bins low   = {[0:15]};
      bins mid   = {[16:31]};
      bins high  = {[32:47]};
      bins upper = {[48:63]};
    }

    cp_data: coverpoint data {
      bins zero     = {0};
      bins nonzero  = {[1:$]};
    }

    cx_we_addr: cross cp_we, cp_addr;
  endgroup

  mem_cg cg;

  function new();
    cg = new();
  endfunction

  function void sample(MemTransaction txn);
    cg.sample(txn.we, txn.addr, txn.wdata);
  endfunction

  function void report();
    $display("\n  --- Kapsam Raporu ---");
    $display("  Toplam     : %.1f%%", cg.get_coverage());
    $display("  cp_we      : %.1f%%", cg.cp_we.get_coverage());
    $display("  cp_addr    : %.1f%%", cg.cp_addr.get_coverage());
    $display("  cp_data    : %.1f%%", cg.cp_data.get_coverage());
    $display("  cx_we_addr : %.1f%%", cg.cx_we_addr.get_coverage());
  endfunction
endclass

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

  mem_if mif(clk);
  memory_dut dut(mif);

  mailbox #(MemTransaction) mbx;
  MemDriver   drv;
  MemCoverage cov;

  initial begin
    $display("============================================================");
    $display("  LAB 5: Interface + Driver + Coverage");
    $display("============================================================\n");

    mbx = new();
    drv = new(mif, mbx);
    cov = new();

    // Reset
    drv.reset();

    // Driver'i arka planda calistir
    fork
      drv.run();
    join_none

    // Islemler uret ve kuyruga ekle
    repeat (50) begin
      MemTransaction txn = new();
      assert(txn.randomize()) else $fatal(1, "Randomize hata!");
      cov.sample(txn);
      mbx.put(txn);
    end

    // Tum islemlerin bitmesini bekle
    wait(mbx.num() == 0);
    #100;

    // Rapor
    $display("\n  --- Istatistikler ---");
    $display("  Toplam surulen: %0d", drv.driven_count);
    cov.report();

    $display("\n============================================================");
    $display("  LAB 5 TAMAMLANDI");
    $display("============================================================");
    $finish;
  end
endmodule