What is need for OVM?

Hi all,
Im new to OVM. I have very basic questions. I’m trying to understand why do we need methodology if we can develop test bench in pure SV. In other words what are benefits of using OVM over SV to develop test bench ? I would appreciate if you could throw some light here ?

Here are some key benefits I have read but what is the rationality behind it ?

  1. Re-Useability , even system verilog based test bench also can be developed to be reused, How OVM scores over SV here ?
  2. Tests are separated from verification environment , how it is done in OVM and what is the benefit of doing it ?
    3.OVM has standard phases , what is need for having phases ?

A good question indeed and is often asked by first time OVM/UVM user/enthusiast. Perhaps the following blog entry can help you: Verification Course Blog | VeriLog Courses | CVC

Bottomline - O(U)VM is a framework on top of SV, created to make your life easier!

Regards
Ajeetha, CVC

Im new to OVM. I have very basic questions. I’m trying to understand why do we need methodology if we can develop test bench in pure SV. In other words what are benefits of using OVM over SV to develop test bench ? …
Here are some key benefits I have read but what is the rationality behind it ?

  1. Re-Useability , even system verilog based test bench also can be developed to be reused, How OVM scores over SV here ?

The purpose of a methodology in TB designs is to bring uniformity in the approach so as to facilitate the understanding and reuse of the TB. However, you may ask why do we need OVM or UVM; those have for ovm-2.1.2: 236 classes, 106 files, 37,786 lines, 293 printed pages; and for uvm-1-1a: 316 classes, 134 files, 67,298 lines, and 495 printed pages. That is a LOT!!!

A class-based verification offers more benefits than non class-based approaches because you can organize the pieces more easily, and thru polymorphism, you can easily change the operations of the TB to do what is needed; that includes changing the constraints, the tests case, the drivers, the monitors, etc. Thus, at a minimum, one needs to define the transaction class (e.g., READ, ADD, FETCH, etc) that can be randomized with constraints, the sequence class that defines the sequence of transactions, and the driver(s) class to drive the sequence of transactions into the DUT. You can do all of these without UVM or OVM.

What UVM/OVM does, among other things. is provide support to connect these classes thru ports (i.e., library classes) in a proper ordering or phasing. These connections are necessary, just like module ports and variables are connected or accessed. However, with these three classes mentioned above (transaction (or item), driver, sequence), you can skip the “sequencer” class,the “agent” class and the “env” class, and emulate these from within the top level module where the sequence and drivers classes are dynamically instanced, and the virtual interfaces are connected to them. I’ll address the monitor/coverage in a moment. Thus, one can do something like the following; make sure to understand the last initial statement of the top level module.

class dut_mem_item; // extends uvm_sequence_item;
	rand bit rd, wr, rst_n; 
	rand mem_scen_e kind; // memory scenario
        // constraint cst_mem_kind  ….
endclass : dut_mem_item

class dut_mem_driver ; 
	virtual interface dut_mem_if.drvr_if_mp  vif;
        virtual task send_to_dut(input dut_mem_item item);
		case(item.kind)
			MEM_IDLE : begin 
				this.idle_task(item.data, item.address, item.idle_cycles); 
			end
                                    // .. 
		endcase 
	endtask : send_to_dut
  // ...
        virtual task write_task(logic [31:0] data, address);
		vif.driver_cb.rst_n <= 1'b1;
		this.vif.driver_cb.wr   <= 1'b1;
		//...
		@ (this.vif.driver_cb);
		wait(this.vif.driver_cb.hold==1'b0);
		this.vif.driver_cb.wr <= 1'b0;
		//..
	endtask : write_task
endclass : dut_mem_driver 

class dut_mem_sequence; 
	dut_mem_driver drvr;
	dut_mem_item  item; 
	virtual task body();
		item = new(); // dut_item::type_id::create("req");  
		if (!item.randomize()) `uvm_error("MYERR", "This is a randomize error");
		item.kind=MEM_RESET; // reset DUT
		drvr.send_to_dut(item);

		// initialize DUT memory 
		for (int i=0; i<20; i++) begin
			if (!item.randomize()) `uvm_error("MYERR", "This is a randomize error");
			item.kind=MEM_WRITE;
			item.address=i; 
			drvr.send_to_dut(item);
		end  

		forever begin // do reads and writes
			if (!item.randomize()) `uvm_error("MYERR", "This is a randomize error");
			drvr.send_to_dut(item);
		end 
	endtask: body
endclass: dut_mem_sequence

//****************
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "dut_mem_pkg.sv"
import dut_mem_pkg::*;
`include "dut_mem.sv"
`include "dut_mem_prop.sv"
`include "dut_mem_item.sv"
`include "dut_mem_if.sv"
`include "dut_mem_driver.sv"
`include "dut_mem_sequence.sv"

module top_dut_mem;
	logic clk =1'b0, rd, wr, rst_n; 
	 //...
	// Class objects
	dut_mem_driver  tp_drvr;
	dut_mem_sequence tp_seq;
	dut_mem_if   dut_mem_if1(.clk(clk));
	dut_mem  (
		.clk(clk), 
		.rd(dut_mem_if1.rd),  // ...
		.data(dut_mem_if1.data)
	); 
	
        bind dut_mem0 dut_mem_prop(...);  
	initial forever #10 clk=!clk;

	initial begin
		tp_seq=new();    // seuence 
		tp_drvr=new();   // driver 
		tp_drvr.vif=dut_mem_if1;  // connect of the interface
		tp_seq.drvr=tp_drvr;   // connect of the driver in the sequence 
                                       // (sequencer job emulation)
		tp_seq.body(); // start the sequence
	end
endmodule

What about the monitor and coverage? UVM suggests the use of classes with ports to transfer info between classes. I think that the monitor function can also be done in a module connected to the interfaces, and if needed data from the class transferred to the interfaces.

OK, after reading this, you may wonder if I support UVM at all. Actually, I do. I see the above approach as a first step to explain the testbench concepts. For simple designs, that would be sufficient. with no mention of the UVM lib. However,.in defining those classes, it would not hurt to add the UVM base classes and few macros (e.g., class dut_mem_driver extends uvm_driver#(dut_mem_item, dut_mem_item);). That would facilitate the growth to a full UVM basis.

  1. Tests are separated from verification environment , how it is done in OVM and what is the benefit of doing it ?
    3.OVM has standard phases , what is need for having phases ?

The separation of tests from the environment makes things clearer.
Ben Cohen SystemVerilog.us

In reply to ben@SystemVerilog.us:

Thanks a lot Ben. I understand class based verification has advantage over non class based approach.class based approach gives OOPS benefit. The original question I have was that what is the need for methodology when we can develop class based testbench using simple system verilog. What is the benefit we get by building testbench using methodology ?

The main reason for using OVM is an economy of scale.

You could put together a SV class based testbench architecture yourself, but:

  1. It would require you to invest time and resources in doing so, and then maintaining it
  2. Your verification components would be unusable by other teams within your company (because if you can create a testbench architecture, why wouldn’t they do so as well)
  3. You would be unable to use verification components and solutions from outside your company
  4. You would have to train every new engineer joining your company on the testbench architecture

You can argue about whether the OVM is the best technical solution, but it has achieved an economy of scale through inter-operability, allowing people to share verification components and have a common language.

If you are starting from scratch, I would highly recommend that you start with the UVM since that is an extension of OVM and has an even greater economy of scale since it has superceded the UVM. It is also where the investment in EDA tools and VIP is going.

In reply to mperyer:

Thanks. You answer clarified what I’m exactly looking for and has given the rationality behind need for OVM. Thanks once again.