How to use AXI VIP

 

Step1. Create a slave AXI VIP interface

 

interface axi_if ();

 

//-----------------------------------------------------------------------

// AXI Interface setup and hold parameters

//-----------------------------------------------------------------------

  parameter setup_time      = 1;

  parameter hold_time       = 1;

 

  bit  aclk ;

  bit  aresetn ;

 

//-----------------------------------------------------------------------

// AXI Interface Write Address Channel Signals

//-----------------------------------------------------------------------

  wire awvalid ;

  wire [`DW_VIP_AXI_ADDR_PORT_WIDTH-1:0] awaddr ;

  wire [`DW_VIP_AXI_ALEN_PORT_WIDTH-1:0] awlen ;

  wire [`DW_VIP_AXI_ASIZE_PORT_WIDTH-1:0] awsize ;

  wire [`DW_VIP_AXI_ABURST_PORT_WIDTH-1:0] awburst ;

  wire [`DW_VIP_AXI_ALOCK_PORT_WIDTH-1:0] awlock ;

  wire [`DW_VIP_AXI_ACACHE_PORT_WIDTH-1:0] awcache ;

  wire [`DW_VIP_AXI_APROT_PORT_WIDTH-1:0] awprot ;

  wire [`DW_VIP_AXI_AID_PORT_WIDTH-1:0] awid ;

  wire [`DW_VIP_AXI_AWSIDEBAND_PORT_WIDTH-1:0] awsideband  ;

  wire awready ;

clocking slave_clocking_block @(posedge aclk);

default input #setup_time output #hold_time ;

 

  input  aresetn ;

 

  input  awvalid ;

  input  awaddr ;

  input  awlen ;

  input  awsize ;

  input  awburst ;

  input  awlock ;

  input  awcache ;

  input  awprot ;

  input  awid ;

  output awready ;

  input  awsideband  ;

endclocking : slave_clocking_block

 

//------------------------------------------------------------------------

/** Modport used to connect the VIP AXI Slave to AXI interface signals. */

modport axi_slave_modport(import clk_block.*, import slave_clocking_block.*);

 

endinterface: axi_if

 

Step2. Create Slave AXI VIP Configuration (axiCfg)

 

class axiCfg extends vmm_data;

  dw_vip_axi_system_model_configuration vip_axi_sys_cfg;

  dw_vip_axi_port_model_configuration   vip_axi_slave_cfg;

 

  function new();

 

    super.new(this.log);

     /* Create system configuration object */

    vip_axi_sys_cfg = new (, 1, 1, VMT_BOOLEAN_FALSE);

    /* Do system level configuration */

    vip_axi_sys_cfg.m_enAddrWidth = dw_vip_axi_configuration :: ADDR_BUS_WIDTH_32;

    vip_axi_sys_cfg.m_enDataWidth = dw_vip_axi_configuration :: DATA_BUS_WIDTH_64;

    /* Configure this member to maximum ID width within all masters in the system */

    vip_axi_sys_cfg.m_nMstrIdWidth = 4;

 

    /* Create port model configuration object for VIP slave. */

vip_axi_slave_cfg = vip_axi_sys_cfg.createPortMdlCfg (`DW_VIP_AXI_SLAVE_PORT_CFG, 0);

 

  /* Do port level configuration */

    vip_axi_slave_cfg.m_oPortCfg.m_nNumOutstandingXact = 1;

    vip_axi_slave_cfg.m_oPortCfg.m_nIdWidth = 4;

    vip_axi_slave_cfg.m_oPortCfg.m_enMemoryDefaultPattern=

                                        dw_vip_axi_configuration::PATTERN_INCR;

 

  endfunction : new

 

  …

endclass : axiCfg

 

 

 

Step3. Create a slave response transactor (refer to the attachment)

 

 

