0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自作AXI Lite SlaveモジュールをAXI VIPで検証する

0
Last updated at Posted at 2025-12-04

はじめに

FPGAに実装される回路間のやり取りは基本AXIトランザクションで統一される。提供されるIPのほとんどがこのAXIという規格を採用しているので、いざ自作IPをそれらと組み合わせようとした場合、必然的に「そもそも正しくAXIできてるの?うちの子。」と検証が必要になる。そこで役立つのがこのAXI Verification IP。
AXI master, AXI slaveの両方として振る舞うことが出来る。 (pass-throughモードもある)
しかし、テストベンチファイルから特定の記述を行わないとシミュレーションでこのAXI VIPは起動しない。とくに、axi masterとしての取り扱いはslaveよりちょっと面倒。本記事はAXI VIPのmasterとしての起動・操作方法について公式サイトからまとめたものである。

テストベンチへの基本的な追記内容

まず、最初に必要になる追記内容は以下の通り。<component_name><hierarchy_path>を実際の文字列に置き換えないといけない。それぞれの確認方法を順に説明する。

import axi_vip_pkg::*;
import <component_name>_pkg::*;

<component_name>_mst_t agent;
initial begin
    agent = new("my VIP agent", <hierarchy_path>.IF);
    agent.start_master();
end
  1. <component_name>の確認方法
    Block Designを開いて、DiagramからVIPをクリック、Block PropertiesペインのProperties内にあるCONFIGを展開、Component_Name行から確認できる

  2. <hierarchy_path>の確認方法
    とりあえずRun Bihavioral Simulationを実行、ScopeタブでExpand Allをクリック。テストベンチの下からvipのIFまでを.で繋げるだけ。以下ならdut.design_4_i.axi_vip_0.inst<hierarchy_path>になる。
    image.png

トランザクションの発行方法

上のままでは何もreadしないし何もwriteしない。ので、騒ぎ立ててもらいたい。上のagent.start_master();に続いて書くといい。
なお、適当なプロジェクト内にVIPを配置、SourceタブにあるVIPを右クリック、Opem IP Example Designで開かれるプロジェクト内にあるaxi_vip_0_mst_stimulus.svhが参考になる。 (末尾に載せる)

  1. writeの発行
task simple_write_transaction();
    axi_transaction t;
    t = agent.wr_driver.create_transaction("writewritewritewrite");
    agent.rd_driver.send(t);
endtask
  1. readの発行
task simple_read_transaction();
    axi_transaction t;
    t = agent.rd_driver.create_transaction("readreadreadreadread");
    agent.rd_driver.send(t);
endtask

まとめ

import axi_vip_pkg::*;
import <component_name>_pkg::*;

<component_name>_mst_t agent;
task simple_write_transaction();
    axi_transaction wr_t;
    wr_t = agent.wr_driver.create_transaction("writewritewritewrite");
    agent.wr_driver.send(wr_t);
endtask
task simple_read_transaction();
    axi_transaction rd_t;
    rd_t = agent.rd_driver.create_transaction("readreadreadreadread");
    agent.rd_driver.send(rd_t);
endtask

initial begin
    agent = new("my VIP agent", <hierarchy_path>.IF);
    agent.start_master();
    simple_read_transaction();
    simple_write_transaction();
end

参考

ちなみに

上の例をそのまんま使うとランダムなアドレスを読みに行くので不便。t.set_read_cmd(addr,burst,id,len,size);とかでアドレス指定とかバースト調指定もできる。詳しくは以下のsingle_read_transaction_apitaskあたりを読むといい。
あとreset中にトランザクションを発行しないように注意。あと同時に二つのトランザクションを発行したいときはfork-joinを使うといい。

fork
    begin
        simple_read_transaction();
    end
    begin
        simple_write_transaction();      
    end
join

image.png
ちなみにアドレス指定しなかったときに使われるデフォルトのアドレスはdeadbeef

おまけ

使用例


import axi_vip_pkg::*;
import design_4_axi_vip_0_0_pkg::*;

