文章目录

  • 前言
  • 一、验证结构
  • 二、各组件功能
    • 1.lvc_apb_master_agent
      • 1.1 driver功能
      • 1.2 monitor功能
      • 1.3 sequencer功能
    • 2.lvc_i2c_slave_agent
      • 2.1 driver功能
      • 2.2 monitor功能
      • 2.3 sequencer功能
    • 3. Scoreboard功能
    • 4. Predictor功能
    • 5. Virtual sequencer功能
  • 总结

前言

I2C项目验证结构以及各验证组件的功能描述,仅为学习目的。


一、验证结构

由lvc_apb_master_agent(配置为master模式),lvc_i2c_slave_agent(配置为slave模式),scoreboard和virtual sequencer,以及predictor等组件构成,如下图

二、各组件功能

1.lvc_apb_master_agent

包括driver, monitor, sequencer,在agent中完成了

  1. 在build_phase中对各组件包括driver, monitor, sequencer的例化配置(由于配置为master模式,所以含有driver和sequencer,monitor无论master/slave模式均有)
function void lvc_apb_master_agent::build();super.build();// get top config(agent work mode/apb bus signal(pready,pslverr))if( !uvm_config_db#(lvc_apb_config)::get(this,"","cfg", cfg)) begin`uvm_warning("GETCFG","cannot get config object from config DB")cfg = lvc_apb_config::type_id::create("cfg");end// get virtual interface(drive and monitor the signal of apb bus)if( !uvm_config_db#(virtual lvc_apb_if)::get(this,"","vif", vif)) begin`uvm_fatal("GETVIF","cannot get vif handle from config DB")endmonitor = lvc_apb_master_monitor::type_id::create("monitor",this);monitor.cfg = cfg;//judge the cfg modeif(cfg.is_active == UVM_ACTIVE) begin  sequencer = lvc_apb_master_sequencer::type_id::create("sequencer",this);sequencer.cfg = cfg;driver = lvc_apb_master_driver::type_id::create("driver",this);driver.cfg = cfg;end
endfunction : build
  1. 在connect_phase完成了虚接口的传递,以及driver的seq_item_port与sequencer的seq_item_export的端口连接(这两个端口是uvm专门定义的端口,无需例化)
function void lvc_apb_master_agent::connect();assign_vi(vif);if(is_active == UVM_ACTIVE) begindriver.seq_item_port.connect(sequencer.seq_item_export);       endendfunction : connect

1.1 driver功能

  1. get_and_drive(): 主体任务为drive_transfer(), 根据从sequencer侧获得的seq的trans_kind属性对apb总线执行响应的读写任务(do_write/do_read_do_idle);代码以do_write为例,do_read与之相似,只不过在setup周期pwrite信号拉低,从端需要在enable周期内返回prdata(传输无误)。
task lvc_apb_master_driver::do_write(lvc_apb_transfer t);`uvm_info(get_type_name(), "do_write ...", UVM_HIGH)@(vif.cb_mst);//apb总线setup状态,psel=1, penable=0,表示有传输要进行,只在此状态停留一个周期,写入addr和data, pwrite拉高vif.cb_mst.paddr <= t.addr;vif.cb_mst.pwrite <= 1;vif.cb_mst.psel <= 1;vif.cb_mst.penable <= 0;vif.cb_mst.pwdata <= t.data;@(vif.cb_mst);//apb总线enable状态,penable被置为1,pwrite/paddr/pdata/psel均保持有效,完成一次传输后地址信号和写信号捕获改变,直到下一次传输开始vif.cb_mst.penable <= 1;#10ps;//pready置为1结束此次transfer,此信号由slave产生,如果想延长响应时间可拉低此信号wait(vif.pready === 1);#1ps;//监测pslverr信号判断传输是否发送错误,当psel,penable,pready同时有效时可采集到此信号,为高表示传输错误,在apb transfer的最后一个周期有效if(vif.pslverr === 1) begint.trans_status = ERROR;if(cfg.master_pslverr_status_severity ==  UVM_ERROR)`uvm_error(get_type_name(), "PSLVERR asserted!")else`uvm_warning(get_type_name(), "PSLVERR asserted!")end//未监测到pslverr表明传输正常else begint.trans_status = OK;endrepeat(t.idle_cycles) this.do_idle();
endtask: do_write
  1. reset_listener(): 在复位信号有效时对apb总线执行复位操作。

1.2 monitor功能

1.collect_transfer(): 通过lvc_apb_if监测apb接口的地址线、数据线、控制线以及传输情况;

task lvc_apb_master_monitor::collect_transfer();// Advance clock//psel为高,penable为低,apb总线处于setup周期@(vif.cb_mon iff (vif.cb_mon.psel === 1'b1 && vif.cb_mon.penable === 1'b0));trans_collected = lvc_apb_transfer::type_id::create("trans_collected");case(vif.cb_mon.pwrite)1'b1    : begin//监测到写信号//监测到pready为高即写传输结束的前一周期,把地址、数据、指令和传输状态传入事务包中@(vif.cb_mon iff vif.cb_mon.pready === 1'b1);trans_collected.addr = vif.cb_mon.paddr;trans_collected.data = vif.cb_mon.pwdata;trans_collected.trans_kind = WRITE;trans_collected.trans_status = vif.cb_mon.pslverr === 1'b0 ? OK : ERROR;end 1'b0    : begin//监测到读信号@(vif.cb_mon iff vif.cb_mon.pready === 1'b1);trans_collected.addr = vif.cb_mon.paddr;trans_collected.data = vif.cb_mon.prdata;trans_collected.trans_kind = READ;trans_collected.trans_status = vif.cb_mon.pslverr === 1'b0 ? OK : ERROR;enddefault : `uvm_error(get_type_name(), "ERROR pwrite signal value")endcase
endtask: collect_transfer
  1. 根据check_enable/coverage_enable两个开关,通过analysis_port传递监测到的信号执行相应的功能。
 // This field controls if this monitor has its checkers enabled// (by default checkers are on)bit checks_enable = 1;// This field controls if this monitor has its coverage enabled// (by default coverage is on)bit coverage_enable = 1;
