Clocking Block

Gün 5: Arayüzler, Assertion ve Coverage | Zamanlama blokları, setup/hold yönetimi, APB protokolü

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;   // Setup/hold zamanlari
    
    output psel;
    output penable;
    output pwrite;
    output paddr;
    output pwdata;
    input  prdata;
    input  pready;
  endclocking

  // Modport'lar clocking block referansi ile
  modport tb (clocking cb, input clk);

  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
    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