AXI VIP集成 简单易懂

将Synopsys AXI VIP集成到自己原有的验证环境

1 生成VIP

按照生成步骤生成VIP,这里生成svt_axi_system_env,生成后只需要include和src文件夹,放在…/tb/axi_vip路径下(可根据个人习惯修改)

2 Makefile

在compile步骤添加宏定义

+define+UVM_PACKER_MAX_BYTES=1500000 +define+UVM_DISABLE_AUTO_ITEM_RECORDING

3 filelist

filelist中添加路径(根据实际修改"…/tb/axi_vip"路径)

+incdir+../tb/axi_vip/include/verilog
+incdir+../tb/axi_vip/include/sverilog
+incdir+../tb/axi_vip/src/verilog/vcs
+incdir+../tb/axi_vip/src/sverilog/vcs

../tb/axi_vip/include/sverilog/svt_axi_if.svi
../tb/axi_vip/include/sverilog/svt_amba.uvm.pkg

原有验证环境将environment、top_test、sequence分别包成了package,所以在package中import VIP包即可
env_pkg中添加下段代码

import svt_uvm_pkg::*;
import svt_amba_uvm_pkg::*;

top_test_pkg中添加下段代码

import svt_uvm_pkg::*;
import svt_amba_uvm_pkg::*;

sequence_pkg中添加下段代码,两个sequence后续会描述

import svt_uvm_pkg::*;
import svt_amba_uvm_pkg::*;

axi_master_wr_sequence.sv
axi_slave_mem_response_sequence.sv

4 environment

在顶层environment中添加子AXI environment
声明部分添加下段代码

svt_axi_system_env   axi_system_env;

build_phase添加下段代码

axi_system_env = svt_axi_system_env::type_id::create("axi_system_env", this);

5 sequence

(1)axi_slave_mem_response_sequence
直接从example复制过来的slave sequence
主要内容是接收来自monitor的transaction,添加信息后发送至driver,添加信息包括随机延时、bresp/rresp返回OKAY、读数据等,同时将AXI读写转换为svt_mem的读写

p_sequencer.response_request_port.peek(req_resp);

status=req_resp.randomize with {
	bresp == svt_axi_slave_transaction::OKAY;
	foreach (rresp[index])  {
		rresp[index] == svt_axi_slave_transaction::OKAY;
	}
};

if(req_resp.get_transmitted_channel() == svt_axi_slave_transaction::WRITE)
	put_write_transaction_data_to_mem(req_resp);
if (req_resp.get_transmitted_channel() == svt_axi_slave_transaction::READ)
	get_read_data_from_mem_to_transaction(req_resp);

(2)axi_master_wr_sequence
简单的master sequence,父类为svt_axi_master_base_sequence,只包含读写行为,通过wr_mode决定读/写,data_arr可以作为写数据也可以作为读数据,作读数据时需要预先分配长度,作为burst长度

int wr_mode; // 1:write 0:read
bit [127:0] data_arr [] ;
bit [31:0]  addr ;

body()中配置AXI读写信息,包含读/写、地址、burst size、burst 长度、数据、地址和延时等
burst size小于端口宽度时,VIP会自动移位,strb和data低对齐即可

