芯片验证中axi vip的基本用法

(1) 在connection中进行signal的连接,以及config_db.

`include "uvm_pkg.sv"
`include "svt_axi_if.svi"
`include "svt_axi.uvm.pkg"
import uvm_pkg::*;
import svt_uvm_pkg::*;
import svt_axi_uvm_pkg::*;

module top;

svt_axi_if axi_if;

initial begin
  信号连接.
  force axi_if.xxx = dut.xxx;
  uvm_config_db#(virtual svt_axi_if)::set(uvm_root::get(), "uvm_test_top.env.axi_system_env", "vif", axi_if);
end

endmodule

(2) 在env中搭建axi的相关环境

  axi_system_env中master和slave的monitor中有item_start_port和item_observed_port,item_start_port中只有地址相关信息,item_observed_port比较常用,包含地址和数据和strb等信息, 连接后把数据打印一下就好.

`include "cust_svt_axi_system_configuration.sv"

class base_env extends uvm_env;

  svt_axi_system_env                  axi_system_env;
  cust_svt_axi_system_configuration   axi_sys_cfg;
  axi_slv_subscriber                  slv_scbr;

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    axi_system_env = svt_axi_system_env::type_id::create("axi_system_env", this);
    axi_sys_cfg = cust_svt_axi_system_configuration::type_id::("axi_sys_cfg");
    uvm_config_db#(svt_axi_system_configuration)::set(this, "axi_sytem_env", "cfg", axi_sys_cfg);
    slv_scbr = axi_slv_subscriber::type_id::create("slv_scbr", this);
  endfunction

  virtual function void connet_phase(uvm_phase phase);
    vseqr.axi0_mst_seqr = axi_system_env.master[0].sequencer;
    vseqr.axi0_slv_seqr = axi_system_env.slave[0].sequencer;
    xxx
    
    axi_system_env.master[0].monitor.item_started_port.connect(slv_scbr.analysis_export);
    axi_system_env.master[0].monitor.item_observed_port.connect(slv_scbr.axi_slv_export);
  endfunction

endclass

(3) cust_svt_axi_system_configuration相关部分配置

class cust_svt_axi_system_configuration extends svt_axi_system_configuration;
  `uvm_object_utils(cust_svt_axi_system_configuration)

  function new(string name = "cust_svt_axi_system_configuration");
    super.new(name);
    this.num_masters = 3;
    this.num_slaves  = 3;

    this.create_sub_cfgs(3,3);
    
    this.wready_watchdog_timeout = 0;
    this.rdata_watchdog_timeout  = 0;
    this.rready_watchdog_timeout = 0;
    this.bready_watchdog_timeout = 0;

    this.master_cfg[0].is_active = 1;
    this.master_cfg[0].enable_xml_gen =1;
    this.master_cfg[0].addr_width =32;
    this.master_cfg[0].data_width = 64;
    this.master_cfg[0].id_width = 5;
    if($test$plusargs("exclusive")) begin
      this.master_cfg[0].exclusive_access_enable = 1;
    end else begin
      this.master_cfg[0].exclusive_access_enable = 0;
    end
    if($test$plusargs("bready_delay")) begin
      this.master_cfg[0].default_bready = 0;
    end
    
    this.master_cfg[0].axi_interface_type = svt_axi_port_configuragion:AXI4;
    this.master_cfg[0].awuser_enable = 1;
    this.master_cfg[0].wuser_enable  = 0;
    this.master_cfg[0].buser_enalbe  = 0;
    this.master_cfg[0].aruser_enable = 1;
    this.master_cfg[0].ruser_enable  = 0;
    this.master_cfg[0].awqos_enable  = 0;
    this.master_cfg[0].awregion_enable = 0;
    this.master_cfg[0].arqos_enable  = 0;
    this.master_cfg[0].arregion_enable = 0;
    this.master_cfg[0].num_outstanding_xact = -1;
    if($test$plusargs("ostd_on")) begin
      this.master_cfg[0].num_read_outstanding_xact  = 128;
      this.master_cfg[0].num_write_outstanding_xact = 128;
    end else begin
      this.master_cfg[0].num_read_outstanding_xact  = 1;
      this.master_cfg[0].num_write_outstanding_xact = 1;
    end
    this.master_cfg[0].toggle_coverage_enable = 1'b0;
    this.master_cfg[0].state_coverage_enable  = 1'b0;
    this.master_cfg[0].transaction_coverage_enable = 1'b0;

    this.slave_cfg[0].is_active = 1;
    this.slave_cfg[0].enable_xml_gen =1;
    this.slave_cfg[0].addr_width = 32;
    this.slave_cfg[0].data_width = 64;
    this.slave_cfg[0].id_width = 5;
    if($test$plusargs("exclusive")) begin
      this.slave_cfg[0].exclusive_access_enable = 1;
    end else begin
      this.slave_cfg[0].exclusive_access_enable = 0;
    end
    if($test$plusargs("bready_delay")) begin
      this.slave_cfg[0].default_bready = 0;
    end

    this.slave_cfg[0].axi_interface_type = svt_axi_port_configuragion:AXI4;
    this.slave_cfg[0].awuser_enable = 1;
    this.slave_cfg[0].wuser_enable  = 0;
    this.slave_cfg[0].buser_enalbe  = 0;
    this.slave_cfg[0].aruser_enable = 1;
    this.slave_cfg[0].ruser_enable  = 0;
    this.slave_cfg[0].awqos_enable  = 0;
    this.slave_cfg[0].awregion_enable = 0;
    this.slave_cfg[0].arqos_enable  = 0;
    this.slave_cfg[0].arregion_enable = 0;
    this.slave_cfg[0].num_outstanding_xact = -1;
    if($test$plusargs("ostd_on")) begin
      this.slave_cfg[0].num_read_outstanding_xact  = 128;
      this.slave_cfg[0].num_write_outstanding_xact = 128;
    end else begin
      this.slave_cfg[0].num_read_outstanding_xact  = 2;
      this.slave_cfg[0].num_write_outstanding_xact = 2;
    end
    this.slave_cfg[0].toggle_coverage_enable = 1'b0;
    this.slave_cfg[0].state_coverage_enable  = 1'b0;
    this.slave_cfg[0].transaction_coverage_enable = 1'b0;

    xxx

  endfunction
endclass

(4) 在filelist.f中添加define

+define+SYNOPSYS_SV
+define+UVM_DISABLE_AUTO_ITEM_RECORDING
+define+UVM_PACKER_MAX_BYTES=1500000

(5) 在scbr中打印axi的transaction

class axi_slv_subscriber extends uvm_subscriber#(svt_axi_transaction);
  `uvm_analysis_imp_decl(_axi_slv)

   uvm_analysis_imp_axi_slv#(svt_axi_transaction, axi_slv_subscriber) axi_slv_export;

   function new(string name="axi_slv_subscriber", uvm_componet parent=null);
     super.new(name, parent);
     axi_slv_export = new("axi_slv_export", this);
   endfunction

   extern virtual function void write_axi_slv(svt_axi_transaction t);
