uvm 知识点整理

1.  uvm_component ,uvm_object

从图上给可以看出,除了driver, monitor, agent, model, scoreboard, env, test之外的几乎所有类本质都是uvm_object。

uvm_component相比uvm_object多出来的功能有两点:

一是增加了new函数的parent参数,使其可以构成UVM树的结构;

二是有phase的自动执行的特点。

与uvm_object相关的factory宏有:

uvm_object_utils:用于将一个直接或间接派生自uvm_object的类注册到factory中。
uvm_object_utils_begin:使用这个宏来开启field_automation机制。
uvm_object_utils_end:与uvm_object_*_begin成对出现,作为factory注册的结束标志。

与uvm_component相关的factory宏有:
uvm_component_utils:用于将一个直接或间接派生自uvm_component的类注册到factory中。
uvm_component_utils_begin/uvm_component_utils_end:同上。

https://www.aldec.com/en/company/blog/149--understanding-the-inner-workings-of-uvm

2.  clocking 

模块端口和接口默认不指定信号之间的任何时序要求或同步方案。在时钟和结束时钟之间定义的时钟块正是如此。它是一组与特定时钟同步的信号集合,有助于指定时钟和信号之间的时序要求。

[default] clocking [identifier_name] @ [event_or_identifier]
	default input #[delay_or_edge] output #[delay_or_edge]
	[list of signals]
endclocking
clocking ckb @ (posedge clk);
	default input #1step output negedge;
	input ...;
	output ...;
endclocking

clocking ck1 @ (posedge clk);
	default input #5ns output #2ns;
	input data, valid, ready = top.ele.ready;
	output negedge grant;
	input #1step addr;
endclocking

注意以下内容:
创建了一个名为ck1的时钟块,该块将在clk的正沿激活;
默认情况下,时钟块内的所有输入信号将在时钟clk的正沿前5ns进行采样,所有输出信号将在时钟clk的正沿后2ns驱动;
data、valid和ready被声明为块的输入,因此将在clk的正沿前5ns进行采样;
grant是块的输出信号,具有自己的时间要求。在这里,grant将在clk的负沿驱动,而不是默认的正沿。

NOTE: 如果clocking block 没有指定 输入和输出的采样时间,默认采样时间是

  default input #1step output #0ns

SystemVerilog Clocking Blocks

SystemVerilog Clocking Tutorial

3. sequence 

* mid_do and post_do are functions, All other are tasks

UVM Sequence - Verification GuideUVM Sequence - Verification Guide

Communication between the Sequence and driver involves below steps,
1.create_item() / create req.
2.wait_for_grant().
3.randomize the req.
4.send the req.
5.wait for item done.
6.get response.

* Step 5 and 6 are optional.

class my_sequence extends uvm_sequence #(seq_item);
  `uvm_object_utils(my_sequence)
  
   function new (string name = "my_sequence")
     super.new(name);
   endfunction

   task body();
     req = seq_item::type_id::create("req");
     start_item(req);
     assert(req.randomize());
     finish_item(req);
   endtask
endclass

①  sequence 内部的task body()内:

创建transaction

start_item()

transaction 随机化

finish_item()

class my_sequence extends uvm_sequence #(seq_item);
  `uvm_object_utils(my_sequence)
  
   function new (string name = "my_sequence")
     super.new(name);
   endfunction

   task body();
     req = seq_item::type_id::create("req");
     wait_for_grant();
     assert(req.randomize());
     send_request(req);
     wait_for_item_done();
     get_respose(rsp);
   endtask
endclass

② 

1.create_item() / create req.
2.wait_for_grant().
3.randomize the req.
4.send the req.
5.wait for item done.
6.get response.

class my_sequence extends uvm_sequence #(seq_item);
  `uvm_object_utils(my_sequence)
  
   function new (string name = "my_sequence")
     super.new(name);
   endfunction

   task body();
     `uvm_do_with(req, {req.<variable> == 0;}); // any constraint
   endtask
endclass

③ 使用 uvm macros :

`uvm_do(sequence)

  `uvm_do_with()

How to write a sequence

An intention is to create a seq_item, randomize it, and then send it to the driver. To perform this operation any one of the following approaches is followed in the sequence.

  1. Using macros like `uvm_do , `uvm_create, `uvm_send etc
  2. Using existing methods from the base class
    a. Using wait_for_grant(), send_request(), wait_for_item_done() etc
    b. Using start_item/finish_item methods.

4.  m_sequencer ,p_sequencer

m_sequencer

The m_sequencer handle contains the reference to the sequencer(default sequencer) on which the sequence is running.

m_sequencer is the generic uvm_sequencer pointer. it will always exist for the uvm_sequence and is initialized when the sequence is started.

This is determined by,

  • the sequencer handle provided in the start method
  • the sequencer used by the parent sequence
  • the sequencer that was set using the set_sequencer method

p_sequencer

p_sequencer is a typed-specific sequencer pointer, created by registering the sequence to the sequencer using macros. It will not exist if we have not registered the sequence with macros.
As it is type-specific we can access almost everything added to the sequencer.

The p_sequencer is a variable, used as handle to access the sequencer properties.
p_sequencer is defined using the macro `uvm_declare_p_sequencer(SEQUENCER_NAME)

