UVM学习——构建一个简单的UVM验证平台

构建一个简单的UVM验证平台

本次构建的验证平台不包含DUT。

创建transaction和sequence

transaction代码如下:

class my_transaction extends uvm_sequence_item;

    rand bit [4:0] sa;
    rand bit [3:0] da;
    rand reg [7:0] payload[$];  //定义数据成员

    `uvm_object_utils_begin(my_transaction)
        `uvm_field_int(sa, UVM_ALL_ON);
        `uvm_field_int(da, UVM_ALL_ON);
        `uvm_field_queue_int(payload, UVM_ALL_ON);
    `uvm_object_utils_end
	// 约束
    constraint Limit{
        sa inside { [0:15] };
        da inside { [0:15] };
        payload.size() inside { [2:4] };
    } 

    function new(string name = "my_transaction");
        super.new(name);
    endfunction

endclass

sequence代码如下:

class my_sequence extends uvm_sequence #(my_transaction);

    `uvm_object_utils(my_sequence)

    function new(string name = "my_sequence");
        super.new(name);
    endfunction

    virtual task body();
        
        if(starting_phase != null)
            starting_phase.raise_objection(this);

        repeat(10) begin
            `uvm_do(req);
        end
	   
           #100;
    	  if(starting_phase != null)
            starting_phase.drop_objection(this);
    endtask

endclass

创建sequencer和driver

sequencer的代码如下:

typedef uvm_sequencer #(my_transaction) my_sequencer;

driver的代码如下:

class my_driver extends uvm_driver #(my_transaction);

    `uvm_component_utils(my_driver)

    function new(string name = "my_driver", uvm_component parent);
        super.new(name, parent);
    endfunction

    virtual task run_phase(uvm_phase phase);
        forever begin
            seq_item_port.get_next_item(req);
            `uvm_info("DRV_RUN_PHASE", req.sprint(), UVM_MEDIUM)
            #100;
            seq_item_port.item_done();
        end
    endtask

endclass

seq_item_port为uvm_driver类内建的接口,用于与sequencer的TLM通信,即把transaction传输到driver。

创建monitor

class my_monitor extends uvm_monitor;

    `uvm_component_utils(my_monitor);

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
    endfunction

    virtual task run_phase(uvm_phase phase);
        forever begin
            `uvm_info("MON_RUN_PHASE", "Monitor run!", UVM_MEDIUM);
            #100;
        end
    endtask

endclass

创建agent

class master_agent extends uvm_agent;

    `uvm_component_utils(master_agent)

    my_sequencer m_seqr;
    my_driver m_driv;
    my_monitor m_moni;

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if(is_active == UVM_ACTIVE) begin
            m_seqr = my_sequencer::type_id::create("m_seqr", this);
            m_driv = my_driver::type_id::create("m_driv", this);
        end
        m_moni = my_monitor::type_id::create("m_moni", this);
    endfunction

    virtual function void connect_phase(uvm_phase phase);
        if(is_active == UVM_ACTIVE)
            m_driv.seq_item_port.connect(m_seqr.seq_item_export);
    endfunction

endclass

m_driv.seq_item_port.connect(m_seqr.seq_item_export);
实现driver和sequencer通信端口的连接。

创建envirenment和testcase

创建envirenment:

class my_env extends uvm_env;

    `uvm_component_utils(my_env)

    master_agent m_agent;

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        
        super.build_phase(phase);
        m_agent = master_agent::type_id::create("m_agent", this);

    endfunction

endclass

m_agent = master_agent::type_id::create(“m_agent”, this);
通过uvm的factory机制实例化对象。

testcase代码如下:

class my_test extends uvm_test;

    `uvm_component_utils(my_test)

    my_env m_env;

    function new(string name = "", uvm_component parent);
        super.new(name, parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        m_env = my_env::type_id::create("m_env", this);

        uvm_config_db#(uvm_object_wrapper)::set(
                        this, "*.m_seqr.run_phase",
                        "default_sequence", my_sequence::get_type());
    endfunction

    virtual function void start_of_simulation_phase(uvm_phase phase);
        super.start_of_simulation_phase(phase);
        uvm_top.print_topology(uvm_default_tree_printer);
    endfunction

endclass

顶层

program automatic test;
    import uvm_pkg::*;
    `include "uvm_macros.svh"
    `include "my_transaction.sv"
    `include "my_sequence.sv"
    `include "my_sequencer.sv"
    `include "my_driver.sv"
    `include "my_monitor.sv"
    `include "master_agent.sv"
    `include "my_env.sv"
    `include "my_test.sv"

    initial begin
        run_test("my_test");
    end

endprogram

仿真

Makefile如下:

SEED = 1

default: test

test: compile run

run:
	./simv -l simv.log +ntb_ramdom_seed=$(SEED)

compile:
	vcs -l vcs.log -sverilog -debug_all -full64 -ntb_opts uvm-1.1 -timescale=1ns/100ps test.sv

clean:
	rm -rf simv* csrc* *.tmp *.vpd *.key *.log *hdrs.h

来到仿真目录下,输入make开始编译及仿真,可以看到打印出的测试测试平台hierarchy如下:
在这里插入图片描述


版权声明:本文为weixin_45704530原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。