分享一个AXI VIP,含详细使用说明

科技   2024-11-26 12:01   陕西  


1.前言

分享一个AMBA AXI VIP,用法和Synopsys的VIP非常类似。本文会详细介绍如何使用该VIP的全过程;文末送全部资料。

2. 以AXI VIP为例,跑该VIP的Example
2.1文件结构如下:
svk--    |-- base    |    |-- vip         |         |-- example         |      |-- axi         |-- src                |-- axi

运行AXI VIP example的方法,如下所示:

cd svk/vip/example/axi/make run
3. AXI VIP详细介绍

总体结构框图,如下图所示

4.集成AXI VIP的步骤

如果想集成该AXI VIP到TestBench中,一共需要如下五步:

4.1连接VIP和DUT;4.2实例化和配置VIP;4.3构造一个Sequence;4.4构造一个Test;4.5添加VIP的文件和路径到编译和仿真。

4.1连接VIP和DUT

module harness;    // 1. Include packages.    import uvm_pkg::*;    import svk_pkg::*;    import svk_axi_pkg::*;    import axi_env_pkg::*;
...
// 2. instantiate and connect clock/reset. svk_axi_ifs u_if(); assign u_if.master[0].aclk = clk; assign u_if.master[0].aresetn = rstn; assign u_if.slave[0].aclk = clk; assign u_if.slave[0].aresetn = rstn;
// 3. connect AXI interface to the DUT, recommand use force initial begin force u_if.slave[0].awvalid = MST_DUT.awvalid; force MST_DUT.awready = u_if.slave[0].awready;
force SLV_DUT.awvalid = u_if.master[0].awvalid; force u_if.master[0].awready = SLV_DUT.awready; ... end
// 4. send virtual interface to environment, "axi_sys_env" is an instance of the AXI system environment(svk_axi_sys_env) initial begin uvm_config_db#(virtual svk_axi_ifs)::set(null, "uvm_test_top.env.axi_sys_env", "vif", u_if); endendmodule


4.2实例化和配置VIP


4.2.1 参考下面的cfg代码

class cust_axi_sys_env_cfg extends svk_axi_sys_env_cfg;    `uvm_object_utils(cust_axi_sys_env_cfg)
function new(string name="cust_axi_sys_env_cfg"); super.new(name);
master_num = 1; slave_num = 1; create_sub_cfg(master_num, slave_num); for(int i=0; i<master_num; ++i)begin master_cfg[i].version = svk_axi_dec::AXI4; master_cfg[i].work_mode = svk_dec::MASTER; master_cfg[i].wr_osd = 10; master_cfg[i].rd_osd = 10; master_cfg[i].ready_timeout_time = 1000; master_cfg[i].data_width = 256; master_cfg[i].addr_width = 32; master_cfg[i].id_width = 8; end for(int i=0; i<slave_num; ++i)begin slave_cfg[i].version = svk_axi_dec::AXI4; slave_cfg[i].work_mode = svk_dec::SLAVE; slave_cfg[i].wr_osd = 10; slave_cfg[i].rd_osd = 10; slave_cfg[i].ready_timeout_time = 1000; slave_cfg[i].data_width = 256; slave_cfg[i].addr_width = 32; slave_cfg[i].id_width = 8; end endfunction

endclass


4.2.2 env参考下面的代码

class axi_env extends uvm_env;    `uvm_component_utils(axi_env)    svk_axi_sys_env         axi_sys_env;    svk_axi_sys_env_cfg     axi_sys_env_cfg;
function new(string name="axi_env", uvm_component parent); super.new(name, parent); endfunction
function void build_phase(uvm_phase phase); super.build_phase(phase); // instanciate svk_axi_sys_env axi_sys_env = svk_axi_sys_env::type_id::create("axi_sys_env", this);
// set configuration to svk_axi_sys_env axi_sys_env_cfg = cust_axi_sys_env_cfg::type_id::create("axi_sys_env_cfg"); uvm_config_db#(svk_axi_sys_env_cfg)::set(this, "axi_sys_env", "cfg", axi_sys_env_cfg); endfunction
endclass

5.构造Sequence,参考下面的代码:

svk_axi_default_master_sequence如下所示:

task svk_axi_default_master_sequence::body();    svk_axi_transaction tr;    svk_axi_agent_cfg   axi_cfg;    svk_agent_cfg       get_cfg;

// get agent configuration get_cfg = p_sequencer.get_cfg(); if(!$cast(axi_cfg, get_cfg)) `uvm_error(get_type_name(), "config type is not svk_axi_agent_cfg")
repeat(10)begin // construct transaction and set configuration tr = svk_axi_transaction::type_id::create("tr"); tr.cfg = axi_cfg; // randomize transactoin and send to driver tr.randomize() with { addr >= 'h8000_0000; addr < 'h8000_00ff; dir == svk_axi_dec::READ; burst == svk_axi_dec::BURST_INCR; length < 20; need_resp == 1; }; `uvm_send(tr) if(tr.need_resp) get_response(rsp, tr.get_transaction_id()); end
...
endtask


