⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apb.v

📁 systemverilog是新出现的一种高级硬件描述和验证语言
💻 V
字号:
// ________________________________________________________________ apb.v ___
//
// Interface model for ARM APB (AMBA Peripheral Bus),
// used as an example of inter-module communication
// with interfaces.
//
// The bus is quite simple and can have only one master.
// The master can perform read and write cycles to one location
// at a time (no burst transfers).  The bus is fully synchronous
// to the rising edges of an externally supplied clock.
//
// Note that APB doesn't specify a global reset signal, so any reset
// required by devices on the bus must be supplied separately and
// doesn't form part of this interface.
//
// The interface also offers procedural entry points so that
// a test fixture can perform read and write cycles without
// needing to create a bus functional model of the bus master.
// Unfortunately, VCS 7.1 doesn't yet allow us to pass these
// procedural entry points through a modport; we have to
// invoke them using hierarchical names, just as with a
// typical Verilog bus functional model (BFM).
//
//
// Revision information:
// =====================
//
// v0.0  19-Jan-2004  Jonathan Bromley
//    Modified from tci_bus.v
//
// v0.1  25-Jan-2004  Jonathan Bromley
//    Improved internal documentation
//
// __________________________________________________________________________



`timescale 1ns/100ps



// _________________________________________________________ GLOBAL STUFF ___

// Publicly visible typedefs for APB data and address types:
//
typedef logic [15:0] T_APB_d;
typedef logic [15:0] T_APB_a;

// __________________________________________________________________________



// _________________________________________________ INTERFACE DEFINITION ___

interface APB #(parameter master_Tco = 1);

  // See also modports and tasks:
  //
  // modport RTL_slave   -- connect any RTL slave model to one of these
  // modport RTL_master  -- connect an RTL master model to this (one only)
  // modport TF_master   -- Connect a behavioural master to this (one only)
  //   task read;          -- BFM entry point for behavioural tests
  //   task write;         -- BFM entry point for behavioural tests

// __________________________________________________________________________



// _________________________________________________ PHYSICAL BUS SIGNALS ___

  // Bus clock, generated by external master (typically AHB-APB bridge).
  //
  // NOTE: Even if there is no external master, but only a testbench using
  // the BFM read and write entry points, it is ESSENTIAL for the
  // environment to provide a suitable clock on this signal.
  // This can be done either directly or through the RTL_master modport.
  //
  logic  PCLK;

  // Select signal.  Each slave must qualify this signal
  // with the appropriate address, since we can't
  // parameterise the slave's modport.
  //
  logic    psel = 0;

  // Address signal from master
  //
  T_APB_a  PADDR;

  // Write data, from master
  //
  T_APB_d  PWDATA;

  // Write and enable signals from master
  //
  logic    PWRITE = 0;
  logic    PENABLE = 0;

  // Readback data signal, written by selected slave
  //
  T_APB_d  PRDATA;

// __________________________________________________________________________



// _____________________________________________________________ MODPORTS ___

  // Any slave connects like this...
  //
  modport RTL_slave (
    input  PCLK,    // Slaves get their clock from the bus
    //input  psel,    // Select signal - global for all slaves
    input  PWRITE,  // Active in the clock when address is sent
    input  PENABLE, // Direction control, sent with the address
    input  PADDR,
    input  PWDATA,
    output PRDATA
  ); // modport RTL_slave

  // The one and only master connects like this:
  //
  modport RTL_master (
    output PCLK,    // Master supplies clock to the bus
    output PWRITE,  // Active in the clock when address is sent
    output PENABLE, // Direction control, sent with the address
    output PADDR,
    output PWDATA,
    input  PRDATA
  );  // modport RTL_master

  // Alternatively you can connect a behavioural master
  // to this BFM-like modport:
  //
  modport TF_master (
    output PCLK,                 // Master supplies clock to the bus
    import task write(), read()  // Master calls these tasks to do cycles
  ); // modport TF_master

// __________________________________________________________________________



// _____________________________________________________ BFM ENTRY POINTS ___

  // Non-synthesisable task-call interface for a testbench master
  // so that it can exercise slaves on the bus without the need for
  // a fully-functional model of a master device.


  // Call read and write tasks at the posedge of the clock
  // right at the beginning of the cycle. They return just after
  // the final posedge of the cycle.
  task read (
    input  T_APB_a adrs,
    output T_APB_d data
  );

    time start_delay;

    CheckLastClock(start_delay);

    #(start_delay)
      PADDR    = adrs;
      PWRITE   = 1'b0;
      psel     = 1'b1;

    @(posedge PCLK)
      PENABLE <= #master_Tco 1'b1;

    @(posedge PCLK)
      data     = PRDATA;
      PADDR   <= {$bits(PADDR){1'bx}};
      psel    <= 1'b0;
      PENABLE <= 1'b0;

  endtask // read

  task write (
    input T_APB_a adrs,
    input T_APB_d data
  );

    time start_delay;

    CheckLastClock(start_delay);

    #(start_delay)
      PADDR    = adrs;
      PWDATA   = data;
      PWRITE   = 1'b1;
      psel     = 1'b1;

    @(posedge PCLK)
      PENABLE <= #master_Tco 1'b1;

    @(posedge PCLK)
      PWDATA  <= {$bits(PADDR){1'bx}};
      PADDR   <= {$bits(PADDR){1'bx}};
      psel    <= 1'b0;
      PENABLE <= 1'b0;

  endtask // write

// __________________________________________________________________________



// ____________________________________________ HELPER CODE FOR BFM TASKS ___

  // As always with procedural entry points into a BFM, there is
  // an issue about synchronisation between the moment of task call
  // and the bus's clock.  If the task is called at some random time,
  // its activity must be resynchronised to the bus clock.  However,
  // if it's already synchronised, then we don't want a spurious
  // additional clock wait.  One possible solution to this problem is
  // offered here: the BFM read and write tasks can be called at any
  // time.  If called at or just after a clock edge, BFM activity can
  // proceed as from that clock edge (signals don't need to be set up
  // until one clock-to-valid delay after the clock edge).  If called
  // at any other time, the task is stalled until just after the next
  // clock edge.

  // In order to make this approach work, we need to keep track of
  // the time of the most recent active clock edge.
  //
  always @(posedge PCLK) begin : ClockEdgeLogger

    time LastClock;
    LastClock = $time;

  end // ClockEdgeLogger

  // Now, when a BFM task is called, it uses the time-of-last-clock
  // information to determine whether it can proceed immediately, or
  // must wait until the next clock.  Task checkLastClock() encapsulates
  // this behaviour;  it not only enforces the clock wait if necessary,
  // but also calculates the future time at which the BFM task must
  // apply its valid bus signals.
  //
  // Note that this task will still work correctly even if
  // parameter master_Tco is set to zero.
  //
  task CheckLastClock (output time t);

    // If this task was called as the result of a clock edge,
    // we must be sure that the LastClock value is updated.
    // That's why we need the #0 delay prefix here.
    //
    #0 t = $time - ClockEdgeLogger.LastClock;

    // Are we too late to start the bus cycle on the current clock?
    //
    if (t > master_Tco) begin

      // Yes, we're too late.  Wait for the next clock.
      @(posedge PCLK) t = master_Tco;

    end else begin

      // No, we're in time.  Calculate how long we need to wait
      // before applying the right signals.
      t = master_Tco - t;

    end

  endtask

// __________________________________________________________________________


endinterface // APB

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -