我是靠谱客的博主 细腻外套,最近开发中收集的这篇文章主要介绍UVM Hello World Tutorialdut:top:my_test:sequencer:driver仿真结果,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在这里插入图片描述

dut:


// dut连接testbench的接口
interface dut_if;     // 在dut中定义dut接口
  logic clock, reset;
  logic cmd;           // 接口的变量,即transaction传输的变量
  logic [7:0] addr;
  logic [7:0] data;
endinterface

`include "uvm_macros.svh"

// dut
// 时钟切换就会简单地打印一条消息
module dut(dut_if dif);  // 声明传入接口,命名为dif 
  import uvm_pkg::*;
  always @(posedge dif.clock)  // 来自接口的时钟
    if (dif.reset != 1) begin
      `uvm_info("DUT",
                $sformatf("Received cmd=%b, addr=0x%2h, data=0x%2h",
                          dif.cmd, dif.addr, dif.data), UVM_MEDIUM)
    end
endmodule

$sformatf(format,args),将args传入字符串中,返回字符串结果。

top:

top中例化dut,例化dut的接口,发送dut接口信息到库,定义dut的接口的时钟,开始测试

/*******************************************
This is a basic UVM "Hello World" testbench.

Explanation of this testbench on YouTube:
https://www.youtube.com/watch?v=Qn6SvG-Kya0
*******************************************/

`include "uvm_macros.svh"
`include "my_testbench_pkg.svh"  // include my_test

// 包含 DUT 和接口的顶层模块
// 这个模块开始测试
module top;
  import uvm_pkg::*;
  import my_testbench_pkg::*;  // import my_test
  
 
  dut_if dut_if1();  // 在top中实例化dut接口
  
  dut dut1(.dif(dut_if1));   // 在top中实例化dut, 并将其连接到接口
  
  // 在top中定义 dut接口的时钟发生器
  initial begin
    dut_if1.clock = 0;
    forever #5 dut_if1.clock = ~dut_if1.clock;  // 10ns一个时钟周期
  end
  
  initial begin
    // 将接口放入UVM配置数据库
    uvm_config_db#(virtual dut_if)::set(null, "*", "dut_vif", dut_if1);
    // 开始测试
    run_test("my_test");
  end
  
  // edaplayground 显示波形设置
  initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, top); 
  end
  
endmodule

my_test:

my_testbench_pkg 中 包括 my_test,env,agent

package my_testbench_pkg;
  import uvm_pkg::*;
  
  // my_test 要包含sequence,driver
  `include "my_sequence.svh"
  `include "my_driver.svh"
  
  /******************my_test*************************/
  class my_test extends uvm_test;
    `uvm_component_utils(my_test)  // component注册
    
    my_env env;  // 声明,my_test包括env

    function new(string name, uvm_component parent);  // 构造函数
      super.new(name, parent);
    endfunction
    
    function void build_phase(uvm_phase phase);  // 实例化组件
      env = my_env::type_id::create("env", this);  // 实例化env
    endfunction
    
    task run_phase(uvm_phase phase);
      phase.raise_objection(this);  // 开始运行
      #10;
      `uvm_warning("", "Hello World!")
      phase.drop_objection(this);   // 结束运行
    endtask

  endclass
  
  /**********************env*********************/
  class my_env extends uvm_env;  // my_test 要包含env
    `uvm_component_utils(my_env)    // component注册
    
    my_agent agent;  // env要包含agent

    function new(string name, uvm_component parent);  // 构造函数
      super.new(name, parent);
    endfunction
    
    function void build_phase(uvm_phase phase);  // 实例化组件
      agent = my_agent::type_id::create("agent", this);  // 实例化agent
    endfunction

  endclass
  
  /******************agent*************************/
  class my_agent extends uvm_agent;  // my_test 再包含agent 
    `uvm_component_utils(my_agent)  // component注册
    
    my_driver driver;  // agent包含driver
    uvm_sequencer#(my_transaction) sequencer;  // agent包含sequencer
    
    function new(string name, uvm_component parent);  // 构造函数
      super.new(name, parent);
    endfunction
    
    function void build_phase(uvm_phase phase);  // 实例化组件
      driver = my_driver ::type_id::create("driver", this);  // 在agent中实例化driver
      sequencer =
        uvm_sequencer#(my_transaction)::type_id::create("sequencer", this);  // 在agent中实例化sequencer
    endfunction    
    
    function void connect_phase(uvm_phase phase);  // 连接组件
      driver.seq_item_port.connect(sequencer.seq_item_export);  // sequencer出口连接driver接口
    endfunction
    
    task run_phase(uvm_phase phase);  // 运行
      phase.raise_objection(this);  // 开始运行
      begin
        my_sequence seq;  // 运行阶段声明sequence
        seq = my_sequence::type_id::create("seq");  // 实例化sequence
        seq.start(sequencer);  // sequence从sequencer发送
      end
      phase.drop_objection(this);  // 结束运行
    endtask

  endclass

