1. 搭建UVM验证环境基础框架

搭建UVM验证环境基础框架 学习卡片

任务说明

本案例目标为搭建一个最小化UVM验证环境基础框架,包含uvm_test、uvm_env、uvm_agent、uvm_driver、uvm_sequencer、uvm_monitor和uvm_scoreboard七个核心组件,并通过一个冒烟测试验证框架可正确编译与运行。该框架不针对特定DUT协议,仅验证UVM组件层次结构与phase机制工作正常。

环境依赖

  • 支持UVM-1.2或IEEE 1800.2的仿真器(如VCS、Questa、Xcelium)
  • UVM库已正确安装并可通过+incdir+<uvm_home>/src引用

完整实现代码

// file: uvm_base_framework.sv
`include "uvm_macros.svh"
import uvm_pkg::*;

// 1. Transaction
class simple_trans extends uvm_sequence_item;
    rand bit [7:0] data;
    `uvm_object_utils_begin(simple_trans)
        `uvm_field_int(data, UVM_ALL_ON)
    `uvm_object_utils_end
    function new(string name = "simple_trans");
        super.new(name);
    endfunction
endclass

// 2. Driver
class simple_driver extends uvm_driver #(simple_trans);
    `uvm_component_utils(simple_driver)
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    task run_phase(uvm_phase phase);
        simple_trans req;
        forever begin
            seq_item_port.get_next_item(req);
            `uvm_info("DRV", $sformatf("Driving data: %0d", req.data), UVM_LOW)
            seq_item_port.item_done();
        end
    endtask
endclass

// 3. Sequencer
class simple_sequencer extends uvm_sequencer #(simple_trans);
    `uvm_component_utils(simple_sequencer)
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
endclass

// 4. Monitor
class simple_monitor extends uvm_monitor;
    `uvm_component_utils(simple_monitor)
    uvm_analysis_port #(simple_trans) mon_ap;
    function new(string name, uvm_component parent);
        super.new(name, parent);
        mon_ap = new("mon_ap", this);
    endfunction
    task run_phase(uvm_phase phase);
        simple_trans item;
        forever begin
            #10;
            item = simple_trans::type_id::create("item");
            item.randomize();
            `uvm_info("MON", $sformatf("Observed data: %0d", item.data), UVM_LOW)
            mon_ap.write(item);
        end
    endtask
endclass

// 5. Scoreboard
class simple_scoreboard extends uvm_scoreboard;
    `uvm_component_utils(simple_scoreboard)
    uvm_analysis_imp #(simple_trans, simple_scoreboard) sb_imp;
    int unsigned count;
    function new(string name, uvm_component parent);
        super.new(name, parent);
        sb_imp = new("sb_imp", this);
        count = 0;
    endfunction
    function void write(simple_trans t);
        count++;
        `uvm_info("SCB", $sformatf("Received item #%0d, data=%0d", count, t.data), UVM_LOW)
    endfunction
    function void check_phase(uvm_phase phase);
        if (count == 0)
            `uvm_error("SCB", "No transaction received by scoreboard!")
    endfunction
endclass

// 6. Agent
class simple_agent extends uvm_agent;
    `uvm_component_utils(simple_agent)
    simple_driver    drv;
    simple_sequencer seq;
    simple_monitor   mon;
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        drv = simple_driver::type_id::create("drv", this);
        seq = simple_sequencer::type_id::create("seq", this);
        mon = simple_monitor::type_id::create("mon", this);
    endfunction
    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        drv.seq_item_port.connect(seq.seq_item_export);
    endfunction
endclass

// 7. Environment
class simple_env extends uvm_env;
    `uvm_component_utils(simple_env)
    simple_agent    agt;
    simple_scoreboard scb;
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        agt = simple_agent::type_id::create("agt", this);
        scb = simple_scoreboard::type_id::create("scb", this);
    endfunction
    function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        agt.mon.mon_ap.connect(scb.sb_imp);
    endfunction
endclass

// 8. Sequence
class simple_seq extends uvm_sequence #(simple_trans);
    `uvm_object_utils(simple_seq)
    function new(string name = "simple_seq");
        super.new(name);
    endfunction
    task body();
        repeat (3) begin
            simple_trans tr;
            tr = simple_trans::type_id::create("tr");
            start_item(tr);
            tr.randomize();
            finish_item(tr);
        end
    endtask
endclass

// 9. Test
class base_test extends uvm_test;
    `uvm_component_utils(base_test)
    simple_env env;
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        env = simple_env::type_id::create("env", this);
    endfunction
    task run_phase(uvm_phase phase);
        simple_seq seq;
        phase.raise_objection(this);
        seq = simple_seq::type_id::create("seq");
        seq.start(env.agt.seq);
        #100;
        phase.drop_objection(this);
    endtask
endclass

// 10. Top module
module top;
    initial begin
        run_test("base_test");
    end
endmodule

编译与运行

# VCS 示例
vcs -sverilog -ntb_opts uvm-1.2 -timescale=1ns/1ps \
    +incdir+$UVM_HOME/src $UVM_HOME/src/uvm.sv \
    uvm_base_framework.sv -o simv
./simv

# Questa 示例
vlog -sv +incdir+$UVM_HOME/src $UVM_HOME/src/uvm.sv uvm_base_framework.sv
vsim -c -do "run -all; quit" work.top

验证方法与通过标准

  • 编译通过:仿真器无编译错误,UVM库正常链接。
  • 运行日志:仿真运行后,UVM报告显示UVM_INFO日志,包含来自driver的Driving data、monitor的Observed data以及scoreboard的Received item信息。
  • 通过条件:UVM报告最终显示UVM_ERROR : 0,且scoreboard的check_phase未报告错误(即收到至少1个transaction)。

预期输出(确定性部分)

由于sequence中固定发送3个transaction,scoreboard的count最终应为3。UVM报告应包含类似以下信息(具体时间戳与实例路径可能因仿真器而异):

UVM_INFO DRV: Driving data: <随机值>
UVM_INFO MON: Observed data: <随机值>
UVM_INFO SCB: Received item #3, data=<随机值>
UVM_ERROR: 0

常见问题

  • 编译报错找不到uvm_pkg:确认+incdir+路径指向UVM源码src目录,且编译命令中包含了uvm.sv文件。
  • 仿真挂起不退出:检查test的run_phase中是否正确raise/drop objection;若sequence提前结束且无objection控制,仿真可能立即退出。
  • scoreboard报错“No transaction”:确认agent中monitor的analysis_port已连接到scoreboard的analysis_imp,且monitor的run_phase确实在产生数据。