当前位置: 首页 > java >正文

APB协议​​ 构建一个完整的 ​​UVM验证VIP Agent介绍类的要素

下面将基于 ​​APB协议​​ 构建一个完整的 ​​UVM验证VIP Agent​​,包含 ​​Transaction(事务类)Sequence(序列类)Sequencer(序列发生器类)​​ 三大核心组件,并扩展 ​​Driver(驱动类)Monitor(监测类)、**Agent(代理类)**​​ 形成完整验证环境。每个组件均附带 ​​工作原理详解​​ 和 ​​逐行注释​​,确保彻底理解其设计逻辑和UVM协作机制。

​​完整APB验证VIP Agent设计​​

​​1. Transaction(事务类)—— 描述APB激励的数据结构​​

​​工作原理​​

Transaction是验证平台中最基础的单元,用于 ​​描述DUT(被测设计)的一次输入或输出行为​​。在APB协议中,一个事务包含 ​​地址(addr)数据(data)、**读写标志(we)**​​ 等关键信息。

​​核心作用​​:作为验证激励的载体,通过随机化生成多样化的测试场景(如不同地址、数据组合),驱动DUT并验证其功能正确性。

​​代码实现(apb_transaction.sv)​​

// 定义APB事务类,继承自uvm_sequence_item(UVM标准基类,支持序列化、打印、随机化等)
class apb_transaction extends uvm_sequence_item;// ===== 成员变量:描述APB事务的属性(数据) =====// rand logic [3:0] addr;  // 4位地址信号(随机化,APB协议中地址宽度通常为4-32bit,此处简化)// rand logic [7:0] data;  // 8位数据信号(随机化,APB数据宽度简化为8bit)// rand bit we;            // 写使能标志(1=写操作,0=读操作)// 注意:原案例中为演示封装改为local,此处恢复rand以支持随机化(验证必需)rand logic [3:0] addr;  // 4位地址(随机化,覆盖0~15)rand logic [7:0] data;  // 8位数据(随机化,覆盖0~255)rand bit we;            // 写使能(1=写DUT,0=读DUT)// ===== UVM支持宏:注册成员变量到UVM框架(支持打印、随机化、约束等) =====`uvm_object_utils_begin(apb_transaction)`uvm_field_int(addr, UVM_DEFAULT)  // 注册addr变量(支持UVM打印和随机化)`uvm_field_int(data, UVM_DEFAULT)  // 注册data变量`uvm_field_int(we, UVM_DEFAULT)    // 注册we变量`uvm_object_utils_end// ===== 构造函数:初始化对象(必须调用父类构造函数) =====// 参数name:对象的名称(用于调试时标识,可选,默认"apb_transaction")function new(string name="apb_transaction");super.new(name);  // 调用父类uvm_sequence_item的构造函数,初始化UVM内部状态endfunction// ===== 可选:约束随机化范围(限制地址和数据的有效范围) =====// 作用:确保生成的地址和数据符合APB协议规范(例如地址0x0~0xF,数据0x00~0xFF)constraint addr_range { addr inside {[0:15]}; }  // 地址范围:4bit有效(0~15)constraint data_range { data inside {[0:255]}; } // 数据范围:8bit有效(0~255)// ===== 可选:成员方法(打印事务内容,调试用) =====// 功能:将事务的addr/data/we值格式化输出到仿真控制台function void print_transaction();$display("APB Transaction: addr=0x%h, data=0x%h, we=%0b (操作=%s)", addr, data, we, (we ? "写" : "读"));endfunctionendclass

​​关键点总结​​:

•​​随机化支持​​:rand关键字允许通过约束(如 addr_range)生成符合协议的随机地址/数据(覆盖更多测试场景)。

•​​UVM集成​​:uvm_object_utils宏让UVM能识别该类(支持序列化、打印、随机化约束)。

•​​调试辅助​​:print_transaction()方法用于验证时检查事务内容是否符合预期。

​​2. Sequence(序列类)—— 生成激励事务的逻辑​​

​​工作原理​​
Sequence是UVM中 ​​生成激励事务(Transaction)的逻辑单元​​,通过定义 body()任务来创建一系列Transaction,并通过Sequencer发送给Driver。

​​核心作用​​:控制激励的生成策略(如顺序执行、随机生成、特定场景覆盖),是验证平台中 ​​“测试用例的源头”​​。