module design_4_wrapper_tb(

    );
    logic ACLK, ARESETN, req_empty;
    design_4_wrapper dut(.aclk(ACLK), .aresetn(ARESETN), .req_empty(req_empty));
    localparam STEP = 10;
    always begin
        ACLK = 0; #(STEP/2);
        ACLK = 1; #(STEP/2);
    end
    
    initial begin
        req_empty = 1;
        ARESETN = 1; #(STEP*5);
        ARESETN = 0; #(STEP*20);
        ARESETN = 1; #(STEP*500);
        $stop;    
    end
    
    design_4_axi_vip_0_0_mst_t agent;
    task simple_write_transaction(  input xil_axi_uint               id =0, 
                                    input xil_axi_ulong              addr =0,
                                    input xil_axi_len_t              len =0, 
                                    input xil_axi_size_t             size =xil_axi_size_t'(xil_clog2((32)/8)),
                                    input xil_axi_burst_t            burst =XIL_AXI_BURST_TYPE_INCR,
                                    input bit [32-1:0]                 data =0);
        axi_transaction wr_t;
        wr_t = agent.wr_driver.create_transaction("writewritewritewrite");
        wr_t.set_write_cmd(addr, burst, id, len, size);
        wr_t.set_data_block(data);
        agent.wr_driver.send(wr_t);
    endtask
    task simple_read_transaction(   input xil_axi_uint               id =0, 
                                    input xil_axi_ulong              addr =0,
                                    input xil_axi_len_t              len =0, 
                                    input xil_axi_size_t             size =xil_axi_size_t'(xil_clog2((32)/8)),
                                    input xil_axi_burst_t            burst =XIL_AXI_BURST_TYPE_INCR);
        axi_transaction rd_t;
        rd_t = agent.rd_driver.create_transaction("readreadreadreadread");
        rd_t.set_read_cmd(addr, burst, id, len, size);
        agent.rd_driver.send(rd_t);
    endtask
        
    initial begin
        #(STEP*50)
        agent = new("my VIP agent", dut.design_4_i.axi_vip_0.inst.IF);
        agent.start_master();
        simple_read_transaction(0, 8, 0, 2, 0); #(STEP*10);
        simple_write_transaction(0, 8, 0, 2, 0, 32'hdeadbeef); #(STEP*10);
        simple_read_transaction(0, 8, 0, 2, 0); #(STEP*10);
        simple_read_transaction(0, 20, 0, 2, 0); #(STEP*10);
        simple_write_transaction(0, 25, 0, 2, 0, 32'hbeefdead); #(STEP*10);
        simple_read_transaction(0, 20, 0, 2, 0); #(STEP*10);
//        fork
//            begin
//                simple_read_transaction();
//            end
//            begin
//                simple_write_transaction();      
//            end
//        join
    end
        
endmodule
mst_stimulus.svh
/***************************************************************************************************
* Description: 
* This file contains examples showing how user can generate simple write and/or read transaction 
* According to VIP's WRITE_READ_MODE. user will see different examples.
* WRITE_ONLY - simple write transaction
* READ_ONLY  - simple read transaction
* READ_WRITE - both simple write and read transaction

*  For Master VIP to work correctly, user environment MUST have to do the following lists of item
*  and follow the same order as shown here.  Item 1 to 5 can be copied into a user testbench and
*  care of the ordering must be taken into account.    
*    1. import two packages.
*         import axi_vip_pkg::*; 
*         import <component_name>_pkg::*;
*    2. delcare <component_name>_mst_t agent
*    3. new agent (passing instance IF correctly)
*    4. start_master
*    5. generate transaction/
* More details about generating transaction please refer tasks below.
*
* In this file,it shows how to generate a write/read transaction in three ways(fully randomization,
* partial randomization and API), it then shows how to get read data back from driver,how
* generate write in data and then read it back.
*  
***************************************************************************************************/
import axi_vip_pkg::*;
import ex_sim_axi_vip_mst_0_pkg::*;

  /*************************************************************************************************
  * <component_name>_mst_t for master agent
  * <component_name> can be easily found in vivado bd design: click on the instance, 
  * Then click CONFIG under Properties window and Component_Name will be shown
  * More details please refer PG267 section about "Useful Coding Guidelines and Examples"
  * for more details.
  *************************************************************************************************/
  ex_sim_axi_vip_mst_0_mst_t                               mst_agent;

  /*************************************************************************************************
  * Declare variables which will be used in API and parital randomization for transaction generation
  * and data read back from driver.
  *************************************************************************************************/
  axi_transaction                                          wr_trans;            // Write transaction
  axi_transaction                                          rd_trans;            // Read transaction
  xil_axi_uint                                             mtestWID;            // Write ID  
  xil_axi_ulong                                            mtestWADDR;          // Write ADDR  
  xil_axi_len_t                                            mtestWBurstLength;   // Write Burst Length   
  xil_axi_size_t                                           mtestWDataSize;      // Write SIZE  
  xil_axi_burst_t                                          mtestWBurstType;     // Write Burst Type  
  xil_axi_uint                                             mtestRID;            // Read ID  
  xil_axi_ulong                                            mtestRADDR;          // Read ADDR  
  xil_axi_len_t                                            mtestRBurstLength;   // Read Burst Length   
  xil_axi_size_t                                           mtestRDataSize;      // Read SIZE  
  xil_axi_burst_t                                          mtestRBurstType;     // Read Burst Type  

  xil_axi_data_beat [255:0]                                mtestWUSER;         // Write user  
  xil_axi_data_beat                                        mtestAWUSER;        // Write Awuser 
  xil_axi_data_beat                                        mtestARUSER;        // Read Aruser
  
  // Error count to check how many comparison failed
  xil_axi_uint                                            error_cnt = 0;

  /************************************************************************************************
  * No burst for AXI4LITE and maximum data bits is 64
  * Write Data Value for WRITE_BURST transaction
  * Read Data Value for READ_BURST transaction
  ************************************************************************************************/
  bit [63:0]                                               mtestWData;         // Write Data
  bit[8*4096-1:0]                                          Rdatablock;        // Read data block
  xil_axi_data_beat                                        Rdatabeat[];       // Read data beats
  bit[8*4096-1:0]                                          Wdatablock;        // Write data block
  xil_axi_data_beat                                        Wdatabeat[];       // Write data beats
 
  task mst_start_stimulus();
    /***********************************************************************************************
    * Before agent is newed, user has to run simulation with an empty testbench to find the hierarchy
    * path of the AXI VIP's instance.Message like
    * "Xilinx AXI VIP Found at Path: my_ip_exdes_tb.DUT.ex_design.axi_vip_mst.inst" will be printed 
    * out. Pass this path to the new function. 
    ***********************************************************************************************/
    mst_agent = new("master vip agent",DUT.ex_design.axi_vip_mst.inst.IF);
    mst_agent.start_master();               // mst_agent start to run

    // Parallel write/read transaction generation 
    fork                               // Fork process of write/read transaction generation                    
  
      begin  
        // single write transaction with fully randomization
         multiple_write_transaction_full_rand ("single write",1);
         
        mtestWID = $urandom_range(0,(1<<(0)-1)); 
        mtestWADDR = 0;
        mtestWBurstLength = 0;
        mtestWDataSize = xil_axi_size_t'(xil_clog2((32)/8));
        mtestWBurstType = XIL_AXI_BURST_TYPE_INCR;
        mtestWData = $urandom();
        //single write transaction filled in user inputs through API 
        single_write_transaction_api("single write with api",
                                     .id(mtestWID),
                                     .addr(mtestWADDR),
                                     .len(mtestWBurstLength), 
                                     .size(mtestWDataSize),
                                     .burst(mtestWBurstType),
                                     .wuser(mtestWUSER),
                                     .awuser(mtestAWUSER), 
                                     .data(mtestWData)
                                     );

        //multiple write transactions with the same inline randomization 
        multiple_write_transaction_partial_rand(.num_xfer(2),
                                                .start_addr(mtestWADDR),
                                                .id(mtestWID),
                                                .len(mtestWBurstLength),
                                                .size(mtestWDataSize),
                                                .burst(mtestWBurstType),
                                                .no_xfer_delays(1)
                                               );
      end
 
      begin
        //single read transaction with fully randomization
        multiple_read_transaction_full_rand ("single read",1);

        mtestRID = $urandom_range(0,(1<<(0)-1));
        mtestRADDR = $urandom_range(0,(1<<(32)-1));
        mtestRBurstLength = 0;
        mtestRDataSize = xil_axi_size_t'(xil_clog2((32)/8)); 
        mtestRBurstType = XIL_AXI_BURST_TYPE_INCR;
        //single read transaction filled in user inputs through API 
        single_read_transaction_api("single read with api",
                                     .id(mtestRID),
                                     .addr(mtestRADDR),
                                     .len(mtestRBurstLength), 
                                     .size(mtestRDataSize),
                                     .burst(mtestRBurstType)
                                     );
        //multiple read transaction with the same inline randomization 
        multiple_read_transaction_partial_rand( .num_xfer(2),
                                                .start_addr(mtestRADDR),
                                                .id(mtestRID),
                                                .len(mtestRBurstLength),
                                                .size(mtestRDataSize),
                                                .burst(mtestRBurstType),
                                                .no_xfer_delays(1)
                                               ); 
        //get read data back from driver
        rd_trans = mst_agent.rd_driver.create_transaction("read transaction with randomization for getting data back");
        fill_transaction_with_fully_randomization(rd_trans);
        //get read data beat back from driver
        get_rd_data_beat_back(rd_trans,Rdatabeat);
        //get read data block back from driver
        get_rd_data_block_back(rd_trans,Rdatablock);
      end  
    join

    mst_agent.wait_drivers_idle();           // Wait driver is idle 
   
 
    //Below shows write two transactions in and then read them back

    mtestWID = $urandom_range(0,(1<<(0)-1)); 
    mtestWADDR = 0;
    mtestWBurstLength = 0;
    mtestWDataSize = xil_axi_size_t'(xil_clog2((32)/8));
    mtestWBurstType = XIL_AXI_BURST_TYPE_INCR;
    multiple_write_in_then_read_back(.num_xfer(2),
                                     .start_addr(mtestWADDR),
                                     .id(mtestWID),
                                     .len(mtestWBurstLength),
                                     .size(mtestWDataSize),
                                     .burst(mtestWBurstType),
                                     .no_xfer_delays(1)
                                    );  

    mst_agent.wait_drivers_idle();           // Wait driver is idle then stop the simulation
   
    if(error_cnt ==0) begin
      $display("EXAMPLE TEST DONE : Test Completed Successfully");
    end else begin  
      $display("EXAMPLE TEST DONE ",$sformatf("Test Failed: %d Comparison Failed", error_cnt));
    end 
    $finish;
  endtask

  /*************************************************************************************************
  * Fully randomization of transaction
  * This simple task shows fully randomize one transaction  
  * Fatal will show up if randomizaiton failed
  *************************************************************************************************/
  
  task automatic fill_transaction_with_fully_randomization(inout axi_transaction trans); 
     if( !(trans.randomize())) begin
       $fatal(1,"fill_transaction_with_fully_randomization of %s failed at time =%t",trans.get_name(), $realtime); 
     end
  endtask : fill_transaction_with_fully_randomization

  /*************************************************************************************************
  * Partial randomization of transaction
  * This simple task shows paritaly randomize one transaction with fixed value for ID,ADDR,LENGTH,
  * SIZE and BURST.User can following this task and create some other partial randomized transaction
  * Fatal will show up if randomizaiton failed
  * NOTE: Please don't use this task in VIVADO Simulator for it's limitiaton of SV support.
  *************************************************************************************************/

  task automatic inline_randomize_transaction(inout axi_transaction trans,
                                              input xil_axi_uint id_val,
                                              input xil_axi_ulong addr_val,
                                              input xil_axi_len_t len_val,
                                              input xil_axi_size_t size_val,
                                              input xil_axi_burst_t burst_val); 
    if(! ((trans.randomize() with {
         id == id_val; 
         addr==addr_val; 
         len==len_val;
         size ==size_val;
         burst ==burst_val;
     }))) begin
        $fatal(1,"inline_randomize_transaction of %s failed at time =%t",trans.get_name(), $realtime);     
       end
  endtask : inline_randomize_transaction

  /************************************************************************************************
  * Task send_wait_rd is a task which set_driver_return_item_policy of the read transaction, 
  * send the transaction to the driver and wait till it is done
  *************************************************************************************************/
  task send_wait_rd(inout axi_transaction rd_trans);
    rd_trans.set_driver_return_item_policy(XIL_AXI_PAYLOAD_RETURN);
    mst_agent.rd_driver.send(rd_trans);
    mst_agent.rd_driver.wait_rsp(rd_trans);
  endtask

  /************************************************************************************************
  * Task get_rd_data_beat_back is to get read data back from read driver with
  *  data beat format.
  *************************************************************************************************/
  task get_rd_data_beat_back(inout axi_transaction rd_trans, 
                                 output xil_axi_data_beat Rdatabeat[]
                            );  
    send_wait_rd(rd_trans);
    Rdatabeat = new[rd_trans.get_len()+1];
    for( xil_axi_uint beat=0; beat<rd_trans.get_len()+1; beat++) begin
      Rdatabeat[beat] = rd_trans.get_data_beat(beat);
   //   $display("Read data from Driver: beat index %d, Data beat %h ", beat, Rdatabeat[beat]);
    end  
  endtask

  /************************************************************************************************
  * Task get_rd_data_block_back is to get read data back from read driver with
  * data block format.
  *************************************************************************************************/
  task get_rd_data_block_back(inout axi_transaction rd_trans, 
                                 output bit[8*4096-1:0] Rdatablock
                            );  
    send_wait_rd(rd_trans);
    Rdatablock = rd_trans.get_data_block();
    // $display("Read data from Driver: Block Data %h ", Rdatablock);
  endtask

  /************************************************************************************************
  * Task send_wait_wr is a task which set_driver_return_item_policy of the write transaction, 
  * send the transaction to the driver and wait till it is done
  *************************************************************************************************/
  task send_wait_wr(inout axi_transaction wr_trans);
    wr_trans.set_driver_return_item_policy(XIL_AXI_PAYLOAD_RETURN);
    mst_agent.wr_driver.send(wr_trans);
    mst_agent.wr_driver.wait_rsp(wr_trans);
  endtask

  /************************************************************************************************
  * Task get_wr_data_beat_back is to get read data back from write driver with
  * data beat format.
  *************************************************************************************************/
  task get_wr_data_beat_back(inout axi_transaction wr_trans, 
                                 output xil_axi_data_beat Wdatabeat[]
                            );  
    send_wait_wr(wr_trans);
    Wdatabeat = new[wr_trans.get_len()+1];
    for( xil_axi_uint beat=0; beat<wr_trans.get_len()+1; beat++) begin
      Wdatabeat[beat] = wr_trans.get_data_beat(beat);
   //   $display("Write data from Driver: beat index %d, Data beat %h ", beat, Wdatabeat[beat]);
    end  
  endtask

  /************************************************************************************************
  * Task get_wr_data_block_back is to get write data back from write driver with
  * data block format.
  *************************************************************************************************/
  task get_wr_data_block_back(inout axi_transaction wr_trans, 
                                 output bit[8*4096-1:0] Wdatablock
                            );  
    send_wait_wr(wr_trans);
    Wdatablock = wr_trans.get_data_block();
    // $display("Write data from Driver: Block Data %h ", Wdatablock);
  endtask


  /************************************************************************************************
  *  task single_write_transaction_api is to create a single write transaction, fill in transaction 
  *  by using APIs and send it to write driver.
  *   1. declare write transction
  *   2. Create the write transaction
  *   3. set addr, burst,ID,length,size by calling set_write_cmd(addr, burst,ID,length,size), 
  *   4. set prot.lock, cache,region and qos
  *   5. set beats
  *   6. set AWUSER if AWUSER_WIDH is bigger than 0
  *   7. set WUSER if WUSR_WIDTH is bigger than 0
  *************************************************************************************************/

  task automatic single_write_transaction_api ( 
                                input string                     name ="single_write",
                                input xil_axi_uint               id =0, 
                                input xil_axi_ulong              addr =0,
                                input xil_axi_len_t              len =0, 
                                input xil_axi_size_t             size =xil_axi_size_t'(xil_clog2((32)/8)),
                                input xil_axi_burst_t            burst =XIL_AXI_BURST_TYPE_INCR,
                                input xil_axi_lock_t             lock = XIL_AXI_ALOCK_NOLOCK,
                                input xil_axi_cache_t            cache =0,
                                input xil_axi_prot_t             prot =0,
                                input xil_axi_region_t           region =0,
                                input xil_axi_qos_t              qos =0,
                                input xil_axi_data_beat [255:0]  wuser =0, 
                                input xil_axi_data_beat          awuser =0,
                                input bit [63:0]                 data =0
                                                );
    axi_transaction                               wr_trans;
    wr_trans = mst_agent.wr_driver.create_transaction(name);
    wr_trans.set_write_cmd(addr,burst,id,len,size);
    wr_trans.set_prot(prot);
    wr_trans.set_lock(lock);
    wr_trans.set_cache(cache);
    wr_trans.set_region(region);
    wr_trans.set_qos(qos);
    wr_trans.set_data_block(data);
    mst_agent.wr_driver.send(wr_trans);   
  endtask  : single_write_transaction_api

  /************************************************************************************************
  *  task single_read_transaction_api is to create a single read transaction, fill in command with user
  *  inputs and send it to read driver.
  *   1. declare read transction
  *   2. Create the read transaction
  *   3. set addr, burst,ID,length,size by calling set_read_cmd(addr, burst,ID,length,size), 
  *   4. set prot.lock, cache,region and qos
  *   5. set ARUSER if ARUSER_WIDH is bigger than 0
  *************************************************************************************************/
  task automatic single_read_transaction_api ( 
                                    input string                     name ="single_read",
                                    input xil_axi_uint               id =0, 
                                    input xil_axi_ulong              addr =0,
                                    input xil_axi_len_t              len =0, 
                                    input xil_axi_size_t             size =xil_axi_size_t'(xil_clog2((32)/8)),
                                    input xil_axi_burst_t            burst =XIL_AXI_BURST_TYPE_INCR,
                                    input xil_axi_lock_t             lock =XIL_AXI_ALOCK_NOLOCK ,
                                    input xil_axi_cache_t            cache =0,
                                    input xil_axi_prot_t             prot =0,
                                    input xil_axi_region_t           region =0,
                                    input xil_axi_qos_t              qos =0,
                                    input xil_axi_data_beat          aruser =0
                                                );
    axi_transaction                               rd_trans;
    rd_trans = mst_agent.rd_driver.create_transaction(name);
    rd_trans.set_read_cmd(addr,burst,id,len,size);
    rd_trans.set_prot(prot);
    rd_trans.set_lock(lock);
    rd_trans.set_cache(cache);
    rd_trans.set_region(region);
    rd_trans.set_qos(qos);
    mst_agent.rd_driver.send(rd_trans);   
  endtask  : single_read_transaction_api


  /************************************************************************************************
  * multiple write transaction with fully randomization 
  * This simple task shows how user can generate multiple write transaction with fully randomization
  * 1. Declare a handle for write transaction
  * 2. Depends on how many transfers user need,it will  
  *    2.a Write driver of the agent create transaction
  *    2.b Randomized the transaction
  *    2.c Write driver of the agent sends the transaction to Master VIP interface
  * 3. once it is does, it repeats step 2 to generate another write transaction.
  *************************************************************************************************/
  task automatic multiple_write_transaction_full_rand (
                               input string          name ="multiple_write_transaction_full_rand",
                               input xil_axi_uint    num_xfer =1);
    axi_transaction                                    wr_tran;
    for (int i =0; i< num_xfer; i++) begin
      wr_tran = mst_agent.wr_driver.create_transaction($sformatf("%s,  %0d of %0d",name,i,num_xfer));
      fill_transaction_with_fully_randomization(wr_tran);
      mst_agent.wr_driver.send(wr_tran);
    end  
  endtask
 
  /************************************************************************************************
  * multiple read transaction with fully randomization 
  * This simple task shows how user can generate multiple read transaction with fully randomization
  * 1. Declare a handle for read transaction
  * 2. Depends on how many transfers user need,it will  
  *    2.a Read driver of the agent create transaction
  *    2.b Randomized the transaction
  *    2.c Read driver of the agent sends the transaction to Master VIP interface
  * 3. once it is does, it repeats step 2 to generate another read transaction.
  *************************************************************************************************/

  task automatic multiple_read_transaction_full_rand(
                               input string          name ="multiple_read_transaction_full_rand",
                               input xil_axi_uint    num_xfer =1);
    axi_transaction                                    rd_tran;
    rd_tran = mst_agent.rd_driver.create_transaction(name);
    for (int i =0; i< num_xfer; i++) begin
      rd_tran = mst_agent.rd_driver.create_transaction($sformatf("%s,  %0d of %0d",name,i,num_xfer));
      fill_transaction_with_fully_randomization(rd_tran);
      mst_agent.rd_driver.send(rd_tran);
    end  
  endtask

  
  /*************************************************************************************************
  * This task is to queue up multiple transactions with the same id, length,size, burst type
  * and incrementd addr with different data. then it send out all these transactions
  * 1. Declare a handle for read transaction
  * 2. set delay range if user set there transction is of no delay
  * 3. constraint randomize the transaction
  * 4. increment the addr
  * 5. repeat 1-4 to generate num_xfer transaction
  * 6. send out the transaction
  *************************************************************************************************/
  
  task automatic multiple_read_transaction_partial_rand(
                              input xil_axi_uint    num_xfer =1,
                              input xil_axi_ulong   start_addr =0,
                              input xil_axi_uint    id =0,
                              input xil_axi_len_t   len =0,
                              input xil_axi_size_t  size =xil_axi_size_t'(xil_clog2((32)/8)),
                              input xil_axi_burst_t burst = XIL_AXI_BURST_TYPE_INCR,
                              input bit             no_xfer_delays =0  
                                        );
    axi_transaction                                          rd_tran[];
    xil_axi_ulong                                            addr;

    rd_tran =new[num_xfer];
    addr = start_addr;

    // queue up transactions
    for (int i =0; i <num_xfer; i++) begin
      rd_tran[i] = mst_agent.rd_driver.create_transaction($sformatf("read_multiple_transaction id =%0d",i));
      if(no_xfer_delays ==1) begin
        rd_tran[i].set_data_insertion_delay_range(0,0);
        rd_tran[i].set_addr_delay_range(0,0);
        rd_tran[i].set_beat_delay_range(0,0);
      end  
      inline_randomize_transaction(.trans(rd_tran[i]), 
                                   .id_val(id), 
                                   .addr_val(addr),
                                   .len_val(len),
                                   .size_val(size), 
                                   .burst_val(burst));
      addr += rd_tran[i].get_num_bytes_in_transaction();
    end
    //send out transaction
    for (int i =0; i <num_xfer; i++) begin
       mst_agent.rd_driver.send(rd_tran[i]);
    end
  endtask :multiple_read_transaction_partial_rand

  /*************************************************************************************************  * This task is to queue up multiple transactions with the same id, length,size, burst type
  * and incrementd addr with different data. then it send out all these transactions 
  * 1. Declare a handle for write transaction
  * 2. set delay range if user set there transction is of no delay
  * 3. constraint randomize the transaction
  * 4. increment the addr
  * 5. repeat 1-4 to generate num_xfer transaction
  * 6. send out the transaction
  *************************************************************************************************/
  
  task automatic multiple_write_transaction_partial_rand(
                              input xil_axi_uint    num_xfer =1,
                              input xil_axi_ulong   start_addr =0,
                              input xil_axi_uint    id =0,
                              input xil_axi_len_t   len =0,
                              input xil_axi_size_t  size =xil_axi_size_t'(xil_clog2((32)/8)),
                              input xil_axi_burst_t burst = XIL_AXI_BURST_TYPE_INCR,
                              input bit             no_xfer_delays =0  
                                        );
    axi_transaction                                          wr_tran[];
    xil_axi_ulong                                            addr;

    wr_tran =new[num_xfer];
    addr = start_addr;

    // queue up transactions
    for (int i =0; i <num_xfer; i++) begin
      wr_tran[i] = mst_agent.wr_driver.create_transaction($sformatf("write_multiple_transaction id =%0d",i));
      if(no_xfer_delays ==1) begin
        wr_tran[i].set_data_insertion_delay_range(0,0);
        wr_tran[i].set_addr_delay_range(0,0);
        wr_tran[i].set_beat_delay_range(0,0);
      end  
      inline_randomize_transaction(.trans(wr_tran[i]), 
                                   .id_val(id), 
                                   .addr_val(addr),
                                   .len_val(len),
                                   .size_val(size), 
                                   .burst_val(burst));
      addr += wr_tran[i].get_num_bytes_in_transaction();
    end
    //send out transaction
    for (int i =0; i <num_xfer; i++) begin
       mst_agent.wr_driver.send(wr_tran[i]);
    end
  endtask :multiple_write_transaction_partial_rand

  /************************************************************************************************
  * multiple_write_in_then_read_back shows user how to write to one address and then read back. 
  * 1. create a write transaction with fixed address, id, length, size, burst type.
  * 2. send the transaction to Master VIP interface and wait till response come back
  * 3. Get write data beat and data block from the driver
  * 4. create a read transaction with the same address, id, length, size and burst type as write transaction
  * 5. send the transaction to Master VIP interface and wait till response come back
  * 6. Get read data beat and data block from the driver
  * 7. user can do a check between write data and read data(if in the enviroment there is memory in the system)
  *    or print out the data information 
  * 8. increment the address and repeat another write in and read back till num_xfer transactions
  *************************************************************************************************/

  task automatic multiple_write_in_then_read_back (
                          input xil_axi_uint    num_xfer =1,
                          input xil_axi_ulong   start_addr =0,
                          input xil_axi_uint    id =0,
                          input xil_axi_len_t   len =0,
                          input xil_axi_size_t  size =xil_axi_size_t'(xil_clog2((32)/8)),
                          input xil_axi_burst_t burst = XIL_AXI_BURST_TYPE_INCR,
                          input bit             no_xfer_delays =0    
                                        );
    axi_transaction                                          wr_trans;
    axi_transaction                                          rd_trans;
    bit[8*4096-1:0]                                          data_block_for_read;
    xil_axi_data_beat                                        DataBeat_for_read[];
    bit[8*4096-1:0]                                          data_block_for_write;
    xil_axi_data_beat                                        DataBeat_for_write[];
    xil_axi_ulong                                            addr;

    addr = start_addr;
    for (int i =0; i <num_xfer; i++) begin
      //write transaction in 
      wr_trans = mst_agent.wr_driver.create_transaction($sformatf("fill in write transaction with inline randomization id =%0d",i));
       if(no_xfer_delays ==1) begin
        wr_trans.set_data_insertion_delay_range(0,0);
        wr_trans.set_addr_delay_range(0,0);
        wr_trans.set_beat_delay_range(0,0);
      end  
      inline_randomize_transaction(.trans(wr_trans), 
                                   .id_val(id), 
                                   .addr_val(addr),
                                   .len_val(len),
                                   .size_val(size), 
                                   .burst_val(burst));
      get_wr_data_beat_back(wr_trans,DataBeat_for_write);
      data_block_for_write = wr_trans.get_data_block();
      //$display("Write data from Driver: Block Data %h ", data_block_for_write);
      
      // read data back
      rd_trans = mst_agent.rd_driver.create_transaction($sformatf("fill in read transaction with inline randomization id =%0d",i));
      if(no_xfer_delays ==1) begin
        rd_trans.set_data_insertion_delay_range(0,0);
        rd_trans.set_addr_delay_range(0,0);
        rd_trans.set_beat_delay_range(0,0);
      end  
      inline_randomize_transaction(.trans(rd_trans),
                                   .id_val(id), 
                                   .addr_val(addr),
                                   .len_val(len),
                                   .size_val(size), 
                                   .burst_val(burst));
      get_rd_data_beat_back(rd_trans,DataBeat_for_read);
      data_block_for_read = rd_trans.get_data_block();
      //  $display("Read data from Driver: Block Data %h ", data_block_for_read);
      addr += wr_trans.get_num_bytes_in_transaction();
    end
  endtask

  /**********************************************************************************************
  * Note: if multiple agents are called in one testbench,it will be hard to tell which
  * agent is complaining. set_agent_tag can be used to set a name tag for each agent
    mst_agent.set_agent_tag("My Master VIP one");

  * If user wants to know all the details of each transaction, set_verbosity can be used to set
  * up information being printed out or not. Default is no print out 
    * Verbosity level which specifies how much debug information to produce
    *    0       - No information will be printed out.
    *   400      - All information will be printed out
    mst_agent.set_verbosity(0);

  * These two lines should be added anywhere after agent is being newed  
  *************************************************************************************************/

  
  /*************************************************************************************************
  * RREADY Generation with customized pattern
  * Master read driver create rready
  * Set rready generation policy
  * Set low/high time
  * Master read driver send rready
  * NOTE: if user wants default pattern of ready generation,nothing needs to be done

  task user_gen_rready();  
    axi_ready_gen                           rready_gen;
    rready_gen = mst_agent.rd_driver.create_ready("rready");
    rready_gen.set_ready_policy(XIL_AXI_READY_GEN_AFTER_VALID_OSC);
    rready_gen.set_low_time(2);
    rready_gen.set_high_time(1);
    mst_agent.rd_driver.send_rready(rready_gen);
  endtask
  *************************************************************************************************/


  /*************************************************************************************************
  * There are two ways to get read data. One is to get it through the read driver of master agent. 
  * The other is to get it through the monitor of VIP.(Please refer
  * monitor_rd_data_method_one, monitor_rd_data_method_two in *exdes_generic.sv file.)
  *
  * To get data from read driver, follow the steps listed below. 
  * step 1: Use the read driver in master agent to create a read transaction handle.
  * step 2: Randmoize the read transaction. If the user wants to generate a specific read command, 
            use the APIs in the axi_transaction class to set address, burst length, etc or 
            randomize the transaction with specific values.
  * step 3: Set driver_return_item_policy of the read transaction to be any of the follwing values:
  *         XIL_AXI_PAYLOAD_RETURN or XIL_AXI_CMD_PAYLOAD_RETURN.
  * step 4: Use the read driver to sends read transaction out.
  * step 5: Use the read driver to wait for the response.
  * step 6: Use get_data_beat/get_data_block to inspect data from the response transaction.
  *
  * driver_rd_data_method_one shows how to get a data beat from the read driver.
  * driver_rd_data_method_two shows how to get a data block from the read driver.
  * 
  * Note on API get_data_beat: get_data_beat returns the value of the specified beat. 
  * It always returns 1024 bits. It aligns the signification bytes to the lower 
  * bytes and sets the unused bytes to zeros.
  * This is NOT always the RDATA representation. If the data width is 32-bit and 
  * the transaction is sub-size burst (1B in this example), only the last byte of 
  * get_data_beat is valid. This is very different from the Physical Bus.
  * 
  * get_data_beat            Physical Bus
  * 1024  ...      0          32        0
  * ----------------         -----------
  * |             X|         |        X| 
  * |             X|         |      X  |
  * |             X|         |    X    |
  * |             X|         | X       |
  * ----------------         -----------
  *
  * Note on API get_data_block: get_data_block returns 4K bytes of the payload
  * for the transaction. This is NOT always the RDATA representation.  If the data
  * width is 32-bit and the transaction is sub-size burst (1B in this example),
  * It will align the signification bytes to the lower bytes and set the unused 
  * bytes to zeros.
  *
  *   get_data_block          Physical Bus
  *   32    ...      0         32        0
  * 0 ----------------         -----------
  *   | D   C   B   A|         |        A| 
  *   | 0   0   0   0|         |      B  |
  *   | 0   0   0   0|         |    C    |
  *   | 0   0   0   0|         | D       |
  *   | 0   0   0   0|         -----------
  *   | 0   0   0   0|         
  * 1k----------------         
  *
  *************************************************************************************************/
  
  task driver_rd_data_method_one();
    axi_transaction                         rd_trans;
    xil_axi_data_beat                       mtestDataBeat[];
    rd_trans = mst_agent.rd_driver.create_transaction("read transaction with randomization");
    RD_TRANSACTION_FAIL_1a:assert(rd_trans.randomize());
    rd_trans.set_driver_return_item_policy(XIL_AXI_PAYLOAD_RETURN);
    mst_agent.rd_driver.send(rd_trans);
    mst_agent.rd_driver.wait_rsp(rd_trans);
    mtestDataBeat = new[rd_trans.get_len()+1];
    for( xil_axi_uint beat=0; beat<rd_trans.get_len()+1; beat++) begin
      mtestDataBeat[beat] = rd_trans.get_data_beat(beat);
   //   $display("Read data from Driver: beat index %d, Data beat %h ", beat, mtestDataBeat[beat]);
    end  
  endtask 

  
  task driver_rd_data_method_two();  
    axi_transaction                         rd_trans;
    bit[8*4096-1:0]                         data_block;
    rd_trans = mst_agent.rd_driver.create_transaction("read transaction with randomization");
    RD_TRANSACTION_FAIL_1a:assert(rd_trans.randomize());
    rd_trans.set_driver_return_item_policy(XIL_AXI_PAYLOAD_RETURN);
    mst_agent.rd_driver.send(rd_trans);
    mst_agent.rd_driver.wait_rsp(rd_trans);
    data_block = rd_trans.get_data_block();
   // $display("Read data from Driver: Block Data %h ", data_block);
  endtask
``` 
</details>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?