The testbench described here (done in OVM) has the same functionality or behavior as a testbenches done without OVM, described in the blog post : Simple testbench (done in both System Verilog and Verilog HDL) for a Digital design block (Verilog HDL) verification
Simulate the source code bellow with Cadence tools (using OVM ) with the command:
irun +incdir+<a path to OVM directories>/ovm-2.1.2/src -access +r -gui -ovm +OVM_TESTNAME=test1 top.sv
Source code
Testcase Source code
// the name of the test is test1
// Define a testcase test1 by extending ovm_test class.
class test1 extends ovm_test;
`ovm_component_utils(test1)
////////////////////////////////////////////////////////////////////
// Take the instance of Environment: HINT: it has to be class "Environment" // defined same where in the code
////////////////////////////////////////////////////////////////////////////
Environment t_env ;
//////////////////////////////////////////////////////////////////////////////
// Define the constructor method:
// In this method, construct the environment class object and don't forget to // pass the parent argument(t_env)
//////////////////////////////////////////////////////////////////////////////
function new (string name="test1", ovm_component parent=null);
super.new (name, parent);
t_env = new("t_env",this);
endfunction : new
/////////////////////////////////////////////////////////////////////////////
// run() method is the only task which is time consuming.
// After completing the start_of_simulation() phase , this method is called.
/////////////////////////////////////////////////////////////////////////////
task run ();
// the same simple stimulus from testbench of SV without OVM
// except this time we are directly driving interface: intf_tb signal: read
// interface intf_tb is defined in configuration: cfg.
// HINT: it has to be an defined somewhere else interface: intf_tb and
// configuration: cfg
cfg.intf_tb.address = 0 ;
cfg.intf_tb.data_in = 0 ;
cfg.intf_tb.read_write = 0 ;
cfg.intf_tb.chip_en = 0 ;
repeat(3) begin
#100
cfg.intf_tb.chip_en = 1 ;
cfg.intf_tb.address = $random ;
cfg.intf_tb.data_in = $random ;
cfg.intf_tb.read_write = 1 ;
#100
cfg.intf_tb.read_write = 0 ;
end
#100
cfg.intf_tb.chip_en = 0 ;
#1000;
// To terminate this task, we will use global_stop_request()
global_stop_request();
endtask : run
endclass : test1
Environment.sv
`ifndef GUARD_ENV
`define GUARD_ENV
// Extend ovm_env class to define Environment class
// We will not implement all the ovm_env virtual methods in this phase but will we print messages from these methods
class Environment extends ovm_env;
`ovm_component_utils(Environment)
// Define the constructor
function new(string name , ovm_component parent = null);
super.new(name, parent);
endfunction: new
/////////////////////////////////////////////
// Define build method: just print messages
// Build is the first phase in simulation
//////////////////////////////////////////////
function void build();
super.build();
ovm_report_info(get_full_name(),"START of build ",OVM_LOW);
ovm_report_info(get_full_name(),"END of build ",OVM_LOW);
endfunction
//////////////////////////////////////////////
// Define connect method: just print messages
// This method is called automatically after the build() method is called
//////////////////////////////////////////////
function void connect();
super.connect();
ovm_report_info(get_full_name(),"START of connect ",OVM_LOW);
ovm_report_info(get_full_name(),"END of connect ",OVM_LOW);
endfunction
endclass : Environment
`endif
Configuration.sv
`ifndef GUARD_CONFIGURATION
`define GUARD_CONFIGURATION
class Configuration extends ovm_object;
// Declare All the interfaces which are required in this verification
// environment
// HINT: It has to be defined before interface intf with modport tb
virtual intf.tb intf_tb ;
// construct a new object of configuration class and update all the important // fields and return it.
virtual function ovm_object create(string name="");
Configuration t = new();
t.intf_tb = this.intf_tb ;
return t;
endfunction : create
endclass : Configuration
`endif
Interface ( intf.sv )
`ifndef GUARD_INTERFACE
`define GUARD_INTERFACE
interface intf ( input clk );
logic read_write, chip_en ;
logic[7:0] address, data_in ;
logic[7:0] data_out ;
modport tb (output read_write, chip_en, address, data_in, input data_out);
endinterface :intf
`endif
///////////////////////////////////////////////////////////////////////////////
// top module: integrating Dut and it’s Testbench
// and OVM configuration
///////////////////////////////////////////////////////////////////////////////
`ifndef GUARD_TOP
`define GUARD_TOP
`include "ovm.svh"
module top();
`include "Configuration.sv"
`include "Environment.sv"
`include "test.sv"
bit clk;
initial
begin
#20;
forever #10 clk = ~clk;
end
intf bus_if(clk); //interface instantiation
/////////////////////////////////////////////////////
// Creat Configuration and Strart the run_test//
/////////////////////////////////////////////////////
Configuration cfg;
initial begin
cfg = new();
cfg.intf_tb = bus_if ;
run_test();
end
memory d (
.address ( bus_if.address ), // connect the verilog
.data_in ( bus_if.data_in ), // using interface hierarchy signal name.
.data_out ( bus_if.data_out ),
.read_write ( bus_if.read_write ),
.chip_en ( bus_if.chip_en )
);
endmodule : top
`endif
No comments:
Post a Comment