​​**代码实现(apb_sequence.sv)**​​

// 定义APB序列类,继承自uvm_sequence<apb_transaction>(专用于生成apb_transaction类型的事务)
class apb_sequence extends uvm_sequence #(apb_transaction);// ===== 构造函数:初始化序列(必须调用父类构造函数) =====// 参数name:序列名称(用于调试标识,可选,默认"apb_sequence")function new(string name="apb_sequence");super.new(name);  // 调用父类uvm_sequence的构造函数endfunction// ===== 核心方法:定义激励生成逻辑(UVM自动调用) =====// 作用:在仿真时,Sequencer会调用此任务的body()来生成一系列apb_transaction并发送给Drivertask body();// 示例1:生成10个随机APB事务(覆盖不同地址和读写操作)repeat(10) begin// 1. 创建一个新的APB事务对象(通过工厂创建,支持UVM的随机化和约束)apb_transaction txn = apb_transaction::type_id::create("txn");// 2. 随机化事务(根据类中定义的约束生成随机addr/data/we)if (!txn.randomize()) begin`uvm_error("RAND_FAIL", "APB事务随机化失败!")  // 随机化失败时报错end// 3. 打印生成的事务内容(调试用)`uvm_info("SEQ_GEN", $sformatf("生成事务: %s", txn.sprint()), UVM_LOW)txn.print_transaction();  // 调用事务的打印方法// 4. 将事务发送给Sequencer(通过UVM的put/get机制,Driver会从Sequencer获取)start_item(txn);          // 通知Sequencer准备接收事务finish_item(txn);         // 将事务传递给Sequencer(实际驱动Driver)end// 示例2(可选):生成一个特定的固定事务(例如地址0x0,写数据0xAA)// apb_transaction fixed_txn = apb_transaction::type_id::create("fixed_txn");// fixed_txn.addr = 4'h0;// fixed_txn.data = 8'hAA;// fixed_txn.we = 1;// if (!fixed_txn.randomize()) `uvm_error("RAND_FAIL", "固定事务随机化失败");// start_item(fixed_txn);// finish_item(fixed_txn);endtaskendclass

​​关键点总结​​:

•​​随机化激励​​:通过 txn.randomize()生成符合约束(如 addr_range)的随机事务,覆盖更多测试场景。

•​​UVM流程​​:start_item(txn)和 finish_item(txn)是UVM的标准方法,用于将事务传递给Sequencer(底层通过TLM通信)。

•​​调试信息​​:uvm_info和 print_transaction()帮助验证人员观察生成的激励是否符合预期。

​​3. Sequencer(序列发生器类)—— 协调事务的调度与传递​​

​​工作原理​​
Sequencer是UVM中 ​​管理Sequence和Driver之间事务传递的中间组件​​,负责从Sequence接收生成的事务(Transaction),并通过TLM端口(如 seq_item_port)将事务分发给Driver。

​​核心作用​​:作为 ​​“事务调度中心”​​,确保Driver能按顺序获取Sequence生成的激励,并支持多Sequence并发(通过分层序列)。

​​代码实现(apb_sequencer.sv)​​

// 定义APB Sequencer类,继承自uvm_sequencer<apb_transaction>(专用于处理apb_transaction类型)
class apb_sequencer extends uvm_sequencer #(apb_transaction);// ===== 构造函数:初始化Sequencer(必须调用父类构造函数) =====// 参数name:Sequencer名称(用于调试标识,可选,默认"apb_sequencer")// 参数parent:父组件(UVM层次化结构,通常为agent)function new(string name="apb_sequencer", uvm_component parent);super.new(name, parent);  // 调用父类uvm_sequencer的构造函数,初始化TLM端口和内部状态endfunctionendclass

​​关键点总结​​:

•​​TLM通信​​:Sequencer内部预定义了 seq_item_port(发送事务给Driver)和 seq_item_export(接收Sequence的事务),无需手动实现。

•​​泛型参数​​:uvm_sequencer #(apb_transaction)指定该Sequencer仅处理 apb_transaction类型的事务(类型安全)。

•​​层次化支持​​:通过构造函数的 parent参数,Sequencer可嵌入到Agent的层次结构中(例如 apb_agent包含 apb_sequencer)。

​​4. Driver(驱动类)—— 将事务转为DUT的时序信号​​