svk_axi_default_slave_sequence如下所示:

 task body();        svk_axi_transaction tr;
forever begin // get transacton from slave dirver p_sequencer.response_request_port.peek(req); $cast(tr, req);
// randomize and set delay tr.randomize();
tr.awready_delay = 2; tr.arready_delay = 0; foreach(tr.wready_delay[i]) tr.wready_delay[i] = i;
tr.bvalid_delay = 1; foreach(tr.rvalid_delay[i]) tr.rvalid_delay[i] = i;
// write transaction data to memory or read data from memory to transaction if(tr.dir == svk_axi_dec::WRITE)begin p_sequencer.write_data_to_mem(tr); end else if(tr.dir == svk_axi_dec::READ)begin p_sequencer.read_data_from_mem(tr); end
`uvm_send(tr) end
endtask


6.构造TEST,请参考下面的代码:

function void build_phase(uvm_phase phase);    super.build_phase(phase);    // Instanciate environment    env = axi_env::type_id::create("env", this);
// start sequence by default sequence mechanism uvm_config_db#(uvm_object_wrapper)::set(null, "*axi_sys_env.master[0].sqr.main_phase", "default_sequence", svk_axi_default_master_sequence::type_id::get()); uvm_config_db#(uvm_object_wrapper)::set(null, "*axi_sys_env.slave[0].sqr.main_phase", "default_sequence", svk_axi_default_slave_sequence::type_id::get());
endfunction

7.添加文件和路径到编译和仿真,请参考下面的代码:

// specify the directory paths for compiler to load VIP files+incdir+../../../../svk
// Add Packges and Source file for compiler../../../../svk/svk_pkg.sv../../../../svk/svk_axi_pkg.svaxi_env_pkg.svtop.sv

8.更多的配置

8.1AGENT的配置,如下面代码所示:

    svk_axi_dec::version_enum                      version                  = svk_axi_dec::AXI3          ;    int unsigned                                   wr_osd                   = 1                          ;    int unsigned                                   rd_osd                   = 10                         ;    bit                                            wr_interleave_en         = 1'b0                       ;    int unsigned                                   wr_interleave_depth      = 1                          ;    bit                                            rd_interleave_en         = 1'b0                       ;    bit                                            wr_out_of_order_en       = 1'b0                       ;    bit                                            rd_out_of_order_en       = 1'b0                       ;
bit data_before_addr = 1'b0 ;
svk_axi_dec::awvalid_delay_event_enum awvalid_delay_event = svk_axi_dec::AWV_PREV_AW_HANDSHAKE_EVENT; svk_axi_dec::arvalid_delay_event_enum arvalid_delay_event = svk_axi_dec::ARV_PREV_AR_HANDSHAKE_EVENT; svk_axi_dec::first_wvalid_delay_event_enum first_wvalid_delay_event = svk_axi_dec::FWV_PREV_W_HANDSHAKE_EVENT ; svk_axi_dec::next_wvalid_delay_event_enum next_wvalid_delay_event = svk_axi_dec::NWV_PREV_W_HANDSHAKE_EVENT ; svk_axi_dec::first_rvalid_delay_event_enum first_rvalid_delay_event = svk_axi_dec::FRV_AR_HANDSHAKE_EVENT ; svk_axi_dec::next_rvalid_delay_event_enum next_rvalid_delay_event = svk_axi_dec::NRV_PREV_R_HANDSHAKE_EVENT ; svk_axi_dec::bvalid_delay_event_enum bvalid_delay_event = svk_axi_dec::BV_LAST_W_HANDSHAKE_EVENT ;
svk_axi_dec::awready_delay_event_enum awready_delay_event = svk_axi_dec::AWR_AWVALID_EVENT ; svk_axi_dec::arready_delay_event_enum arready_delay_event = svk_axi_dec::ARR_ARVALID_EVENT ; svk_axi_dec::wready_delay_event_enum wready_delay_event = svk_axi_dec::WR_WVALID_EVENT ; svk_axi_dec::bready_delay_event_enum bready_delay_event = svk_axi_dec::BR_BVALID_EVENT ; svk_axi_dec::rready_delay_event_enum rready_delay_event = svk_axi_dec::RR_RVALID_EVENT ;
bit default_bready = 1'b1 ; bit default_rready = 1'b1 ; bit default_awready = 1'b1 ; bit default_arready = 1'b1 ; bit default_wready = 1'b1 ; svk_dec::default_value_enum mem_default_value = svk_dec::DEFAULT_ZERO ; svk_dec::idle_value_enum idle_value = svk_dec::IDLE_ZERO ;
int unsigned ready_timeout_time = 1000 ; int unsigned data_width = `SVK_AXI_DATA_WIDTH ; int unsigned addr_width = `SVK_AXI_ADDR_WIDTH ; int unsigned id_width = `SVK_AXI_ID_WIDTH ; int unsigned data_user_width = `SVK_AXI_USER_WIDTH ; // w/r int unsigned resp_user_width = `SVK_AXI_USER_WIDTH ; // b int unsigned addr_user_width = `SVK_AXI_USER_WIDTH ; // aw/ar

