image/svg+xml
  • Contents
      • Back
      • Digital Basics
      • Verilog
      • Verification
      • SystemVerilog
      • UVM
Most Popular
Verification
  Testbench Evolution
  Constraint Random Verification
  Verification Techniques
  Verification Plan
  Code Coverage

Verilog
  Data Types
  Basic Constructs
  Behavioral Modeling
  Gate Modeling
  Simulation Basics
  Design Examples

SystemVerilog
  Data Types
  Class
  Interface
  Constraints and more!
  Testbench Examples

UVM
  Sequences
  Testbench Components
  TLM Tutorial
  Register Model Tutorial
  Testbench Examples

Digital Fundamentals
  Binary Arithmetic
  Boolean Logic
  Karnaugh Maps
  Combinational Logic
  Sequential Logic




How to use `uvm_do sequence macros ?

In How to create and use a sequence, we saw that a sequence calls on the tasks start_item() and finish_item(). You can avoid putting all these statements in your code by simply calling UVM sequence macros `uvm_do or `uvm_do_with. At compile time, these macros will be substituted with calls to start_item() and finish_item(). There are primarily four types of UVM macros that can be executed on the default sequencer.

Read more: How to use `uvm_do sequence macros ?

How to create and use a sequence

Sequences are made up of several data items, which may form an interesting scenario. For example, you can have a sequence that performs register read/writes to all the registers within the design, a sequence to perform reset, or another one to apply some stimulus to the DUT. So, you'll end up having a number of different sequences that perform different tasks to verify different aspects of the design. Remember that a sequence item refers to a packet of data, while a sequence is just a container for an arrangement of items/sub-sequences. sequence_library Now, you have a few options :

  • Use existing sequences to drive stimulus to the DUT individually
  • Combine existing sequences to create new ones - perform reset sequence followed by register read/writes followed by FSM state change sequence
  • Pull random sequences from the sequence library and execute them on the DUT
arrange sequences in multiple ways

Read more: How to create and use a sequence

Verilog T Flip Flop

Design


module tff ( 	input clk,
            	input rstn,
            	input t,
            output reg q);
  
  always @ (posedge clk) begin
    if (!rstn) 
      q <= 0;
    else
    	if (t)
      		q <= ~q;
    	else
      		q <= q;
  end
endmodule

Testbench


module tb;
  reg clk;
  reg rstn;
  reg t;
  
  tff u0 (	.clk(clk),
          	.rstn(rstn),
          	.t(t),
          .q(q));
  
  always #5 clk = ~clk;
  
  initial begin  
    {rstn, clk, t} <= 0;
    
    $monitor ("T=%0t rstn=%0b t=%0d q=%0d", $time, rstn, t, q);
    repeat(2) @(posedge clk);
    rstn <= 1;
    
    for (integer i = 0; i < 20; i = i+1) begin
      reg [4:0] dly = $random;
      #(dly) t <= $random;
    end
	#20 $finish;
  end
endmodule
 Simulation Log
ncsim> run
T=0 rstn=0 t=0 q=x
T=5 rstn=0 t=0 q=0
T=15 rstn=1 t=0 q=0
T=19 rstn=1 t=1 q=0
T=25 rstn=1 t=1 q=1
T=35 rstn=1 t=1 q=0
T=43 rstn=1 t=0 q=0
T=47 rstn=1 t=1 q=0
T=55 rstn=1 t=0 q=1
T=59 rstn=1 t=1 q=1
T=65 rstn=1 t=1 q=0
T=67 rstn=1 t=0 q=0
T=71 rstn=1 t=1 q=0
T=75 rstn=1 t=0 q=1
T=79 rstn=1 t=1 q=1
T=83 rstn=1 t=0 q=1
T=87 rstn=1 t=1 q=1
T=95 rstn=1 t=0 q=0
Simulation complete via $finish(1) at time 115 NS + 0