​​工作原理​​
Driver是UVM中 ​​**将Transaction(抽象激励)转换为DUT的实际输入信号(时序逻辑)**​​ 的组件。它通过Sequencer获取事务,并按照协议规范(如APB的时序)驱动DUT的引脚信号(如PADDR、PWDATA、PWRITE)。

​​核心作用​​:作为 ​​“协议转换器”​​,确保验证平台生成的激励能被DUT正确识别和处理。

​​代码实现(apb_driver.sv)​​

// 定义APB Driver类,继承自uvm_driver<apb_transaction>(专用于驱动apb_transaction类型)
class apb_driver extends uvm_driver #(apb_transaction);// ===== 虚接口:连接到DUT的APB信号(通过virtual interface传递) =====// 作用:封装DUT的物理引脚信号(如PCLK时钟、PADDR地址、PWDATA数据等)// virtual关键字表示这是一个指针,指向实际的APB接口实例(避免硬编码连接)virtual apb_interface vif;  // ===== 构造函数:初始化Driver(必须调用父类构造函数) =====// 参数name:Driver名称(用于调试标识,可选,默认"apb_driver")// 参数parent:父组件(通常为agent)function new(string name="apb_driver", uvm_component parent);super.new(name, parent);  // 调用父类uvm_driver的构造函数,初始化内部状态endfunction// ===== 核心方法:从Sequencer获取事务并驱动DUT时序 =====// 作用:UVM自动调用此任务,循环获取Transaction并转换为DUT的APB时序信号task run_phase(uvm_phase phase);// 1. 永久循环(持续等待并处理事务,直到仿真结束)forever begin// 2. 从Sequencer获取一个apb_transaction(阻塞等待,直到Sequence生成事务)apb_transaction txn;seq_item_port.get_next_item(txn);  // 阻塞调用,获取下一个事务// 3. 调用方法:将事务转为DUT的APB时序信号drive_apb_signal(txn);// 4. 通知Sequencer当前事务已完成(允许Sequence生成下一个事务)seq_item_port.item_done();endendtask// ===== 辅助方法:根据事务驱动APB时序(具体协议实现) =====// 作用:按照APB协议规范,将txn的addr/data/we转换为DUT的物理信号// 参数:txn 是当前处理的APB事务对象task drive_apb_signal(apb_transaction txn);// 1. 准备阶段:拉高片选(PSEL),设置地址和数据vif.psel <= 1'b1;           // 片选有效(告诉DUT:我要访问你)vif.paddr <= txn.addr;      // 设置要访问的地址(来自事务的addr)vif.pwdata <= txn.data;     // 设置要写入的数据(如果是写操作)vif.pwrite <= txn.we;       // 设置读写标志(1=写,0=读)// 2. 等待时钟上升沿(APB协议通常在时钟边沿采样信号)@(posedge vif.pclk);        // 等待DUT的时钟上升沿(确保信号稳定)// 3. 使能传输:拉高PENABLE(开始传输)vif.penable <= 1'b1;        // 传输使能(告诉DUT:现在开始操作)// 4. 再次等待时钟上升沿(确保DUT完成操作)@(posedge vif.pclk);// 5. 结束传输:拉低PENABLE和PSEL(释放总线)vif.penable <= 1'b0;        // 结束传输vif.psel <= 1'b0;           // 释放片选endtaskendclass

​​关键点总结​​:

•**​​虚接口(vif)**​​:通过 virtual apb_interface传递DUT的实际信号(如 paddr、pwdata),避免硬编码连接(提高代码可移植性)。

•​​TLM通信​​:seq_item_port.get_next_item(txn)从Sequencer获取事务(阻塞式,确保Driver按顺序处理)。

•​​协议实现​​:drive_apb_signal()方法封装了APB的时序逻辑(如PSEL→PADDR→PENABLE的时序步骤),确保DUT正确响应。

​​5. Monitor(监测类)—— 捕获DUT的输出并验证​​

​​工作原理​​
Monitor是UVM中 ​​监测DUT的输出信号(如读数据PRDATA)并将其转换为Transaction对象上报给Scoreboard/Checker​​ 的组件。它被动监听DUT的引脚信号,不主动驱动DUT。

​​核心作用​​:作为 ​​“观测者”​​,确保DUT的输出符合预期(例如读操作返回正确的数据)。

​​代码实现(apb_monitor.sv)​​