8.2 Transaction的配置,参考下面的代码:

uvm_object                                      extension      ;rand bit                                        need_resp      ;

rand int awready_delay ;rand int awvalid_delay ;rand int arready_delay ;rand int arvalid_delay ;rand int wready_delay[] ;rand int wvalid_delay[] ;rand int rready_delay[] ;rand int rvalid_delay[] ;rand int bvalid_delay ;rand int bready_delay ;
svk_axi_agent_cfg cfg;

9.重要的宏定义

`define SVK_AXI_ADDR_WIDTH             64`define SVK_AXI_DATA_WIDTH             1024`define SVK_AXI_WSTRB_WIDTH            `SVK_AXI_DATA_WIDTH/8`define SVK_AXI_LEN_WIDTH              8`define SVK_AXI_SIZE_WIDTH             3`define SVK_AXI_BURST_WIDTH            2`define SVK_AXI_LOCK_WIDTH             2`define SVK_AXI_CACHE_WIDTH            4`define SVK_AXI_PROT_WIDTH             3`define SVK_AXI_ID_WIDTH               64`define SVK_AXI_QOS_WIDTH              4`define SVK_AXI_REGION_WIDTH           4`define SVK_AXI_RESP_WIDTH             2`define SVK_AXI_USER_WIDTH             64`define SVK_AXI_MAX_OSD                1024`define SVK_AXI_MAX_NUM_MASTER         16`define SVK_AXI_MAX_NUM_SLAVE          16

10.接口信号,如下代码所示:

    logic                                   aclk;    logic                                   aresetn;
logic awvalid; logic awready; logic [`SVK_AXI_ID_WIDTH -1: 0] awid; logic [`SVK_AXI_ADDR_WIDTH -1: 0] awaddr; logic [`SVK_AXI_LEN_WIDTH -1: 0] awlen; logic [`SVK_AXI_SIZE_WIDTH -1: 0] awsize; logic [`SVK_AXI_BURST_WIDTH -1: 0] awburst; logic [`SVK_AXI_LOCK_WIDTH -1: 0] awlock; logic [`SVK_AXI_CACHE_WIDTH -1: 0] awcache; logic [`SVK_AXI_PROT_WIDTH -1: 0] awprot; logic [`SVK_AXI_REGION_WIDTH -1: 0] awregion; logic [`SVK_AXI_USER_WIDTH -1: 0] awuser; logic [`SVK_AXI_QOS_WIDTH -1: 0] awqos;
logic arvalid; logic arready; logic [`SVK_AXI_ID_WIDTH -1: 0] arid; logic [`SVK_AXI_ADDR_WIDTH -1: 0] araddr; logic [`SVK_AXI_LEN_WIDTH -1: 0] arlen; logic [`SVK_AXI_SIZE_WIDTH -1: 0] arsize; logic [`SVK_AXI_BURST_WIDTH -1: 0] arburst; logic [`SVK_AXI_LOCK_WIDTH -1: 0] arlock; logic [`SVK_AXI_CACHE_WIDTH -1: 0] arcache; logic [`SVK_AXI_PROT_WIDTH -1: 0] arprot; logic [`SVK_AXI_REGION_WIDTH -1: 0] arregion; logic [`SVK_AXI_USER_WIDTH -1: 0] aruser; logic [`SVK_AXI_QOS_WIDTH -1: 0] arqos;
logic rvalid; logic rready; logic rlast; logic [`SVK_AXI_ID_WIDTH -1: 0] rid; logic [`SVK_AXI_DATA_WIDTH -1: 0] rdata; logic [`SVK_AXI_RESP_WIDTH -1: 0] rresp; logic [`SVK_AXI_USER_WIDTH -1: 0] ruser;
logic wvalid; logic wready; logic wlast; logic [`SVK_AXI_ID_WIDTH -1: 0] wid; logic [`SVK_AXI_DATA_WIDTH -1: 0] wdata; logic [`SVK_AXI_WSTRB_WIDTH -1: 0] wstrb; logic [`SVK_AXI_USER_WIDTH -1: 0] wuser;
logic bvalid; logic bready; logic [`SVK_AXI_ID_WIDTH -1: 0] bid; logic [`SVK_AXI_RESP_WIDTH -1: 0] bresp; logic [`SVK_AXI_USER_WIDTH -1: 0] buser;
logic csysreq; logic csysack;logic   cactive;


资料获取:

链接:https://pan.baidu.com/s/1BupW11F7a_iWzbgQXgQh7g?pwd=1234


提取码:1234




*免责声明:本文由作者原创。文章内容系作者个人观点,路科验证转载仅为了传达一种不同的观点,不代表路科验证对该观点赞同或支持,如果有任何异议,欢迎联系路科验证。




















路科验证
专注于数字芯片验证的系统思想和前沿工程领域。
 最新文章