Interface ve Modport

Gün 5: Arayüzler, Assertion ve Coverage | Sinyal gruplama, erişim yönü tanımlama, master/slave/monitor

Kaynak Kod

// =============================================================================
// GUN 5 - Konu 1: Interface Kavrami ve Modports
// =============================================================================

// Interface tanimi: Sinyalleri gruplar
interface bus_if(input logic clk);
  logic        rst_n;
  logic        valid;
  logic        ready;
  logic        rw;        // 0=read, 1=write
  logic [7:0]  addr;
  logic [31:0] wdata;
  logic [31:0] rdata;
  logic        resp;      // 0=OK, 1=ERROR

  // Modport: Her bilesenin sinyallere erisim yonunu tanimlar
  modport master (
    input  clk, rst_n, ready, rdata, resp,
    output valid, rw, addr, wdata
  );

  modport slave (
    input  clk, rst_n, valid, rw, addr, wdata,
    output ready, rdata, resp
  );

  modport monitor (
    input clk, rst_n, valid, ready, rw, addr, wdata, rdata, resp
  );
endinterface

// Master modulu
module bus_master(bus_if.master bus);
  int txn_count = 0;

  task write(input logic [7:0] address, input logic [31:0] data);
    @(posedge bus.clk);
    bus.valid <= 1;
    bus.rw    <= 1;
    bus.addr  <= address;
    bus.wdata <= data;
    @(posedge bus.clk);
    wait(bus.ready);
    bus.valid <= 0;
    txn_count++;
    $display("  [%0t][Master] WRITE: Addr=0x%02h, Data=0x%08h", $time, address, data);
  endtask

  task read(input logic [7:0] address, output logic [31:0] data);
    @(posedge bus.clk);
    bus.valid <= 1;
    bus.rw    <= 0;
    bus.addr  <= address;
    @(posedge bus.clk);
    wait(bus.ready);
    data = bus.rdata;
    bus.valid <= 0;
    txn_count++;
    $display("  [%0t][Master] READ:  Addr=0x%02h, Data=0x%08h", $time, address, data);
  endtask
endmodule

// Slave modulu
module bus_slave(bus_if.slave bus);
  logic [31:0] memory [256];

  always @(posedge bus.clk or negedge bus.rst_n) begin
    if (!bus.rst_n) begin
      bus.ready <= 0;
      bus.rdata <= 0;
      bus.resp  <= 0;
    end else if (bus.valid) begin
      #2;
      if (bus.rw) begin  // Write
        memory[bus.addr] <= bus.wdata;
        bus.resp <= 0;
      end else begin     // Read
        bus.rdata <= memory[bus.addr];
        bus.resp  <= 0;
      end
      bus.ready <= 1;
      @(posedge bus.clk);
      bus.ready <= 0;
    end
  end
endmodule

// Monitor modulu
module bus_monitor(bus_if.monitor bus);
  int total_reads = 0, total_writes = 0;

  always @(posedge bus.clk) begin
    if (bus.valid && bus.ready) begin
      if (bus.rw) begin
        total_writes++;
        $display("  [%0t][Monitor] WRITE gozlemlendi: Addr=0x%02h", $time, bus.addr);
      end else begin
        total_reads++;
        $display("  [%0t][Monitor] READ gozlemlendi:  Addr=0x%02h", $time, bus.addr);
      end
    end
  end
endmodule

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

  // Interface ornekleme
  bus_if bif(clk);

  // Modul baglantilari
  bus_master  mst(bif);
  bus_slave   slv(bif);
  bus_monitor mon(bif);

  logic [31:0] read_data;

  initial begin
    $display("=== Interface ve Modport ===\n");

    // Reset
    bif.rst_n = 0;
    #20;
    bif.rst_n = 1;
    #10;

    // Yazma islemleri
    mst.write(8'h10, 32'hDEAD_BEEF);
    mst.write(8'h20, 32'hCAFE_BABE);
    mst.write(8'h30, 32'h1234_5678);

    #20;

    // Okuma islemleri
    mst.read(8'h10, read_data);
    mst.read(8'h20, read_data);

    #50;
    $display("\n  --- Istatistikler ---");
    $display("  Master islem sayisi: %0d", mst.txn_count);
    $display("  Monitor - Read: %0d, Write: %0d", mon.total_reads, mon.total_writes);

    $display("\n=== Interface ve Modport Sonu ===");
    $finish;
  end
endmodule