UVM学习之路(5)— 完整的UVM验证平台

UVM学习之路(5)— 完整的UVM验证平台

一、前言

一个完整的UVM验证平台还应该加入寄存器模型,对应的设计文件中也应该存在寄存器及其控制端口, 通过该控制端口可以配置DUT中的寄存器。

二、设计模块

设计文件添加寄存器模块后信号列表如下所示:
在这里插入图片描述
寄存器列表如下所示在这里插入图片描述

三、验证环境

基于UVM搭建的验证环境如下所示
在这里插入图片描述
其中sequence组织方式如下所示
在这里插入图片描述

四、基本任务

寄存器模型提供了两个基本的readwrite任务, 来设置寄存器模型和dut中寄存器的值,如下所示:

/*case0.sv*/
	    virtual task body();
        uvm_status_e status;
        uvm_reg_data_t value;

        if(starting_phase != null)
            starting_phase.raise_objection(this);
        
        #1000;
        // set value of registers via uvm_reg::write()
        p_sequencer.p_rm.invert.write(status, {15'h00, 1'b1});
        p_sequencer.p_rm.counter.write(status, 32'h2000ff);

        // read out the value form register
        p_sequencer.p_rm.invert.read(status, value);
        `uvm_info("case0_cfg_vseq", $sformatf("after write, invert's value is %0h", value), UVM_LOW)
        p_sequencer.p_rm.counter.read(status, value);
        `uvm_info("case0_cfg_vseq", $sformatf("after write, counter's value is %0h", value), UVM_LOW)
    
        #5000;
        if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask

然后我们可以通过打印信息以及波形看到, invert的值写入成功了,而counter的值没有设置为32'h2000ff,这实际上是正确的,因为counter为写1清零寄存器。
在这里插入图片描述在这里插入图片描述

五、后门访问

UVM提供两类后门访问的函数:

  • UVM_BACKDOOR形式的read和write;
  • peek和poke函数。

这两类函数的区别是, 第一类会在进行操作时模仿DUT的行为, 第二类则完全不管DUT的行为。
如对一个只读的寄存器进行写操作, 那么第一类由于要模拟DUT的只读行为, 所以是写不进去的, 但是使用第二类可以写进去。编写代码如下所示:

/*case1.sv*/
	virtual task body();
        uvm_status_e status;
        uvm_reg_data_t value;

        if(starting_phase != null)
            starting_phase.raise_objection(this);
        
        #1000;

        // set value of registers via uvm_reg::poke() for UVM_BACKDOOR
        p_sequencer.p_rm.invert.poke(status, {15'h00, 1'b0});
        p_sequencer.p_rm.counter.poke(status, {15'h00, 32'h2000f0});
        // read out the value form register
        p_sequencer.p_rm.invert.peek(status, value);
        `uvm_info("case1_cfg_vseq", $sformatf("after poke, invert's value is %0h", value), UVM_LOW)
        p_sequencer.p_rm.counter.peek(status, value);
        `uvm_info("case1_cfg_vseq", $sformatf("after poke, counter's value is %0h", value), UVM_LOW)

        // set value of registers via uvm_reg::write() for UVM_BACKDOOR
        p_sequencer.p_rm.invert.write(status, {15'h00, 1'b1}, UVM_BACKDOOR);
        p_sequencer.p_rm.counter.write(status, 32'h2000f0, UVM_BACKDOOR);
        // read out the value form register
        p_sequencer.p_rm.invert.read(status, value);
        `uvm_info("case1_cfg_vseq", $sformatf("after UVM_BACKDOOR write, invert's value is %0h", value), UVM_LOW)
        p_sequencer.p_rm.counter.read(status, value);
        `uvm_info("case1_cfg_vseq", $sformatf("after UVM_BACKDOOR write, counter's value is %0h", value), UVM_LOW)

        #5000;
        if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask

然后我们可以通过打印信息以及波形看到, 通过poke,invertcounter的值都被直接改变了,而通过write的UVM_BACKDOOR访问,invert的值写入成功了,而counter的值被写1清零了。
在这里插入图片描述
在这里插入图片描述

六、期望值与镜像值

镜像值(mirrored value): 寄存器模型中都会有一个专门的变量用于最大可能地与DUT保持同步, 这个变量在寄存器模型中称为DUT的镜像值;
期望值(desired value): 当希望向某个寄存器中写入一个值时,例如'h1,我们就可以通过set函数将期望值设置为’h1( 此时镜像值依然为0), 之后调用update任务, update任务会检查期望值和镜像值是否一致, 如果不一致, 那么将会把期望值写入DUT中, 并且更新镜像值。

另外,在调用write任务时, 期望值与镜像值都会更新。
编写代码如下所示:

/*case2.sv*/
	virtual task body();
        uvm_status_e status;
        uvm_reg_data_t value;

		if(starting_phase != null)
			starting_phase.raise_objection(this);
        
        #1000;

        p_sequencer.p_rm.invert.set(16'h1);
        value = p_sequencer.p_rm.invert.get();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's desired value is %0h", value), UVM_LOW)
        
        value = p_sequencer.p_rm.invert.get_mirrored_value();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's mirrored value is %0h", value), UVM_LOW)
        
        p_sequencer.p_rm.invert.update(status, UVM_FRONTDOOR);
        value = p_sequencer.p_rm.invert.get();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's desired value is %0h", value), UVM_LOW)

        value = p_sequencer.p_rm.invert.get_mirrored_value();
        `uvm_info("case2_cfg_vseq", $sformatf("invert's mirrored value is %0h", value), UVM_LOW)
        p_sequencer.p_rm.invert.read(status, value);
        `uvm_info("case2_cfg_vseq", $sformatf("invert's actual value is %0h", value), UVM_LOW)
		
        #5000;
		if(starting_phase != null)
			starting_phase.drop_objection(this);
	endtask

打印信息如下所示
在这里插入图片描述

七、附录

本篇中的UVM验证平台源码:https://gitee.com/william_william/uvm-s07.git

  • 7
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值