// perform_transfer_checks
function void lvc_apb_master_monitor::perform_transfer_checks();// USER: do some checks on the transfer hereendfunction : perform_transfer_checks// perform_transfer_coverage
function void lvc_apb_master_monitor::perform_transfer_coverage();// USER: coverage implementation-> lvc_apb_master_cov_transaction; endfunction : perform_transfer_coverage

1.3 sequencer功能

无特别任务。

2.lvc_i2c_slave_agent

  1. 在build_phase中将agent配置为passive模式(slave),并例化driver, monitor, sequencer组件;(由于对I2C配置是可以更改的(可以控制slave和master的数量),为了便于后续配置更改,i2c_slave_agent在build_phase中具有层次化的配置,代码看起来比apb复杂,此处省略不贴代码)
  2. 在connect_phase完成driver和sequencer的端口连接(代码与apb_master_agent相似,省略)
  3. run_phase中根据agent配置模式通过reconfigure_via_task完成对driver, sequencer的重新配置(monitor在slave/master模式下均有)

2.1 driver功能

  1. wait_for_reset():等待复位信号到来(该任务位于lvc_i2c_bfm_common中);
  2. consum_from_seq_item_port():在通过seq_item_port收到有效事务后,将事务按照协议驱动给i2c总线,并为此事务做标记后复制一份resp发回给sequencer(主体任务send_xact位于lvc_i2c_driver_common中)
    注:涉及代码太多,后续分析

2.2 monitor功能

包含两个analysis_port,xact_observed_port(当观测到完整事务,monitor通过write方法将信号放进port); data_observed_port(monitor一旦监测到数据就会通过port传递信息,而不会等整个事务都出现在总线上)

  1. wait_for_reset(): 等待复位信号到来(该任务位于lvc_i2c_bfm_common中);
  2. received_and_sent():按照i2c协议监测事务,并在数据不为空或监测未结束时,两个analysis_port持续执行write方法将信号写入端口

2.3 sequencer功能

无特别功能,需要检查特定设置下是否获得相应配置。

3. Scoreboard功能

包含两个analysis port的接收端口,分别来自apb_master和i2c_slave中的monitor,负责接收来自两边的观测数据,并通过访问寄存器模型获得读写指令,再依据apb写入寄存器模型中的数据模拟出refmod的期望数据,最后将其与i2c侧观测到的数据进行对比

  1. i2c_refmod(): 模拟DUV工作时使用APB接口配置控制寄存器,并模拟前门访问寄存器模型行为产生读/写命令下的数据期望值(模拟apb总线产生的数据对寄存器配置后模块输出的数据);
