mcdf项目验证总结-UVM

本文详细介绍了MCDF项目的UVM验证平台搭建,包括chnl_pkg、arb_pkg、fmt_pkg、reg_pkg和mcdf_pkg的内容。重点讨论了UVM配置数据库的使用、参考模型、得分板和寄存器模型的实现。各组件如driver、sequencer、monitor的实现细节被逐一阐述,展示了如何在不同验证阶段进行组件例化和连接。

1.顶层验证环境

在这里插入图片描述

2.通信机制

在这里插入图片描述在这里插入图片描述在这里插入图片描述

3.UVM验证平台搭建

重点:通过uvm_config_db的set和get方法完成各个接口从TB(硬件一侧)到验证环境mcdf_env一侧的传递,TB:set, mcdf:get 激励是怎么产生的
reference model 是怎么实现的
scoreboard是怎么实现的
寄存器模型是怎么实现的
在定义sequence item 时,应当伴随域的自动化声明,利用uvm_object_utils_begin()uvm_object_utils_end完成
在不同的phase阶段完成组件的例化和连接
MCDF的UVM验证平台主要有chnl_pkg/arb_pkg/fmt_pkg/reg_pkg/mcdf_pkg

3.1 chnl_pkg的内容

包括chnl_trans - chnl_driver - chnl_sequencer- chnl_sequence - chnl_monitor - chnl_agent,还有一个数据打包的结构体,里面是32位的数据和2位的ID

  • 1)定义chnl_trans类继承于uvm_sequence_item类。定义随机的变量,主要有data,ch_id,pkt_id,data_nidles,pkt_nidles,并对其进行constraint,soft为随机变量指定默认值和分布,然后域的自动化的声明(克隆、打印、比较),构建函数function(new)
  • 2定义chnl_driver类,vif,注册,构建函数,然后set_interface函数,判断接口是否传递,run_phase里边两个函数,do_reset复位(valid和data)和do_drive (进行sequencer和deriver之间数据的传递)
task do_drive();
	chnl_trans req, rsp;
	@(posedge intf.rstn);
	forever begin
		seq_item_port.get_next_item(req);
		this.chnl_write(req);
		void'($cast(rsp,req.clone()));
		rsp.rsp = 1;
		rsp.set_sequence_id(req.get_sequence_id());
		seq_item_port.item_done(rsp);
	end
endtask

chnl_write函数:当时钟到来时,把数据写进去,如果ready
为1,数据已经写进去了,加入data_nidles,这个数据发送完毕,加入pkt_nidles

  • 3)定义chnl_sequencer继承于uvm_sequencer,注册,构建函数
  • 4)定义chnl_data_sequence继承于uvm_sequence,定义数据的值,有10个trans,域的自动化,运用了uvm_declare_p_sequencer,构建函数,用task body()任务来发送数据:采用uvm_do_with,之后pkt_id++,然后get_response返回rsp,再用断言检查assert(rsp.rsp),可能随机化之前会调用post_randomize
  • 5)定义chnl_monitor:vif,还有TLM通信端口uvm_blocking_put_port,注册,构建函数(创建对象mon_bp_port),set_interface将接口传递进来,在run_phase里边将监测数据,当chnl的valid和ready都为1的时候,把chnl的数据传给monitor
  • 6)定义chnl_agent,vif,把driver,monitor,sequencer放进来,注册,构建函数,build_phase里边config_db::set接口,创建三个对象,在connect_phase里边连接driver.seq_item_port.connect(sequencer.seq_item_export)

3.2 arb_pkg的内容

包括arb_trans-arb_driver-arb_sequencer-arb_monitor-arb_agent
仲裁器的算法实现:就是创建和例化这些类

  • 1)arb_trans:继承于uvm_sequence_item,注册,构建函数
  • 2)arb_driver:继承于uvm_driver,注册,构建函数
  • 3)arb_sequencer:继承uvm_sequencer,注册,构建函数
  • 4)arb_monitor:继承uvm_monitor,注册,构建函数
  • 5)arb_agent:继承uvm_agent,注册,构建函数