endclas

function void axi_slv_subscriber ::write_axi_slv(svt_axi_transaction t);
  svt_axi_transaction item;
  if(!$cast(item, t.clone()))
    `uvm_fatal("subscriber", "unable to case");
  item_q.push_back(item);
  `uvm_info(get_type_name(), $sformatf("subscriber, axi_item", item.sprint()), UVM_LOW)
endfunction

(6) master seq和slave seq的基本用法.

class write_sequence extends svt_axi_master_base_sequence;
  svt_axi_master_transaction req;

  `uvm_object_utils(write_sequence)
  function new(string name="write_sequence");
    super.new(name);
  endfunction

  virtual task body();
    svt_configuration get_cfg;
    super.body();
    p_sequencer.get_cfg(get_cfg);
    if(!$cast(cfg, get_cfg))begin
      `uvm_fatal("body", "unable to case")
    end

    `uvm_create(req);
    req.port_cfg = cfg;
    assert(req.randomize with {
             req.xact_type == svt_axi_transaction::WRITE;//READ
             req.enable_interleave == 1'b0;
             req.addr[31:0] == xx_addr;
             foreach(xx_data[idx])
               req.data[idx] == xx_data[idx];
             req.burst_type == svt_axi_transaction::INCR;
             req.burst_size == svt_axi_transaction::BURST_SIZE_32BIT;
             req.burst_length== xx_len;
             req.atomic_type == svt_axi_transaction::NORMAL;
             req.data_before_addr == 0;
             reference_event_for_first_wvalid_delay == svt_axi_transaction::WRITE_ADDR_HANDSHAKE;
             foreach(wstrb[j]) {(wstrb[j]== 32'hffff)};
          })
    `uvm_send(req)
    get_response(rsp);
  endtask
endclass



class axi_slave_sequence exntends svt_axi_slave_base_sequence;
  svt_axi_slave_transaction req_resp;
  `uvm_object_utils(axi_slave_sequence)

  function new(string name="axi_slave_sequence");
    super.new(name);
  endfunction
 
  virtual task body();
    interger status;
    sink_responses();

    forever begin
      p_sequencer.response_request_port.peek(req_resp);
      resp_cnt++;
      status = req_resp.randomize with {
        bresp == svt_axi_transaction::OKAY;
        foreach (rresp[index]) {
          rresp[index] inside {svt_axi_transaction::OKAY};
          enable_interleave == 0;
        }
      }
      if(!status)
        `uvm_fatal("body", "unable to randomize a resps")
      `uvm_send(req)
    end
  endtask
endclass

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值