zoukankan      html  css  js  c++  java
  • *2.2.1 最简单的验证平台

    2.2 只有driver的验证平台

    driver是验证平台最基本的组件,是整个验证平台数据流的源泉。本节以一个简单的DUT为例,说明一个只有driver的UVM验证平台是如何搭建的。

    *2.2.1 最简单的验证平台

    在本章中,假设有如下的DUT定义:

    代码清单 2-1
    文件:src/ch2/dut/dut.sv
      1 module dut(clk,
      2           rst_n,
      3           rxd,
      4           rx_dv,
      5           txd,
      6           tx_en);
      7 input clk;
      8 input rst_n;
      9 input[7:0] rxd;
     10 input rx_dv;
     11 output [7:0] txd;
     12 output tx_en;
     13
     14 reg[7:0] txd;
     15 reg tx_en;
     16
     17 always @(posedge clk) begin
     18    if(!rst_n) begin
     19       txd <= 8'b0;
     20       tx_en <= 1'b0;
     21    end
     22    else begin
     23       txd <= rxd;
     24       tx_en <= rx_dv;
     25    end
     26 end
     27 endmodule

    这个DUT的功能非常简单,通过rxd接收数据,再通过txd发送出去。其中rx_dv是接收的数据有效指示,tx_en是发送的数据有效指示。本章中所有例子都是基于这个DUT。

    UVM中的driver应该如何搭建?UVM是一个库,在这个库中,几乎所有的东西都是使用类(class)来实现的。driver、monitor、reference model、scoreboard等组成部分都是类。类是像SystemVerilog这些面向对象编程语言中最伟大的发明之一,是面向对象的精髓所在。类有函数(function),另外还可以有任务(task),通过这些函数和任务可以完成driver的输出激励功能,完成monitor的监测功能,完成参考模型的计算功能,完成scoreboard的比较功能。类中可以有成员变量,这些成员变量可以控制类的行为,如控制driver的行为等。当要实现一个功能时,首先应该想到的是从UVM的某个类派生出一个新的类,在这个新的类中实现所期望的功能。

    所以,使用UVM的第一条原则是:验证平台中所有的组件应该派生自UVM中的类。

    UVM验证平台中的driver应该派生自uvm_driver,一个简单的driver如下例所示:

    代码清单 2-2
    文件:src/ch2/section2.2/2.2.1/my_driver.sv
      3 class my_driver extends uvm_driver;
      4
      5    function new(string name = "my_driver", uvm_component parent = null);
      6       super.new(name, parent);
      7    endfunction
      8    extern virtual task main_phase(uvm_phase phase);
      9 endclass
     10
     11 task my_driver::main_phase(uvm_phase phase);
     12    top_tb.rxd <= 8'b0;
     13    top_tb.rx_dv <= 1'b0;
     14    while(!top_tb.rst_n)
     15       @(posedge top_tb.clk);
     16    for(int i = 0; i < 256; i++)begin
     17       @(posedge top_tb.clk);
     18       top_tb.rxd <= $urandom_range(0, 255);
     19       top_tb.rx_dv <= 1'b1;
     20       `uvm_info("my_driver", "data is drived", UVM_LOW)
     21    end
     22    @(posedge top_tb.clk);
     23    top_tb.rx_dv <= 1'b0;
     24 endtask

    这个driver的功能非常简单,只是向rxd上发送256个随机数据,并将rx_dv信号置为高电平。当数据发送完毕后,将rx_dv信号置为低电平。在这个driver中,有两点应该引起注意:

    所有派生自uvm_driver的类的new函数有两个参数,一个是string类型的name,一个是uvm_component类型的parent。关于name参数,比较好理解,就是名字而已;至于parent则比较难以理解,读者可暂且放在一边,下文会有介绍。事实上,这两个参数是由uvm_component要求的,每一个派生自uvm_component或其派生类的类在其new函数中要指明两个参数:name和parent,这是uvm_component类的一大特征。而uvm_driver是一个派生自uvm_component的类,所以也会有这两个参数。

    driver所做的事情几乎都在main_phase中完成。UVM由phase来管理验证平台的运行,这些phase统一以xxxx_phase来命名,且都有一个类型为uvm_phase、名字为phase的参数。main_phase是uvm_driver中预先定义好的一个任务。因此几乎可以简单地认为,实现一个driver等于实现其main_phase

    上述代码中还出现了uvm_info宏。这个宏的功能与Verilog中display语句的功能类似,但是它比display语句更加强大。它有三个参数,第一个参数是字符串,用于把打印的信息归类;第二个参数也是字符串,是具体需要打印的信息;第三个参数则是冗余级别。在验证平台中,某些信息是非常关键的,这样的信息可以设置为UVM_LOW,而有些信息可有可无,就可以设置为UVM_HIGH,介于两者之间的就是UVM_MEDIUM。UVM默认只显示UVM_MEDIUM或者UVM_LOW的信息,本书3.4.1节会讲述如何显示UVM_HIGH的信息。本节中uvm_info宏打印的结果如下:
    UVM_INFO my_driver.sv(20) @ 48500000: drv [my_driver] data is drived

    在uvm_info宏打印的结果中有如下几项:

    UVM_INFO关键字:表明这是一个uvm_info宏打印的结果。除了uvm_info宏外,还有uvm_error宏、uvm_warning宏,后文中将会介绍。

    my_driver.sv(20):指明此条打印信息的来源,其中括号里的数字表示原始的uvm_info打印语句在my_driver.sv中的行号。

    48500000:表明此条信息的打印时间。

    drv:这是driver在UVM树中的路径索引。UVM采用树形结构,对于树中任何一个结点,都有一个与其相应的字符串类型的路径索引。路径索引可以通过get_full_name函数来获取,把下列代码加入任何UVM树的结点中就可以得知当前结点的路径索引:

    代码清单 2-3
    $display("the full name of current component is: %s", get_full_name());

    [my_driver]:方括号中显示的信息即调用uvm_info宏时传递的第一个参数。

    data is drived:表明宏最终打印的信息。

    可见,uvm_info宏非常强大,它包含了打印信息的物理文件来源、逻辑结点信息(在UVM树中的路径索引)、打印时间、对信息的分类组织及打印的信息。读者在搭建验证平台时应该尽量使用uvm_info宏取代display语句。

    定义my_driver后需要将其实例化。这里需要注意类的定义与类的实例化的区别。所谓类的定义,就是用编辑器写下:

    代码清单 2-4
    classs A;
    …
    endclass

    而所谓类的实例化指的是通过new创造出A的一个实例。如:

    代码清单 2-5
    A a_inst;
    a_inst = new();

    类的定义类似于在纸上写下一纸条文,然后把这些条文通知给SystemVerilog的仿真器:验证平台可能会用到这样的一个类,请做好准备工作。而类的实例化在于通过new()来通知SystemVerilog的仿真器:请创建一个A的实例。仿真器接到new的指令后,就会在内存中划分一块空间,在划分前,会首先检查是否已经预先定义过这个类,在已经定义过的情况下,按照定义中所指定的“条文”分配空间,并且把这块空间的指针返回给a_inst,之后就可以通过a_inst来查看类中的各个成员变量,调用成员函数/任务等。对大部分的类来说,如果只定义而不实例化,是没有任何意义的;而如果不定义就直接实例化,仿真器将会报错。

    对my_driver实例化并且最终搭建的验证平台如下:

    代码清单 2-6

    文件:src/ch2/section2.2/2.2.1/top_tb.sv
      1 `timescale 1ns/1ps
      2 `include "uvm_macros.svh"
      3
      4 import uvm_pkg::*;
      5 `include "my_driver.sv"
      6
      7 module top_tb;
      8
      9 reg clk;
     10 reg rst_n;
     11 reg[7:0] rxd;
     12 reg rx_dv;
     13 wire[7:0] txd;
     14 wire tx_en;
     15
     16 dut my_dut(.clk(clk),
     17            .rst_n(rst_n),
     18            .rxd(rxd),
     19            .rx_dv(rx_dv),
     20            .txd(txd),
     21            .tx_en(tx_en));
     22
     23 initial begin
     24    my_driver drv;
     25    drv = new("drv", null);
     26    drv.main_phase(null);
     27    $finish();
     28 end
     29
     30 initial begin
     31    clk = 0;
     32    forever begin
     33       #100 clk = ~clk;
     34    end
     35 end
     36
     37 initial begin
     38    rst_n = 1'b0;
     39    #1000;
     40    rst_n = 1'b1;
     41 end
     42
     43 endmodule

    第2行把uvm_macros.svh文件通过include语句包含进来。这是UVM中的一个文件,里面包含了众多的宏定义,只需要包含一次。

    第4行通过import语句将整个uvm_pkg导入验证平台中。只有导入了这个库,编译器在编译my_driver.sv文件时才会认识其中的uvm_driver等类名。

    第24和25行定义一个my_driver的实例并将其实例化。注意这里调用new函数时,其传入的名字参数为drv,前文介绍uvm_info宏的打印信息时出现的代表路径索引的drv就是在这里传入的参数drv。另外传入的parent参数为null,在真正的验证平台中,这个参数一般不是null,这里暂且使用null

    第26行显式地调用my_driver的main_phase。在main_phase的声明中,有一个uvm_phase类型的参数phase,在真正的验证平台中,这个参数是不需要用户理会的。本节的验证平台还算不上一个完整的UVM验证平台,所以暂且传入null。

    第27行调用finish函数结束整个仿真,这是一个Verilog中提供的函数。

    运行这个例子,可以看到“data is drived”被输出了256次。

  • 相关阅读:
    8086汇编学习小记王爽汇编语言实验12
    8086汇编学习小记王爽汇编语言课程设计1
    activeMQ 持久化配置 kevin
    snmpwalk kevin
    tcp benchmark kevin
    apache camel 条件路由 kevin
    netty 并发访问测试配置 kevin
    snmp常见操作 kevin
    转发:RocketMQ与kafka的对比 kevin
    centos jdk 下载 kevin
  • 原文地址:https://www.cnblogs.com/YINBin/p/6821822.html
Copyright © 2011-2022 走看看