3.3 fmt_pkg的内容(重点是driver和monitor)

包括:fmt_trans-fmt_driver-fmt_sequencer-fmt_config_sequence-fmt_monitor-fmt_agent,定义两个枚举类型,fmt_fifo_tfmt_bandwidth_t
-1) fmt_trans:定义各个参数,constraint soft,域的自动化,构建函数

  • 2)fmt_driver: vif,信箱,构建函数,创建函数fifo,对象,设置fifo_bound ,data_consum_peroid的值,build_phase,中get 接口,在run_phase中有四个函数:
    do_receive:当req为1时,判断FIFO深度是否够用,然后让grant信号拉高,然后开始传递数据
    do_consume:调用fifo.try_get拿数据,然后重复数据消耗周期
    do_config:设置fmt_trans:req和rsp,首先get_next_item(req),然后设置FIFO的深度和位宽,void将req的类型转换为rsp,令rsp=1,设置sequence_id,调用item_done
    do_reset:就是复位的时候,让fmt_grant=0
  • 3)fmt_sequencer:注册,构建函数
  • 4)fmt_config_sequence:定义FIFO的深度和宽度,约束,域的自动化,uvm_declare_p_sequence(fmt_sequencer)声明sequencer类型的成员变量。构建函数,通过task body发送trans:定义fmt_trans req, rsp;uvm_do_with,get_response(rsp),然后assert(rsp.rsp),最后调用post_randomize 4
  • 5)fmt_monitor:定义string,vif,uvm_blocking_put_port,注册,构建函数,build_phase里边::get接口,run_phase里边进行数据的检测,mon_trans函数:定义一个fmt_trans m 对象,new例化,然后把接口上的数据赋值给m,并通过mon_bp_port.put(m),再打印
  • 6) fmt_agent:声明driver,monitor,sequencer,vif,注册,构建函数,build_phase里边type_id::create对象,config_db#()::get接口,connect_phase里边连接driver.seq_item_port.connect(sequencer.seq_item_export)

3.4 reg_pkg的内容

reg_trans/reg_driver/reg_sequencer/reg_base_sequence/idle_reg_sequence/write_reg_sequence/read_reg_sequence/reg_monitor/reg_agent

  • 1.reg_trans:addr,cmd,data,约束,域的自动化,构建函数
  • 2.reg_driver:vif,注册,构建函数,build_phase,get接口,run_phase里边有do_reset和do_drive(get_next_item和item_done)里边有个reg_write函数,有write/read/idle把对象的数据写到接口上边
  • 3.reg_sequencer:继承于uvm_sequencer,注册,构建函数
  • 4.reg_base_sequence:设置参数addr,cmd,data,约束,域的自动化,构建函数,task body()里边发送数据,有个send trans函数uvm_do_with,get_response,数据赋值,断言检查,最后还有个post_randomize
  • 5.idle_reg_sequence:约束,注册,构建函数
  • 6.write_reg_sequence:约束,注册,构建函数
  • 7.read_reg_sequence:约束,注册,构建函数
  • 8.reg_monitor:vif,以及进行TLM通信的uvm_blocking_put_port和analysis_port的对象,注册,构建函数,build_phase中::get if,run_phase中,将接口的数据传到寄存器,地址和指令传过去,如果是写的话,传递写的数据,如果是读的话,就是读数据
  • 9.reg_agent:声明driver,monitor,sequencer,vif,注册,构建函数,build_phase里边type_id::create对象,config_db#()::get接口,connect_phase里边连接driver.seq_item_port.connect(sequencer.seq_item_export)

3.5 mcdf_rgm_pkg