class axiSlaveXactor extends vmm_xactor;

 

 

  /* A local reference to the VIP slave's input and output VMM channel. */

  dw_vip_axi_slave_resp_transaction_channel o_output_chan;

  dw_vip_axi_slave_resp_transaction_channel o_input_chan;

 

  axiCfg                                  tb_cfg;// slave AXI VIP Configuration handle

  AxiSlave                               oSlave;// slave AXI VIP Model handle, used for FIFO/RAM access

 

  dw_vip_axi_slave_rvm    vip_axi_slave;// slave AXI VIP Xactor

  dw_vip_axi_slave_resp_transaction          resp_trans;// AXI response transaction

 

  //for SB

  axiMasterTrans                act_trans;

  axiMasterTrans_channel act_chan;

  axiMasterTrans                cpy_trans;

 

  extern function new(axiCfg           tb_cfg,

                                dw_vip_axi_slave_rvm    vip_axi_slave,

                                axiMasterTrans_channel act_chan =null,

               dw_vip_axi_slave_resp_transaction_channel o_output_chan,

               dw_vip_axi_slave_resp_transaction_channel o_input_chan);

 

  extern virtual task process_axi_resp_trans();

  extern virtual task recv_read();

  extern virtual task recv_write();

 

endclass

 

Step4. Register the slave response transactor and slave AXI VIP into vmm_env

 

class axiEnv extends vmm_env;

 

  virtual axi_if.axi_slave_modport  slave_mp;

  dw_vip_axi_slave_rvm                     vip_axi_slave;

  axiSlaveXactor                                   slave_xactor;

  axiSB                                                    axi_sb;

  axiCfg                        tb_cfg;

 

 

  dw_vip_axi_slave_resp_transaction_channel slave_input_chan;

  dw_vip_axi_slave_resp_transaction_channel slave_output_chan;

 

  virtual function void gen_cfg() ;

super.gen_cfg();

   this.tb_cfg                  = new;

    tb_cfg.vip_axi_slave_cfg.m_oPortCfg.m_enExclAccSupp = VMT_BOOLEAN_TRUE;

  endfunction : gen_cfg

 

  virtual function void build() ;

super.build();

   /* Create the VIP Slave input and output channels. */

    slave_input_chan  = new ("slave_response_channel","",2,0);

    slave_output_chan = new ("slave_response_channel","",2,0);

 

    vip_axi_slave   = new ("AXI SLAVE VIP",

                            slave_mp,

                            tb_cfg.vip_axi_slave_cfg,  

                            slave_input_chan,

                            slave_output_chan

                            );

 

    slave_xactor = new(tb_cfg,

                                            vip_axi_slave, ,  

                                            slave_output_chan,

                                            slave_input_chan

                    );

 

    axi_sb=new(tb_cfg,master_xactor.exp_chan,slave_xactor.act_chan);

 

  endfunction : build

 

 

virtual task start() ;

   super.start();

 

    vip_axi_slave.start_xactor();

    slave_xactor.start_xactor();

    axi_sb.start_xactor();

      

  endtask : start

endclass : axiEnv

 

Step5. Connect the slave AXI VIP interface to DUT  in the TB Top

module test_top;

// ----------------------------------------------------------------------

// Interface for AXI SLAVE side port, identified as axi_slave_if

// ----------------------------------------------------------------------

axi_if axi_slave_if();

 

// ----------------------------------------------------------------------

// VMM Testbench Program Instantiation:

// ----------------------------------------------------------------------

basic_system_test tb();

 

// ----------------------------------------------------------------------

// DUT Instantiation: Example DUT is just pass-through connection.

// ----------------------------------------------------------------------

axi_basic_interconnect_sv_wrapper hdl_interconnect(axi_master_if, axi_slave_if);

 

endmodule

=======================================================================================

/*
 COPYRIGHT (C) 2005, 2006, 2007, 2008, 2009, 2010 SYNOPSYS INC.
 This software and the associated documentation are confidential and
 proprietary to Synopsys, Inc. Your use or disclosure of this software
 is subject to the terms and conditions of a written license agreement
 between you, or your company, and Synopsys, Inc. In the event of
 publications, the following notice is applicable:

 ALL RIGHTS RESERVED

 The entire notice above must be reproduced on all authorized copies.

*/