task i2c_refmod();lvc_apb_transfer tr;ral_reg_rkv_i2c_IC_DATA_CMD data_cmd_r;bit[7:0] data;data_cmd_r = new("data_cmd_r");data_cmd_r.build();//创建一个控制寄存器forever beginwait(apb_trans_observed.size() > 0) tr = apb_trans_observed.pop_front();//一旦通过analysis port观测到apb总线事务,就从队列前面取出从apb总线观测到的事务元素存入tr中data_cmd_r.set(tr.data);//通过前门访问,将控制寄存器的期望值修改为tr.data;if(tr.trans_kind == lvc_apb_pkg::WRITE && cfg.rgm.IC_DATA_CMD_CMD.get() == RGM_WRITE) begin//如果观测到的事务和通过前门访问获得的寄存器模型期望值都是写命令,把寄存器中的数据以push_back的方式放入期望值写数据的队列中,并计数加一write_data_expected.push_back(data_cmd_r.DAT.get());write_count_expected++;end//如果观测到的事务和通过前门访问获得的寄存器模型期望值都是读命令,把寄存器中的数据以push_back的方式放入期望值读数据的队列中,并计数加一else if(tr.trans_kind == lvc_apb_pkg::READ && cfg.rgm.IC_DATA_CMD_CMD.get() == RGM_READ) beginread_data_expected.push_back(data_cmd_r.DAT.get());read_count_expected++;endendendtask
  1. i2c_write_compare():写数据的对比,把实际观测到的值和refmod产生的期望值进行对比,统计错误次数;
 task i2c_write_comparer();bit[7:0] exp, obs;//两个数组分别存放写命令下的期望值和实际观测值forever beginforkwait(write_data_expected.size() > 0) exp = write_data_expected.pop_front();wait(write_data_observed.size() > 0) obs = write_data_observed.pop_front();joincompare_transaction(exp, obs);//对比期望值和观测值endendtask
function void compare_transaction(bit[7:0] exp, bit[7:0] obs);bit mismatch_detected = 0 ;//默认检测结果匹配if(exp != obs) begin//如果期望值和观测值不同,把错误标记置1`uvm_error(get_type_name(), $sformatf("Byte transferred different in expected value is %h and slave observed value is %h", exp, obs))mismatch_detected = 1;end// check for no mismatchif(!mismatch_detected)//错误标记为低,打印正确信息,否则错误计数加1`uvm_info(get_type_name(), $sformatf("Trans match between expected %h and observed %h", exp, obs), UVM_LOW)elsemismatch_count++;endfunction: compare_transaction
  1. i2c_read_compare():读数据的对比,把在i2c侧实际观测到的值和refmod产生的期望值进行对比,统计错误次数;
 task i2c_read_comparer();bit[7:0] exp, obs;//两个数组分别存放读命令下的期望值和实际观测值forever beginforkwait(read_data_expected.size() > 0) exp = read_data_expected.pop_front();wait(read_data_observed.size() > 0) obs = read_data_observed.pop_front();joincompare_transaction(exp, obs);//此任务代码在上面已贴endendtask
  1. i2c_mon_interrupt():监测中断,监测到RX FIOFO溢出中断、TXFIFO为空中断以及TX发送数据异常中断,就插入中断并关闭scoreboard数据比对功能。
task i2c_mon_interrupt();forever begin// wait any interrupt assertedcfg.vif.wait_intr();if(   cfg.vif.get_intr(IC_RX_OVER_INTR_ID) || cfg.vif.get_intr(IC_TX_ABRT_INTR_ID)|| cfg.vif.get_intr(IC_TX_EMPTY_INTR_ID)) begininterrupt_abort = 1;enable = 0;`uvm_info(get_type_name(), "monitored aborted/exceptional interrupt asserted, and disable scoreboard.", UVM_LOW)endendendtask//读写观测值来源于analysis port的write任务,对应于i2c agent中的monitor,期望值则来源于analysis port的write任务产生的apb_trans_observed(此队列用于配置refmod中的控制寄存器,进而产生期望读写值),对应于apb agent中monitor。

4. Predictor功能

更新寄存器模型有两种途径,一种是自动预测途径,当driver将读取值返回后,寄存器模型会更新寄存器的镜像值和期望值;
另一种是经由predictor的途径,monitor从apb总线上收集到的transaction交给寄存器模型,再由寄存器模型更新相应寄存器的值,这种方式则需要实例化一个reg_predictor并为这个reg_predictor例化一个adapter。

a. 使用predictor时,需要为其设置adapter及map变量,只有设置了map后,才能将predictor和寄存器模型关联在一起; uvm_predictor使用adapter将monitor传递来的bus transaction转换成uvm_reg_item, 然后使用map根据uvm_reg_item中的address信息找到对应的register,并更新其镜像值和期望值
build_phase中:

    adapter = lvc_apb_reg_adapter::type_id::create("adapter", this);predictor = uvm_reg_predictor#(lvc_apb_transfer)::type_id::create("predictor", this);

connect_phase中:

    apb_mst.monitor.item_collected_port.connect(predictor.bus_in);predictor.map = rgm.default_map;predictor.adapter = adapter;

5. Virtual sequencer功能

实现对apb_mst_sqr, i2c_slave_sqr的挂载,最终实现各类seq在test中的启动。
run_phase中

seq.start(env.sqr);

总结