To put it simply, a P-sequencer (port-sequencer) is to drive transaction to a specific port interface on the DUT.

m_sequencer is the default handle for uvm_vitual_sequencer and p_sequencer is the hook up for child sequencer.

5. modport

 在sv中,对一系列接口的方向做出限制的接口列表。  可简化模块间的链接方式,易于测试激励编写。

先在interface中描述modport ,此时描述的接口方向与dut的接口方向一致。 slave 接受输入data 和addr ,master 接受sready  响应。 

interface ms_if (input clk);
  logic sready;      // Indicates if slave is ready to accept data
  logic rstn;        // Active low reset
  logic [1:0] addr;  // Address
  logic [7:0] data;  // Data

  modport slave ( input addr, data, rstn, clk,
                 output sready);

  modport master ( output addr, data,
                  input  clk, sready, rstn);
endinterface

定义master module 功能

// This module accepts an interface with modport "master"
// Master sends transactions in a pipelined format
// CLK    1   2   3   4   5   6
// ADDR   A0  A1  A2  A3  A0  A1
// DATA       D0  D1  D2  D3  D4
module master ( ms_if.master mif);
  always @ (posedge mif.clk) begin

  	// If reset is applied, set addr and data to default values
    if (! mif.rstn) begin
      mif.addr <= 0;
      mif.data <= 0;

    // Else increment addr, and assign data accordingly if slave is ready
    end else begin
    // Send new addr and data only if slave is ready
      if (mif.sready) begin
      	mif.addr <= mif.addr + 1;
      	mif.data <= (mif.addr * 4);

     // Else maintain current addr and data
      end else begin
        mif.addr <= mif.addr;
        mif.data <= mif.data;
      end
    end
  end
endmodule

 定义slave 功能

module slave (ms_if.slave sif);
  reg [7:0] reg_a;
  reg [7:0]	reg_b;
  reg 		reg_c;
  reg [3:0] reg_d;

  reg		dly;
  reg [3:0] addr_dly;


  always @ (posedge sif.clk) begin
    if (! sif.rstn) begin
      addr_dly <= 0;
    end else begin
      addr_dly <= sif.addr;
    end
  end

  always @ (posedge sif.clk) begin
    if (! sif.rstn) begin
      	reg_a <= 0;
    	reg_b <= 0;
    	reg_c <= 0;
    	reg_d <= 0;
  	end else begin
      case (addr_dly)
        0 : reg_a <= sif.data;
        1 : reg_b <= sif.data;
        2 : reg_c <= sif.data;
        3 : reg_d <= sif.data;
      endcase
    end
  end

  assign sif.sready = ~(sif.addr[1] & sif.addr[0]) | ~dly;

  always @ (posedge sif.clk) begin
    if (! sif.rstn)
      dly <= 1;
    else
      dly <= sif.sready;
  end

endmodule

 top层模块链接

module d_top (ms_if tif);
	// Pass the "master" modport to master
  	master 	m0 (tif.master);

  	// Pass the "slave" modport to slave
  	slave 	s0 (tif.slave);
endmodule

 测试用例

module tb;
  reg clk;
  always #10 clk = ~clk;

  ms_if 	if0 (clk);
  d_top 	d0  (if0);

  // Let the stimulus run for 20 clocks and stop
  initial begin
    clk <= 0;
    if0.rstn <= 0;
    repeat (5) @ (posedge clk);
    if0.rstn <= 1;

    repeat (20) @ (posedge clk);
    $finish;
  end
endmodule

6. analysis port 

  1. The uvm_analysis_port is a TLM-based class that provides a write method for communication. TLM analysis port broadcasts transactions to one or multiple components.
  2. uvm_analysis_port can be open without any implementation of uvm_analysis_imp or uvm_analysis_export.
  3. Single uvm_analysis_port can have a connection with uvm_analysis_imp or uvm_analysis_export. No errors will be reported. 
  4. Multiple uvm_analysis_port can be connected to a single uvm_analysis_imp or uvm_analysis_export.
  5. uvm_subscriber already has analysis_export so that it can directly receive transactions from the connected analysis port. Generally, it is useful to write a coverage collector that attaches to the monitor.
  6. Valid Connections:
    a. port to port
    b. port to export
    c. port to imp
    d. export to export
    e. export to imp    (没有imp to imp)

uvm 参考

http://cluelogic.com/2011/07/uvm-tutorial-for-candy-lovers-agent/

sequence

https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.1b/html/files/seq/uvm_sequence_base-svh.html

How to create and use a sequence

UVM Sequence item - Verification Guide

UVM Sequence - VLSI Verify

uvm_sequence_base methods - VLSI Verify

UVM Sequence macros - VLSI Verify

sequencer

UVM Sequencer | The Octet Institute

https://verificationacademy.com/forums/t/p-sequencer-and-m-sequencer/31081/3

https://www.youtube.com/watch?v=OdHVk3Pc3Gw

modport

SystemVerilog Modport

analysis port

https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.1d/html/files/tlm1/uvm_analysis_port-svh.html

UVM TLM Analysis Port

TLM Analysis port Analysis imp port - Verification Guide

TLM-10 A Single Port - EDA Playground

TLM Analysis interface - VLSI Verify

TLM Analysis interface - VLSI Verify

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值