endpackage


sequencer:

// sequencer

class my_transaction extends uvm_sequence_item;  // transaction

  `uvm_object_utils(my_transaction)  // object注册

  rand bit cmd;  // transaction变量
  rand int addr;
  rand int data;

  constraint c_addr { addr >= 0; addr < 256; }  // addr变量约束
  constraint c_data { data >= 0; data < 256; }  // data变量约束

  function new (string name = "");  // 构造函数的
    super.new(name);
  endfunction

endclass: my_transaction

class my_sequence extends uvm_sequence#(my_transaction);   // sequence

  `uvm_object_utils(my_sequence)   // object注册

  function new (string name = "");  // 构造函数
    super.new(name);
  endfunction

  task body;
    repeat(8) begin  // 重复8次
      req = my_transaction::type_id::create("req");  // 在sequence中实例化transaction
      start_item(req);  // 发送

      if (!req.randomize()) begin  // 随机化transaction失败
        `uvm_error("MY_SEQUENCE", "Randomize failed.");
      end

      // If using ModelSim, which does not support randomize(),
      // we must randomize item using traditional methods, like
      // req.cmd = $urandom;
      // req.addr = $urandom_range(0, 255);
      // req.data = $urandom_range(0, 255);

      finish_item(req);  // 结束发送
    end
  endtask: body

endclass: my_sequence


driver


class my_driver extends uvm_driver #(my_transaction);

  `uvm_component_utils(my_driver)  // 注册component

  virtual dut_if dut_vif;  // 指向dut接口的指针, 在driver中的“虚拟接口”

  function new(string name, uvm_component parent);  // 构造函数
    super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);  // 实例化组件
    // 从配置数据库获取接口
    if(!uvm_config_db#(virtual dut_if)::get(this, "", "dut_vif", dut_vif)) begin
      `uvm_error("", "uvm_config_db::get failed")
    end
  endfunction 

  task run_phase(uvm_phase phase);  // 运行
    dut_vif.reset = 1;     // 第一次切换先重置
    @(posedge dut_vif.clock);  // 获取dut接口时钟
    #1;
    dut_vif.reset = 0;    // 取消重置
    
    // 开始运行
    forever begin
      seq_item_port.get_next_item(req);  // sequencer获取transaction给driver
	  // driver把transaction给dut,此时sequencer停止获取transaction给driver
      dut_vif.cmd  = req.cmd;   // transaction的变量传给dut接口
      dut_vif.addr = req.addr;
      dut_vif.data = req.data;
      @(posedge dut_vif.clock);

      seq_item_port.item_done();  // 解除阻塞(sequencer可以获取transaction给driver)
    end
  endtask

endclass: my_driver

仿真结果

在这里插入图片描述

在这里插入图片描述


最后

以上就是细腻外套为你收集整理的UVM Hello World Tutorialdut:top:my_test:sequencer:driver仿真结果的全部内容,希望文章能够帮你解决UVM Hello World Tutorialdut:top:my_test:sequencer:driver仿真结果所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(77)

评论列表共有 0 条评论

立即
投稿
返回
顶部