首先需要 import reg_pkg 然后包ctrl_reg/start_reg/mcdf_rgm/reg2mcdf_adapter等几个类

  • 1.ctrl_reg:(读写寄存器)注册,声明各个寄存器域,设置覆盖组,构建函数(里面设置覆盖率),在build函数里边创建对象,并设置各个域的参数,在sample函数里边进行采样
  • 2.start_reg:(只读寄存器),注册,声明保留域,定义覆盖组,在build函数里边例化对象,uvm_reg.configure设置各个域的属性,在sample函数里边做采样
  • 3.mcdf_rgm:继承于uvm_reg_block,声明6个chnl的ctrl_reg和start_reg以及uvm_reg_map,在build函数里边例化对象,并设置各个寄存器的参数,通过add_hdl_path将寄存器模型关联到DUT一端,add_hdl_path_slice完成寄存器模型各个寄存器成员与HDL一侧的地址映射,最后通过lock_model结束地址映射关系,并保证模型不会被其它用户所修改
  • 4.reg2mcdf_adapter:继承于uvm_reg_adapter,注册,构建函数,实现reg2busbus2reg两个函数

3.6 Mcdf_pkg的内容(refmodel和scoreboard都在这个里边)

首先把chnl_pkg,reg_pkg,arb_pkg,fmt_pkg,mcdf_rgm_pkg几个包import进去,然后定义了packed的结构体,按照len,prio,en,avail等进行,并根据寄存器的设置定义枚举类型

  • mcdf_refmod:首先定义vif,声明TLM端口,寄存器和monitor的端口,reg_bg_port和in_bgpk_ports,还有三个TLM FIFO,注册函数(例化对象)
    1.Run_phase里边完成复位,寄存器的更新还有打包,do_reset,do_reg_update,do_packet(0),do_packet(1),do_packet(2),do_reg_update是通过reg_bg_port.get端口获得寄存器的值,并且分为读写模式
    2.Do_packet,打包,定义两个对象fmt_trans ot和mon_data_t it,通过in_bgpk_ports[id].peek(it)端口将it 的数据赋给ot,再通过out_tlm_fifos[id].put把ot的数据传出去,其中有个函数 get_field_value获得寄存器域的值

  • mcdf_checker:即是scoreboard,首先声明err_count,total_count,chnl_count[3]等变量,还有chnl_vif,arb_vif,mcdf_vif以及refmod,通过TLM端口monitor、fmt和reg的数据和checker连接起来,还有信箱chnl_mbs[3],fmt_mb,reg_mb
    1.注册,构建函数(例化对象),在build_phase里边例化信箱还有创建对象,可以通过config_db进行get接口
    2.在connect_phase里边将这些端口进行连接,主要是将chnl和reg的和mcdf的连接
    3.在run_phase里边检查,do_channel_disable_check,do_arbiter_priority_check和do_data_compare,以及refmod.run
    4.其中do_data_compare是将fmt_trans类型的expt和mont进行对比,运用TLM通信获得数据,然后调用compare函数进行比较
    5.do_channel_disable_check:当复位信号为1,使能为0时,若valid,ready为1则检查错误
    6.do_arbiter_priority_check:如果arbiter接收到req信号为1且chnl的某个端口的有较高的优先级,但是不被arbiter所允许,即为错误
    7.在report_phase里边报告结果,打印消息,后边还有很多task,通过TLM通信peek,或get数据

  • mcdf_coverage:定义chnl/arb/mcdf/reg/fmt的vif,以及delay_req_to_grant变量,注册,定义几个covergroup:cg_mcdf_reg_write_read,cg_mcdf_reg_illegal_access,cg_channel_disable,cg_arbiter_priority,cg_formatter_length,cg_formatter_grant,定义很多bins,并通过cross定义交叉的部分,binsof指定覆盖点
    1.构建函数,例化覆盖组,在run_phase里边做采样do_reg_sample,do_channel_sample,do_arbiter_sample,do_formater_sample
    2.在report_phase里边打印消息
    3.在set_interface里边get接口

  • mcdf_virtual_sequencer:声明reg_sequencer,fmt_sequencer, chnl_sequencer,mcdf_rgm,注册,构建函数,set_interface

  • mcdf_env:声明chnl_agent,reg_agent,fmt_agent,mcdf_checker,mcdf_coverage,mcdf_virtual_sequencer,mcdf_rgm,reg2mcdf_adapter,uvm_reg_predictor注册,构建函数,在build_phase里边创建对象(type_id::create),在connect_phase里边进行TLM端口的连接以及寄存器模型的配置

	  rgm.map.set_seque
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值