// 定义APB Monitor类,继承自uvm_monitor(UVM标准监控基类)
class apb_monitor extends uvm_monitor;// ===== 虚接口:连接到DUT的APB信号(用于监测输入输出) =====virtual apb_interface vif;  // ===== UVM分析端口:将捕获的Transaction上报给Scoreboard/Checker =====// 作用:通过此端口将生成的apb_transaction发送给其他组件(如Scoreboard)uvm_analysis_port #(apb_transaction) ap;  // ===== 构造函数:初始化Monitor(必须调用父类构造函数) =====function new(string name="apb_monitor", uvm_component parent);super.new(name, parent);  // 调用父类uvm_monitor的构造函数ap = new("ap", this);     // 创建分析端口(名称"ap",关联当前Monitor实例)endfunction// ===== 核心方法:监测DUT信号并生成Transaction(运行在run_phase) =====task run_phase(uvm_phase phase);// 1. 永久循环(持续监测DUT信号,直到仿真结束)forever begin// 2. 等待DUT的读操作(示例:监测PREADY和PRDATA信号,简化逻辑)// 注意:实际APB协议需监测PSEL、PENABLE、PREADY等信号组合@(posedge vif.pclk);    // 等待时钟上升沿// 3. 检测读操作(示例条件:PSEL高且PENABLE高且PWRITE=0表示读操作)if (vif.psel && vif.penable && !vif.pwrite) begin// 4. 创建一个新的APB事务对象(描述读操作)apb_transaction txn = apb_transaction::type_id::create("monitored_txn");// 5. 填充事务属性(从DUT信号获取地址和数据)txn.addr = vif.paddr;  // 读取的地址(来自DUT的PADDR信号)txn.data = vif.prdata; // 读取的数据(来自DUT的PRDATA信号)txn.we = 0;            // 读操作标志// 6. 打印监测到的事务(调试用)`uvm_info("MONITOR", $sformatf("监测到读事务: %s", txn.sprint()), UVM_LOW)txn.print_transaction();// 7. 通过分析端口上报事务(Scoreboard将接收并验证)ap.write(txn);endendendtaskendclass

​​关键点总结​​:

•​​被动监测​​:Monitor不主动驱动DUT,仅监听DUT的引脚信号(如 paddr、prdata)。

•​​**分析端口(ap)**​​:通过 uvm_analysis_port将监测到的Transaction发送给Scoreboard(或其他验证组件),实现数据比对。

•​​协议解析​​:根据APB信号(如 psel、penable、pwrite)判断当前是读操作还是写操作,并提取对应的地址/数据。

​​6. Agent(代理类)—— 整合Sequencer、Driver和Monitor​​

​​工作原理​​
Agent是UVM中 ​​封装Sequencer、Driver和Monitor的容器​​,用于管理一个DUT接口(如APB接口)的完整验证环境。它根据配置(如主动/被动模式)决定是否包含Driver(主动模式需要驱动DUT,被动模式仅监测)。

​​核心作用​​:作为 ​​“验证环境的模块化单元”​​,简化顶层环境的集成(例如一个芯片可能包含APB、I2C等多个Agent)。

​​代码实现(apb_agent.sv)​​

// 定义APB Agent类,继承自uvm_agent(UVM标准代理基类)
class apb_agent extends uvm_agent;// ===== 组件实例:Sequencer、Driver、Monitor =====apb_sequencer sqr;  // 序列发生器(生成激励)apb_driver drv;     // 驱动器(将激励转为DUT信号)apb_monitor mon;    // 监测器(捕获DUT输出)// ===== 构造函数:初始化Agent(必须调用父类构造函数) =====function new(string name="apb_agent", uvm_component parent);super.new(name, parent);  // 调用父类uvm_agent的构造函数endfunction// ===== 核心方法:构建Agent的组件(UVM的build_phase) =====// 作用:在仿真初始化阶段创建Sequencer、Driver和Monitor实例function void build_phase(uvm_phase phase);super.build_phase(phase);  // 调用父类build_phase(可选,但推荐)// 创建Sequencer(处理apb_transaction类型)sqr = apb_sequencer::type_id::create("sqr", this);// 创建Driver(驱动APB事务)drv = apb_driver::type_id::create("drv", this);// 创建Monitor(监测APB事务)mon = apb_monitor::type_id::create("mon", this);endfunction// ===== 核心方法:连接Agent的组件(UVM的connect_phase) =====// 作用:在组件创建后,建立Sequencer与Driver之间的TLM通信连接function void connect_phase(uvm_phase phase);super.connect_phase(phase);  // 调用父类connect_phase(可选)// 将Driver的seq_item_port连接到Sequencer的seq_item_export(事务传递通道)drv.seq_item_port.connect(sqr.seq_item_export);endfunctionendclass