/*
 Abstract:
     This file defines the class that the testbench uses to provide response
     information to the AXI Slave VIP. This class receives a response object of
     type dw_vip_axi_slave_resp_transaction from the output channel of the AXI
     slave VIP. This class then modifies the delay values in the received
     response object. The response object is then put back into AXI Slave VIP's
     input channel. The AXI Slave VIP uses the information in this response
     object to provide response to the received transaction.
*/
class axiSlaveXactor extends vmm_xactor;


  /* A local reference to the VIP slave's input and output VMM channel. */
  dw_vip_axi_slave_resp_transaction_channel o_output_chan;
  dw_vip_axi_slave_resp_transaction_channel o_input_chan;

  logic[1023:0]  rdata;
  axiCfg  tb_cfg;
  AxiSlave   oSlave;
  dw_vip_axi_slave_rvm      vip_axi_slave;
  dw_vip_axi_slave_resp_transaction  resp_trans;

  //for SB
  axiMasterTrans  act_trans;
  axiMasterTrans_channel act_chan;
  axiMasterTrans  cpy_trans;

 

 


  static int  num_of_trans;
  static int   DONE;

 

  extern function new(axiCfg tb_cfg,
    dw_vip_axi_slave_rvm    vip_axi_slave,
    axiMasterTrans_channel act_chan =null,
                dw_vip_axi_slave_resp_transaction_channel o_output_chan,
                dw_vip_axi_slave_resp_transaction_channel o_input_chan);

  extern virtual protected task main();
  extern virtual task process_axi_resp_trans();
  extern virtual task recv_read();
  extern virtual task recv_write();


endclass

 

//****************************************************************
// function new()
//****************************************************************

function axiSlaveXactor::new(axiCfg tb_cfg,
    dw_vip_axi_slave_rvm    vip_axi_slave,
  axiMasterTrans_channel act_chan =null,
                dw_vip_axi_slave_resp_transaction_channel o_output_chan,
                dw_vip_axi_slave_resp_transaction_channel o_input_chan);
    super.new("axiSlaveXactor", "class");

   
    if (act_chan == null)
      act_chan = new("axiSlaveXactor act_chan", "class");


    this.act_chan = act_chan ;
    this.o_output_chan = o_output_chan ;
    this.o_input_chan  = o_input_chan  ;
    this.vip_axi_slave=vip_axi_slave;
    this.tb_cfg=tb_cfg;

    act_trans=new();

    this.DONE = this.notify.configure(-1, vmm_notify::ON_OFF);
        
  endfunction : new

 

//****************************************************************
// main
//****************************************************************
  task axiSlaveXactor::main();
    super.main();
 
    oSlave = vip_axi_slave.getModel();

      //Slave VIP response
      while(1) begin 
    wait_if_stopped_or_empty(o_output_chan); 
       o_output_chan.peek(resp_trans);
 process_axi_resp_trans();
       o_output_chan.get(resp_trans);
        num_of_trans ++;
        if(num_of_trans==tb_cfg.run_for_n_trans)
      this.notify.indicate(this.DONE);

      end
 

 

  endtask

//****************************************************************
// process_axi_resp_trans();
//****************************************************************
task axiSlaveXactor::process_axi_resp_trans();

  case(resp_trans.m_enXactDir)
    dw_vip_axi_transaction::DIR_READ: recv_read();
    dw_vip_axi_transaction::DIR_WRITE: recv_write();
  endcase

endtask

//****************************************************************
// recv_write();
//****************************************************************
task axiSlaveXactor::recv_write();

    $display("###########################################################################");
    $display($time,,"SLAVE receives a WRITE transaction");
    $display("###########################################################################");
    resp_trans.display("SLAVE RECV ::/t");
    $display("/n");

    if (resp_trans.m_enXactBurst==dw_vip_axi_master_transaction::BURST_FIXED)
       oSlave.enable_fifo_all(`VMT_DEFAULT_STREAM_ID,16);


    /* Put the response object into the VIP slave input channel. */
    resp_trans.m_nAvalidAreadyDelay = 3;
    o_input_chan.put(resp_trans);
    $display("###########################################################################");
    $display($time,,"SLAVE responses a WRITE transaction");
    $display("###########################################################################");
    resp_trans.display("SLAVE RESP ::/t");
    $display("/n");


    //get the write data from VIP
    vip_axi_slave.notify.wait_for(vip_axi_slave.AXI_MSGID_END_OF_WR_XACT_NOTIFY_ID);

    //BURST_FIXED
    if (resp_trans.m_enXactBurst == dw_vip_axi_master_transaction::BURST_FIXED) begin
            for(int i=0; i<= resp_trans.m_enXactLength;i++) begin
         oSlave.pop_fifo(`VMT_DEFAULT_STREAM_ID,resp_trans.m_bvAddr,rdata);
       resp_trans.m_bvvData[i]=rdata;
              $display("SLAVE FIFO::addr=%0h read_data=%0h",resp_trans.m_bvAddr,rdata);
            end
     oSlave.disable_fifo_all(`VMT_DEFAULT_STREAM_ID);

    end

    //BURST_INCR
    if (resp_trans.m_enXactBurst == dw_vip_axi_master_transaction::BURST_INCR) begin
            for(int i=0; i<= resp_trans.m_enXactLength;i++) begin
              oSlave.get_mem(`VMT_DEFAULT_STREAM_ID,resp_trans.m_bvAddr+i*4,32,rdata);
       resp_trans.m_bvvData[i]=rdata;
            end
    end

    //BURST_INCR
    //put the act_trans into SB channel
    begin
      act_trans.m_enXactDir=resp_trans.m_enXactDir;
      act_trans.m_enXactLength=resp_trans.m_enXactLength;
      act_trans.m_enXferSize=resp_trans.m_enXferSize;
      act_trans.m_enXactBurst=resp_trans.m_enXactBurst;
      act_trans.m_enXactLock=resp_trans.m_enXactLock;
      act_trans.m_enXactCache=resp_trans.m_enXactCache;
      act_trans.m_enXactProt=resp_trans.m_enXactProt;
      act_trans.m_bvAddr=resp_trans.m_bvAddr;

      for(int i=0; i<= resp_trans.m_enXactLength;i++)
         act_trans.m_bvvData[i]=resp_trans.m_bvvData[i];

      act_trans.data_id=num_of_trans;

      $cast(cpy_trans,act_trans.copy());
      act_chan.put(cpy_trans);
    end

 