UVM Object Compare

  1. Using automation macros
  2. Using do_compare

uvm_object has many common functions like print, copy and compare that are available to all its child classes and can be used out of the box if UVM automation macros are used inside the class definition. In a previous article , copy, do_copy and use of automation macros to print were discussed.

Using automation macros

UVM automation macros can be used for automatic implementation of copy, print, compare and more. In this example, a class called Packet is defined with a variable called m_addr that is registered with automation macros `uvm_field_int to be included for all the default functions like print, copy, compare, etc. An object of this class is used inside another class Object which has a bunch of other variables of different data types that are also registered using appropriate macros. For example, m_bool is of enum type and is registered with `uvm_field_enum macro.


typedef enum {FALSE, TRUE} e_bool;

class Packet extends uvm_object;
  rand bit[15:0] 	m_addr;
  
  virtual function string convert2string();
    string contents;
    contents = $sformatf("m_addr=0x%0h", m_addr);
  endfunction

  `uvm_object_utils_begin(Packet)
  	`uvm_field_int(m_addr, UVM_DEFAULT)
  `uvm_object_utils_end
  
  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass

class Object extends uvm_object;
  rand e_bool 				m_bool;
  rand bit[3:0] 			m_mode;
  string 					m_name;
  rand Packet 				m_pkt;
  
  function new(string name = "Object");
    super.new(name);
    m_name = name;
    m_pkt = Packet::type_id::create("m_pkt");
    m_pkt.randomize();
  endfunction
  
  `uvm_object_utils_begin(Object)
  	`uvm_field_enum(e_bool, m_bool, UVM_DEFAULT)
  	`uvm_field_int (m_mode, 		UVM_DEFAULT)
  	`uvm_field_string(m_name, 		UVM_DEFAULT)
  	`uvm_field_object(m_pkt, 		UVM_DEFAULT)
  `uvm_object_utils_end
endclass

Let us create a base class and create two objects obj1 and obj2 , randomize both and print them. Then compare both objects to see what the result is. Then copy each variable from obj2 from obj1 including the nested class object of type Packet until the comparison errors are resolved.


class base_test extends uvm_test;
  `uvm_component_utils(base_test)
  function new(string name = "base_test", uvm_component parent=null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
  	// Create two objects, randomize them and print the contents
    Object obj1 = Object::type_id::create("obj1");
    Object obj2 = Object::type_id::create("obj2");
    obj1.randomize();
    obj1.print();
    obj2.randomize();
    obj2.print();
    
    _compare(obj1, obj2);
   
      `uvm_info("TEST", "Copy m_bool", UVM_LOW)
    obj2.m_bool = obj1.m_bool;
        `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
      
      `uvm_info("TEST", "Copy m_mode", UVM_LOW)
    obj2.m_mode = obj1.m_mode;
        `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
    
      `uvm_info("TEST", "Copy m_name", UVM_LOW)
    obj2.m_name = obj1.m_name;
        `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
      
      `uvm_info("TEST", "Copy m_pkt.m_addr", UVM_LOW)
    obj2.m_pkt.m_addr = obj1.m_pkt.m_addr;
    	`uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
  endfunction
  
  function void _compare(Object obj1, obj2);
    if (obj2.compare(obj1))
      `uvm_info("TEST", "obj1 and obj2 are same", UVM_LOW)
    else
      `uvm_info("TEST", "obj1 and obj2 are different", UVM_LOW)
  endfunction
endclass

module tb;
	initial begin
		run_test("base_test");
	end
endmodule
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
----------------------------------
Name        Type      Size  Value 
----------------------------------
obj1        Object    -     @1903 
  m_bool    e_bool    32    TRUE  
  m_mode    integral  4     'h9   
  m_name    string    4     obj1  
  m_pkt     Packet    -     @1905 
    m_addr  integral  16    'h3cb6
----------------------------------
----------------------------------
Name        Type      Size  Value 
----------------------------------
obj2        Object    -     @1907 
  m_bool    e_bool    32    FALSE 
  m_mode    integral  4     'hf   
  m_name    string    4     obj2  
  m_pkt     Packet    -     @1908 
    m_addr  integral  16    'h64c1
----------------------------------
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(351) @ 0: reporter [MISCMP] Miscompare for obj2.m_bool: lhs = FALSE : rhs = TRUE
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(382) @ 0: reporter [MISCMP] 1 Miscompare(s) for object obj1@1903 vs. obj2@1907
UVM_INFO testbench.sv(71) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(73) @ 0: uvm_test_top [TEST] Copy m_bool
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(351) @ 0: reporter [MISCMP] Miscompare for obj2.m_mode: lhs = 'hf : rhs = 'h9
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(382) @ 0: reporter [MISCMP] 1 Miscompare(s) for object obj1@1903 vs. obj2@1907
UVM_INFO testbench.sv(78) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(80) @ 0: uvm_test_top [TEST] Copy m_mode
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(351) @ 0: reporter [MISCMP] Miscompare for obj2.m_name: lhs = "obj2" : rhs = "obj1"
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(382) @ 0: reporter [MISCMP] 1 Miscompare(s) for object obj1@1903 vs. obj2@1907
UVM_INFO testbench.sv(85) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(87) @ 0: uvm_test_top [TEST] Copy m_name
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(351) @ 0: reporter [MISCMP] Miscompare for obj2.m_pkt.m_addr: lhs = 'h64c1 : rhs = 'h3cb6
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_comparer.svh(382) @ 0: reporter [MISCMP] 1 Miscompare(s) for object obj1@1903 vs. obj2@1907
UVM_INFO testbench.sv(92) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(94) @ 0: uvm_test_top [TEST] Copy m_pkt.m_addr
UVM_INFO testbench.sv(97) @ 0: uvm_test_top [TEST] obj1 and obj2 are same
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 

Automation macros introduce a lot of additional code and is not generally recommended

Using do_compare

Another way is for the user to implement do_compare method inside the child class and compare the values of each variable and return the result. Note in the following example that uvm_object_utils_* macros are not used and hence the print() method we used above will not work as is. Instead another method called convert2string is implemented for both classes so that it returns the contents in a string format when called.

Just like the way print calls do_print method, a compare calls the do_compare method and implementation of the function is all that is required to be done.


typedef enum {FALSE, TRUE} e_bool;

class Packet extends uvm_object;
  rand bit[15:0] 	m_addr;
  
  virtual function string convert2string();
    string contents;
    contents = $sformatf("m_addr=0x%0h", m_addr);
    return contents;
  endfunction

  `uvm_object_utils(Packet)
  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    bit res;
    Packet _pkt;
    
    $cast(_pkt, rhs);
    super.do_compare(_pkt, comparer);
    
    res = 	super.do_compare(_pkt, comparer) &
			m_addr == _pkt.m_addr;   			
    `uvm_info(get_name(), $sformatf("In Packet::do_compare(), res=%0b", res), UVM_LOW)
    return res;
  endfunction
  
  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass

class Object extends uvm_object;
  rand e_bool 				m_bool;
  rand bit[3:0] 			m_mode;
  string 					m_name;
  rand Packet 				m_pkt;
  
  function new(string name = "Object");
    super.new(name);
    m_name = name;
    m_pkt = Packet::type_id::create("m_pkt");
    m_pkt.randomize();
  endfunction
  
  // This task is used to print contents
  virtual function string convert2string();
    string contents = "";
    $sformat(contents, "%s m_name=%s", contents, m_name);
    $sformat(contents, "%s m_bool=%s", contents, m_bool.name());
    $sformat(contents, "%s m_mode=0x%0h", contents, m_mode);
    $sformat(contents, "%s %s", contents, m_pkt.convert2string()); 
    return contents;
  endfunction
  
  `uvm_object_utils(Object)
  
  // "rhs" does not contain m_bool, m_mode, etc since its a parent
  // handle. So cast into child data type and access using child handle
  // Copy each field from the casted handle into local variables
  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    bit res;
    Object _obj;
    $cast(_obj, rhs);
    res = 	super.do_compare(_obj, comparer) &
    		m_name == _obj.m_name &
    		m_mode == _obj.m_mode &
    		m_bool == _obj.m_bool &
    		m_pkt.do_compare(_obj.m_pkt, comparer);
    
    `uvm_info(get_name(), $sformatf("In Object::do_compare(), res=%0b", res), UVM_LOW)
    return res;
  endfunction
endclass

UVM automation macros were used in the previous example and hence the print method implementation was already done and available to be used. However, when automation is not used, user has to implement either do_print or atleast fill the convert2string function so that contents can be printed. We have chosen to do the latter as evident in the code above. So convert2string function is called in a UVM info statement instead of calling print.

Then compare the variables, copy each variable from obj1 into obj2 and keep comparing until both objects are the same.


class base_test extends uvm_test;
  `uvm_component_utils(base_test)
  function new(string name = "base_test", uvm_component parent=null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    Object obj1 = Object::type_id::create("obj1");
    Object obj2 = Object::type_id::create("obj2");
    obj1.randomize();
    `uvm_info("TEST", $sformatf("Obj1.print: %s", obj1.convert2string()), UVM_LOW)
    obj2.randomize();
    `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    
    _compare(obj1, obj2);
   
      `uvm_info("TEST", "Copy m_bool", UVM_LOW)
    obj2.m_bool = obj1.m_bool;
        `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
      
      `uvm_info("TEST", "Copy m_mode", UVM_LOW)
    obj2.m_mode = obj1.m_mode;
        `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
    
      `uvm_info("TEST", "Copy m_name", UVM_LOW)
    obj2.m_name = obj1.m_name;
        `uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);
      
      `uvm_info("TEST", "Copy m_pkt.m_addr", UVM_LOW)
    obj2.m_pkt.m_addr = obj1.m_pkt.m_addr;
    	`uvm_info("TEST", $sformatf("Obj2.print: %s", obj2.convert2string()), UVM_LOW)
    _compare(obj1, obj2);

  endfunction
  
  function void _compare(Object obj1, obj2);
    if (obj2.compare(obj1))
      `uvm_info("TEST", "obj1 and obj2 are same", UVM_LOW)
    else
      `uvm_info("TEST", "obj1 and obj2 are different", UVM_LOW)
  endfunction
endclass

module tb;
	initial begin
		run_test("base_test");
	end
endmodule
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO testbench.sv(96) @ 0: uvm_test_top [TEST] Obj1.print:  m_name=obj1 m_bool=TRUE m_mode=0x9 m_addr=0x3cb6
UVM_INFO testbench.sv(98) @ 0: uvm_test_top [TEST] Obj2.print:  m_name=obj2 m_bool=FALSE m_mode=0xf m_addr=0x64c1
UVM_INFO testbench.sv(30) @ 0: reporter [m_pkt] In Packet::do_compare(), res=0
UVM_INFO testbench.sv(77) @ 0: reporter [obj2] In Object::do_compare(), res=0
UVM_INFO testbench.sv(128) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(102) @ 0: uvm_test_top [TEST] Copy m_bool
UVM_INFO testbench.sv(104) @ 0: uvm_test_top [TEST] Obj2.print:  m_name=obj2 m_bool=TRUE m_mode=0xf m_addr=0x64c1
UVM_INFO testbench.sv(30) @ 0: reporter [m_pkt] In Packet::do_compare(), res=0
UVM_INFO testbench.sv(77) @ 0: reporter [obj2] In Object::do_compare(), res=0
UVM_INFO testbench.sv(128) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(107) @ 0: uvm_test_top [TEST] Copy m_mode
UVM_INFO testbench.sv(109) @ 0: uvm_test_top [TEST] Obj2.print:  m_name=obj2 m_bool=TRUE m_mode=0x9 m_addr=0x64c1
UVM_INFO testbench.sv(30) @ 0: reporter [m_pkt] In Packet::do_compare(), res=0
UVM_INFO testbench.sv(77) @ 0: reporter [obj2] In Object::do_compare(), res=0
UVM_INFO testbench.sv(128) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(112) @ 0: uvm_test_top [TEST] Copy m_name
UVM_INFO testbench.sv(114) @ 0: uvm_test_top [TEST] Obj2.print:  m_name=obj1 m_bool=TRUE m_mode=0x9 m_addr=0x64c1
UVM_INFO testbench.sv(30) @ 0: reporter [m_pkt] In Packet::do_compare(), res=0
UVM_INFO testbench.sv(77) @ 0: reporter [obj2] In Object::do_compare(), res=0
UVM_INFO testbench.sv(128) @ 0: uvm_test_top [TEST] obj1 and obj2 are different
UVM_INFO testbench.sv(117) @ 0: uvm_test_top [TEST] Copy m_pkt.m_addr
UVM_INFO testbench.sv(119) @ 0: uvm_test_top [TEST] Obj2.print:  m_name=obj1 m_bool=TRUE m_mode=0x9 m_addr=0x3cb6
UVM_INFO testbench.sv(30) @ 0: reporter [m_pkt] In Packet::do_compare(), res=1
UVM_INFO testbench.sv(77) @ 0: reporter [obj2] In Object::do_compare(), res=1
UVM_INFO testbench.sv(126) @ 0: uvm_test_top [TEST] obj1 and obj2 are same
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 

Verilog Single Port RAM

  1. What is a single port RAM ?

What is a single port RAM ?

A single-port RAM (Random Access Memory) is a type of digital memory component that allows data to be read from and written to a single memory location (address) at a time. It is a simple form of memory that provides a basic storage mechanism for digital systems. Each memory location in a single-port RAM can store a fixed number of bits (usually a power of 2, such as 8, 16, 32, etc.).

During a read operation, the data stored at a specific address is retrieved. During a write operation, new data is stored at a specific address, replacing the previous data.

Read more: Verilog Single Port RAM

  1. Configure Components
  2. UVM Testbench Top
  3. UVM Test [uvm_test]
  4. UVM Environment [uvm_env]
  5. UVM Monitor [uvm_monitor]

Page 46 of 63

  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
Interview Questions
  Verilog Interview Set 1
  Verilog Interview Set 2
  Verilog Interview Set 3
  Verilog Interview Set 4
  Verilog Interview Set 5

  SystemVerilog Interview Set 1
  SystemVerilog Interview Set 2
  SystemVerilog Interview Set 3
  SystemVerilog Interview Set 4
  SystemVerilog Interview Set 5

  UVM Interview Set 1
  UVM Interview Set 2
  UVM Interview Set 3
  UVM Interview Set 4
Related Topics
  Digital Fundamentals
  Verilog Tutorial

  Verification
  SystemVerilog Tutorial
  UVM Tutorial
  • Verilog Testbench
  • Verilog Coding Style Effect
  • Verilog Conditional Statements
  • Verilog Interview Set 10
  • Synchronous FIFO
  • SystemVerilog Interview Set 10
  • SystemVerilog Interview Set 9
  • SystemVerilog Interview Set 8
  • SystemVerilog Interview Set 7
  • SystemVerilog Interview Set 6
  • UVM Singleton Object
  • UVM Component [uvm_component]
  • UVM Object [uvm_object]
  • UVM Root [uvm_root]
  • UVM Interview Set 4
© 2015 - 2023 ChipVerify
Terms and Conditions | DMCA.com Protection Status