本文主要结合代码介绍了i2c验证环境中的各类组件功能,有不同见解的地方可以交流讨论喔。

I2C虚拟项目验证结构相关推荐

  1. I2C虚拟项目笔记(一)-virtual sequence

    文章目录 项目结构 准备工作 一.user_sequence部分 1. rkv_i2c_master_abrt_10b_rd_norstrt_virt_seq 2. rkv_i2c_master_ab ...

  2. I2C虚拟项目-test3

    持续更新测试用例解读. 文章目录 前言 1. rkv_i2c_master_sda_control_cg_test 2. rkv_i2c_master_timeout_cg_test 总结 前言 一个 ...

  3. 【IC萌新虚拟项目】ppu整体uvm验证环境搭建

    关于整个虚拟项目,请参考: [HISI IC萌新虚拟项目]Package Process Unit项目全流程目录_尼德兰的喵的博客-CSDN博客 前言 本篇文章完成ppu整体uvm环境搭建的指导,在进 ...

  4. 【IC萌新虚拟项目】ppu模块的编译环境搭建与RTL编译

    关于整个虚拟项目,请参考: [HISI IC萌新虚拟项目]Package Process Unit项目全流程目录_尼德兰的喵的博客-CSDN博客 前言 虚拟机为芯王国公众号提供的虚拟机,虚拟机内置vc ...

  5. Angular4.x 安装|创建项目|目录结构|创建组件

    Angular4.x 安装|创建项目|目录结构|创建组件 安装最新版本的 nodejs node.js 官网:https://nodejs.org/zh-cn/ 去官网下载 node.js,下一步下一 ...

  6. 拳王虚拟项目公社:虚拟资源平台的虚拟产品大全整理副业系列

    我个人觉得在不久的未来,通过虚拟产品赚钱会越来越细分,个人IP的要求会越来越高. 因为做网络营销的都清楚,免费赠送是互联网上最强大的手段,而虚拟产品可以说是零成本的,所以一般来说通过赠送虚拟产品吸粉成 ...

  7. php网站目录结构图,thinkphp项目目录结构详解

    在上一节无忧主机(www.51php.com)小编和大家讲了thinphp 3.0的主入口文件,不知大家是否还记得我们第一次执行主入口文件后,我们的项目目录下自动生成了很多文件夹,这个就是我们项目的结 ...

  8. 【IC萌新虚拟项目】ppu模块基于spyglass的lint清理环境搭建与lint清理

    关于整个虚拟项目,请参考: [HISI IC萌新虚拟项目]Package Process Unit项目全流程目录_尼德兰的喵的博客-CSDN博客 前言 RTL代码在交付给验证同时进行功能验证时,可以同 ...

  9. 最全的 eclipse web 项目目录结构

    本文会尽可能对 java web 项目的目录结构做出最详细的解释,尽量做到浅显易懂. eclipse web 项目目录结构 java web 项目事例 03-springmvc-drien-xgq 是 ...

最新文章

  1. 多线程总结五:线程通信(一)
  2. VS生成时复制文件到指定目录
  3. PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数详解
  4. python2中使用中文报错:SyntaxError: Non-ASCII character
  5. bzoj1207(HNOI2004)打鼹鼠
  6. vue-自主研发非父子关系组件之间通信的问题
  7. js_DOM读写节点
  8. PYTHON 100days学习笔记001:初识python
  9. python调用数据库存储过程_python调用MySql存储过程
  10. HD2做Windows Phone 7开发机小记(上)
  11. 2022年全新UI聚合支付系统四方源码更新完美版
  12. 2018年海峡两岸光电展将在台北举办
  13. 个人网页制作(教你制作简单网页)
  14. 3D打印机DIY之五------切片软件Cura的使用
  15. 搞一下 车载以太网实战 | 01 车载以太网帧结构详解
  16. 偏偏在面试的时候踏入一个大坑--360浏览器兼容模式
  17. 版权和商标权有什么关系?版权和商标的区别在哪里?
  18. Python---None
  19. Linux mysql服务(重启,启动,停止)
  20. Ubuntu 16.04 LTS + CUDA 8.0 + GTX960M

热门文章

  1. ORACLE面试题整理(一)
  2. 企业电脑屏幕监控:为何需要及如何选择适合的工具
  3. 多普达A6388刷机2.3
  4. Ubuntu安装驱动
  5. 《Secrets》 秘密 中英互译——【one republic英文经典歌曲】
  6. html中dl块自适应高度,CSS高度自适应代码(用了都说好)
  7. CVPR2018总结
  8. 2022全年度空调十大热门品牌销量榜单
  9. html5设计礼品盒效果,十大包装创意设计网站
  10. word文字上下颠倒_您如何制作上下颠倒的文字?