`uvm_do_with(req,
	{
		xact_type    == wr_mode ? svt_axi_transaction::WRITE : svt_axi_transaction::READ ;
        data_before_addr == 0;
        addr         == local::addr;
        burst_type   == svt_axi_transaction::INCR;
        burst_size   == svt_axi_transaction::BURST_SIZE_32BIT;
        burst_length == data_arr.size();
        if(wr_mode) foreach(data[fi]) data[fi] == data_arr[fi];
        if(wr_mode) foreach(wstrb[fi]) wstrb[fi] == 4'hf;
	}) 
    
get_response(rsp);

if(!wr_mode)
    foreach(data_arr[fi])
        data_arr[fi] = rsp.data[fi];

6 test

(1)top_base_test
将通用例化和配置加入top_base_test,主要包括:
a)将AXI配置发信至axi_system_env,具体配置是包含1主1从、AXI数据宽度256、slave地址全范围可读写
b)将AXI slave的sequence发送至VIP slave agent,行为是将AXI读写转换为对svt_mem的读写

声明部分添加下段代码

svt_axi_system_configuration cfg;

build_phase添加下段代码

cfg = svt_axi_system_configuration::type_id::create("cfg");
cfg.num_masters = 1;
cfg.num_slaves  = 1;
cfg.system_monitor_enable = 1;
cfg.create_sub_cfgs(1,1);
cfg.master_cfg[0].data_width = 256;
cfg.slave_cfg[0].data_width = 256;
cfg.master_cfg[0].id_width = 8;
cfg.slave_cfg[0].id_width = 8;
cfg.set_addr_range(0,64'h0,64'hffff_ffff_ffff_ffff);

uvm_config_db#(svt_axi_system_configuration)::set(this, "top_env.axi_system_env", "cfg", cfg);

uvm_config_db#(uvm_object_wrapper)::set(this, "top_env.axi_system_env.slave*.sequencer.run_phase", "default_sequence", axi_slave_mem_response_sequence::type_id::get());

(2)axi_wr_test
将会执行的AXI读写test,是top_base_test的子类,test内容是:
a)通过AXI master发送写burst,地址32’h200,数据’{5,6,7,8}
b)后门读svt_mem,期待读到’{5,6,7,8}
c)后门写svt_mem,修改为’{9,10,11,12}
d)通过AXI master发送读burst,地址32’h200,期待读到’{9,10,11,12}
声明部分代码

axi_master_wr_sequence seq_axi_wr;
bit [31:0] rdata;

build_phase代码

// step a
seq_axi_wr = new();
seq_axi_wr.wr_mode = 1;
seq_axi_wr.data_arr = '{5,6,7,8};
seq_axi_wr.addr = 32'h200;
seq_axi_wr.start(top_env.axi_system_env.master[0].sequencer);
// step b
foreach(seq_axi_wr.data_arr[fi]) begin
  top_env.axi_system_env.slave[0].read_byte(32'h200+4*fi, rdata);
  `uvm_info("body", $sformatf("back-door rdata %32h",rdata), UVM_LOW);
  top_env.axi_system_env.slave[0].write_byte(32'h200+4*fi, 9+fi);
end
// step c
seq_axi_wr = new();
seq_axi_wr.wr_mode = 0;
seq_axi_wr.data_arr = new[4];
seq_axi_wr.addr = 32'h200;
seq_axi_wr.start(top_env.axi_system_env.master[0].sequencer);
// step d
foreach(seq_axi_wr.data_arr[fi])
  `uvm_info("body", $sformatf("front-door rdata %32h",seq_axi_wr.data_arr[fi]), UVM_LOW);

7 top_tb

tb中定义svt_axi_if接口,默认common模式下只需要连接common时钟,每个master/slave需要单独连接复位,为了便于验证将master和slave直接连接,只列举AW通道信号,其他略。最后再将接口传递至axi_system_env的虚接口

svt_axi_if axi_if();
    
assign axi_if.common_aclk = clk_200MHz;
assign axi_if.master_if[0].aresetn = rst_n;
assign axi_if.slave_if[0].aresetn = rst_n;

assign axi_if.slave_if[0].awvalid = axi_if.master_if[0].awvalid;
assign axi_if.slave_if[0].awaddr  = axi_if.master_if[0].awaddr ;
assign axi_if.slave_if[0].awlen   = axi_if.master_if[0].awlen  ;
assign axi_if.slave_if[0].awsize  = axi_if.master_if[0].awsize ;
assign axi_if.slave_if[0].awburst = axi_if.master_if[0].awburst;
assign axi_if.slave_if[0].awlock  = axi_if.master_if[0].awlock ;
assign axi_if.slave_if[0].awcache = axi_if.master_if[0].awcache;
assign axi_if.slave_if[0].awprot  = axi_if.master_if[0].awprot ;
assign axi_if.slave_if[0].awid    = axi_if.master_if[0].awid   ;
assign axi_if.master_if[0].awready = axi_if.slave_if[0].awready;

initial begin
    uvm_config_db#(virtual svt_axi_if)::set(uvm_root::get(), "uvm_test_top.top_env.axi_system_env", "vif", axi_if);
    run_test();
end

7 执行结果

(1)verdi波形
可以看到先发起写burst ‘{5,6,7,8},由于期间后门修改了数据,再读burst读到’{9,10,11,12}
在这里插入图片描述

(2)sim log,后门读取读到’{5,6,7,8},期间后门修改了数据,再通过AXI master前门读取读到’{9,10,11,12}
在这里插入图片描述
在这里插入图片描述

<think>好的,我现在需要回答用户关于UVM中UVC是什么的问题。首先,我得回想一下之前用户的问题和我的回答,确保这次回答保持一致性和准确性。之前用户询问了UVM中“.”和“::”的区别,我详细解释了它们的用法和区别,现在用户可能希望深入了解UVM的其他组件,比如UVC。 首先,我需要明确UVC的定义。UVC是UVM Verification Component的缩写,中文通常翻译为验证组件。它是UVM方法学中的一个重要概念,用于模块化和重用验证环境。接下来,我需要考虑用户可能的背景,他们可能是刚开始学习UVM,所以需要从基础开始解释,同时结构清晰,分点说明。 我需要解释UVC的组成部分,通常包括Driver、Monitor、Sequencer、Agent等。然后,说明UVC的作用,比如提高重用性、标准化验证流程等。还需要提到UVC的结构,可能包括主动和被动模式,或者根据协议不同有不同的实现。 可能还需要比较UVC和其他组件(如Env)的关系,但用户没有问到,所以可能不需要展开。要确保用简单的中文术语,避免过于专业的行话,但必要时使用术语并加以解释。 另外,我需要检查是否有常见的误解需要澄清,例如UVC和VIP(Verification IP)的关系。可能需要指出UVC通常是VIP的一部分,但具体实现可能因公司或项目而异。 然后,我需要组织回答的结构,可能分为定义、组成部分、作用、示例、总结等部分。使用标题和项目符号来使内容更清晰,符合用户之前对结构清晰的要求。 需要确保使用正确的术语和正确的技术细节,比如UVC如何与Testbench集成,使用config_db进行配置等。同时,可能需要给出一个简单的代码示例,说明UVC的结构,但用户之前的问题中没有代码示例,但可能有助于理解。 最后,总结UVC的重要性,以及在验证环境中的优势,比如加速验证过程,提高代码复用率等。还要注意不要遗漏任何关键点,比如UVC的复用性和标准化如何帮助团队协作。 现在,我需要将这些思考整理成一个连贯的回答,使用用户指定的格式,分点说明,结构清晰,同时确保技术准确性。可能还需要对比之前的回答,保持一致的风格和术语使用。例如,使用中文术语,避免直接使用英文缩写而不解释,必要时给出英文全称和缩写。 需要确保回答符合用户提供的系统级指令,如使用正确的LaTeX格式(虽然这个问题可能不涉及数学表达式,但如果有变量或代码示例,需正确应用格式)。不过UVC的介绍可能更多是概念性的,所以可能不需要LaTeX,但代码块需要用正确的标记。 最后,检查是否有错别字或语法错误,确保回答准确、易懂,并且符合用户的要求。</think>### UVM 中 UVC 是什么? 在 **UVM(Universal Verification Methodology)** 中,**UVC(UVM Verification Component,验证组件)** 是验证环境的核心模块化单元,用于构建可复用的验证 IP(VIP)。它封装了针对特定协议或功能模块的验证逻辑,能够独立配置和集成到不同的测试平台(Testbench)中。 --- ### 一、UVC 的组成 一个典型的 UVC 包含以下关键组件: | 组件 | 功能 | |---------------|----------------------------------------------------------------------| | **Agent** | 核心容器,包含 `Driver`、`Monitor`、`Sequencer` 等子组件,控制数据流 | | **Driver** | 将事务(Transaction)转换为协议信号,驱动到 DUT(被测设计) | | **Monitor** | 监视 DUT 接口,捕获信号并转换为事务,用于功能覆盖或检查 | | **Sequencer** | 生成事务序列(Sequence),控制测试场景的生成逻辑 | | **Scoreboard**| (可选)比较 DUT 输出与预期结果,实现自动校验 | | **Configuration** | 配置 UVC 的工作模式(如主动/被动)、协议参数等 | --- ### 二、UVC 的作用 1. **模块化复用** - UVC 封装了协议相关的验证逻辑,可跨项目复用。例如:一个 AXI UVC 可复用于所有支持 AXI 协议的设计。 2. **标准化验证流程** - 提供统一的接口和配置方法,简化验证环境的搭建和维护。 3. **支持多种验证模式** - **主动模式(Active)**:生成激励并驱动到 DUT(通常包含 Driver 和 Sequencer)。 - **被动模式(Passive)**:仅监视 DUT 接口(不生成激励),用于监控或协议检查。 4. **集成覆盖率收集** - 内置功能覆盖率模型(Covergroup),可直接收集协议覆盖率。 --- ### 三、UVC 的典型结构 ```systemverilog class axi_uvc extends uvm_component; // 子组件声明 axi_agent agent; // Agent 管理 Driver/Monitor/Sequencer axi_config cfg; // 配置对象 axi_scoreboard scb; // 计分板 // 构建阶段:创建子组件 function void build_phase(uvm_phase phase); agent = axi_agent::type_id::create("agent", this); cfg = axi_config::type_id::create("cfg"); scb = axi_scoreboard::type_id::create("scb", this); endfunction // 连接阶段:绑定 Monitor 到 Scoreboard function void connect_phase(uvm_phase phase); agent.monitor.item_collected_port.connect(scb.analysis_export); endfunction endclass ``` --- ### 四、UVC 与 VIP 的关系 - **UVC** 是 **VIP(Verification IP)** 的实现形式之一。 - VIP 可能包含多个 UVC(如 PCIe VIP 含 Root Complex UVC 和 Endpoint UVC)。 - 商用 VIP 通常还包含文档、测试用例和覆盖率模型。 --- ### 五、UVC 的使用场景 1. **协议验证** - 如 AXI、APB、I2C 等总线协议的验证。 2. **IP 核验证** - 针对特定 IP(如 USB 控制器)定制 UVC。 3. **系统级验证** - 多个 UVC 协同工作,验证芯片级交互(如 CPU 与外设通信)。 --- ### 六、优势与挑战 | 优势 | 挑战 | |-------------------------------|-------------------------------------| | 提高验证效率(复用性) | 初期开发成本较高(需完整实现协议逻辑)| | 标准化接口(易于集成) | 需维护协议更新(如新版本 AXI) | | 支持动态配置(通过 Config DB)| 对复杂协议的覆盖率建模较复杂 | --- ### 七、总结 - **UVC 是 UVM 验证环境的“乐高积木”**,通过模块化设计简化复杂验证任务。 - 其核心价值在于 **复用性** 和 **标准化**,尤其适合大型项目或协议驱动的验证场景。 - 实际开发中,UVC 的设计需平衡灵活性与性能,并注重协议规范的完整覆盖。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值