​​关键点总结​​:

•​​层次化构建​​:在 build_phase中创建Sequencer、Driver和Monitor实例(通过 type_id::create方法,支持UVM工厂机制)。

•​​TLM连接​​:在 connect_phase中通过 drv.seq_item_port.connect(sqr.seq_item_export)建立Sequencer与Driver的通信通道(Driver从Sequencer获取事务)。

**•​​主动/被动模式​​:**当前Agent为 ​​主动模式​​(包含Driver,用于驱动DUT),若为被动模式(仅监测),可省略Driver实例。

​​完整VIP Agent的顶层集成(示例)​​
​​代码实现(apb_env.sv,可选扩展)​​

// 定义APB验证环境(集成Agent、Scoreboard等,此处仅展示Agent集成)
class apb_env extends uvm_env;apb_agent apb_agt;  // APB Agent实例(包含Sequencer/Driver/Monitor)function new(string name="apb_env", uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);// 创建APB Agent(主动模式,驱动并监测APB接口)apb_agt = apb_agent::type_id::create("apb_agt", this);endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);// 可在此处连接Scoreboard(例如:apb_agt.mon.ap.connect(scoreboard.ap_port))endfunctionendclass

​​总结:各组件协作流程​​
1.​​Transaction​​:描述APB激励(地址/数据/读写标志),通过随机化生成多样化测试场景。

2.​​Sequence​​:定义激励生成逻辑(如循环生成10个随机事务),通过 body()任务创建Transaction并交给Sequencer。

3.​​Sequencer​​:接收Sequence的事务,通过TLM端口(seq_item_port)分发给Driver。

4.​​Driver​​:从Sequencer获取Transaction,按照APB协议时序驱动DUT的物理信号(如PADDR、PWDATA)。

5.​​Monitor​​:被动监听DUT的输出信号(如PRDATA),转换为Transaction并通过分析端口上报给Scoreboard。

6.​​Agent​​:整合Sequencer、Driver和Monitor,形成完整的DUT接口验证环境。

通过以上组件的协作,UVM验证平台能够 ​​自动生成激励、驱动DUT、监测输出并验证功能正确性​​,是芯片验证的核心基础设施。

http://www.xdnf.cn/news/19468.html

相关文章:

  • 壁纸、logo、短视频去水印
  • 前端常见安全问题 + 防御方法 + 面试回答
  • Qt QML连接数据库如何解决重复创建连接问题
  • 大话 IOT 技术(3) -- MQTT篇
  • Qt中使用 GStreamer 播放视频文件
  • HikariCP vs DBCP2 vs Tomcat JDBC:多场景数据库连接池方案对比与实践指南
  • 局域网中使用Nginx部署https前端和后端
  • Qt中解析XML文件
  • word中插入字符后会自动删除后面的字符
  • Visual Studio Code中launch.json的解析笔记
  • Prometheus之启用--web.enable-remote-write-receiver
  • 对于一个多层感知机,参数初始化的时候不是已经把权重的范围根据方差进行优化过了,为什么还要进行正则化惩罚过大权重
  • springboot整合minio实现上传下载搭建minio
  • Unity转抖音小游戏重点摘记
  • 学生请假就餐系统
  • 计算机网络---http(超文本传输协议)
  • XPlayer播放器APP:安卓平台上的全能视频播放器
  • LeetCode每日一题,2025-8-31
  • TFS-2002《Analysis and Efficient Implementation of a Linguistic Fuzzy C-Means》
  • 【量化回测】backtracker整体架构和使用示例
  • Rsync 数据同步工具及实时同步配置
  • SAP PP中的MRP
  • 【OpenGL】LearnOpenGL学习笔记18 - Uniform缓冲对象UBO
  • 模型系列(篇三)-Llama
  • vscode克隆远程代码步骤
  • 合约服务架构-OOP 方式
  • leetcode 371 两个整数之和
  • 微软开源TTS模型VibeVoice,可生成 90 分钟4人语音
  • TFS-1996《The Possibilistic C-Means Algorithm: Insights and Recommendations》
  • 一些八股总结