endtask


//****************************************************************
// recv_read();
//****************************************************************
task axiSlaveXactor::recv_read();

    $display("###########################################################################");
    $display($time,,"SLAVE receives a READ transaction");
    $display("###########################################################################");
    resp_trans.display("SLAVE RECV ::/t");
    $display("/n");

    resp_trans.m_nAvalidAreadyDelay = 3;

    rdata= $random();

    //BURST_FIXED
    if (resp_trans.m_enXactBurst==dw_vip_axi_master_transaction::BURST_FIXED) begin
      oSlave.enable_fifo_address(`VMT_DEFAULT_STREAM_ID,resp_trans.m_bvAddr,resp_trans.m_enXactLength+1);
      for(int i=0;i<=resp_trans.m_enXactLength;i++) begin
        oSlave.set_fifo(`VMT_DEFAULT_STREAM_ID,resp_trans.m_bvAddr,rdata,i);
        act_trans.m_bvvData[i]=rdata;
 rdata++;
      end
      o_input_chan.put(resp_trans);
    end
    //BURST_INCR
    if (resp_trans.m_enXactBurst==dw_vip_axi_master_transaction::BURST_INCR) begin
      for(int i=0;i<=resp_trans.m_enXactLength;i++) begin
 oSlave.set_mem(`VMT_DEFAULT_STREAM_ID,resp_trans.m_bvAddr+(i*4), 32, rdata);
 act_trans.m_bvvData[i]=rdata;
        rdata++;
      end
      o_input_chan.put(resp_trans);
    end
    $display("###########################################################################");
    $display($time,,"SLAVE responses a READ transaction");
    $display("###########################################################################");
    resp_trans.display("SLAVE RESP ::/t");
    $display("/n");
    act_trans.m_enXactDir=resp_trans.m_enXactDir;
    act_trans.m_enXactLength=resp_trans.m_enXactLength;
    act_trans.m_enXferSize=resp_trans.m_enXferSize;
    act_trans.m_enXactBurst=resp_trans.m_enXactBurst;
    act_trans.m_enXactLock=resp_trans.m_enXactLock;
    act_trans.m_enXactCache=resp_trans.m_enXactCache;
    act_trans.m_enXactProt=resp_trans.m_enXactProt;
    act_trans.m_bvAddr=resp_trans.m_bvAddr;
 
    act_trans.data_id=num_of_trans;
    $cast(cpy_trans,act_trans.copy());
    act_chan.put(cpy_trans);
 
    //delete FIFO
    if (resp_trans.m_enXactBurst==dw_vip_axi_master_transaction::BURST_FIXED) begin
 vip_axi_slave.notify.wait_for(vip_axi_slave.AXI_MSGID_END_OF_RD_XACT_NOTIFY_ID);
        $display("READ end");
       oSlave.disable_fifo_address(`VMT_DEFAULT_STREAM_ID,resp_trans.m_bvAddr);
    end


endtask

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值