EDA Playground lets you type in and run HDL code (using a selection of free and commercial simulators and synthesizers).
It's great for learning HDLs, it's great for testing out unfamiliar things and it's great for sharing code.
You can start typing straight away. But to run your code, you'll need to sign or log in. Logging in with a Google account gives you access to all non-commercial simulators and some commercial simulators:
To run commercial simulators, you need to register and log in with a username and password. Registration is free, and only pre-approved email's will have access to the commercial simulators.
* not available.
205
`include "uvm_macros.svh"
package my_pkg;
timeunit 1ns;
timeprecision 1ns;
import uvm_pkg::*;
`define FALSE 0
`define TRUE 1
typedef enum { read, write } dir_t;
// Define a uvm_sequence_item
class my_seq_item extends uvm_sequence_item;
rand bit [31:0] data;
rand bit [9:0] addr;
rand dir_t dir;
function new (string name = "");
super.new(name);
endfunction
function string convert2string;
return $sformatf("addr = %0d, data = %0d, dir = %s", addr, data, dir);
endfunction
// Register sequence item with the factory and add the
// field automation macros
`uvm_object_utils_begin( my_seq_item )
`uvm_field_int( data, UVM_ALL_ON )
`uvm_field_int( addr, UVM_ALL_ON )
`uvm_field_enum( dir_t, dir, UVM_ALL_ON )
`uvm_object_utils_end
endclass : my_seq_item
class my_other_seq extends uvm_sequence #(my_seq_item);
`uvm_object_utils ( my_other_seq )
rand bit ctrl_flag;
function new ( string name = "my_seq");
super.new (name);
endfunction : new
virtual task body();
`uvm_info ( get_name(), "Starting my_other_seq ...", UVM_NONE )
`uvm_do( req )
`uvm_info ( get_name(), $sformatf("ctrl_flag = %0d, addr = %0d, data = %0d", ctrl_flag, req.addr, req.data), UVM_MEDIUM )
endtask : body
endclass : my_other_seq
// Create a sequence that uses the sequence item
class my_seq extends uvm_sequence #(my_seq_item);
`uvm_object_utils ( my_seq )
// my_seq_item req; // built-in sequence item
my_other_seq subseq; // A nested subsequence
// Define a constructor
function new ( string name = "my_seq");
super.new (name);
endfunction : new
// Define the sequence functionality in the body() using macros
virtual task body();
`uvm_info ( get_name(), "Starting the sequence ...", UVM_NONE )
// Use the do action macros on the sequence item
`uvm_do_with( req,{ addr > 10'h0ff; dir == read; } )
// Invoke a nested subsequence
`uvm_do_with( subseq, { ctrl_flag == `TRUE; } )
endtask : body
endclass : my_seq
// Equivalent sequence that uses start_item() and finish_item()
class my_seq_alt extends uvm_sequence #(my_seq_item);
`uvm_object_utils ( my_seq_alt )
`uvm_declare_p_sequencer(uvm_sequencer #(my_seq_item))
my_other_seq subseq; // A nested subsequence
function new ( string name = "my_seq_alt");
super.new (name);
endfunction : new
virtual task body();
`uvm_info ( get_name(), "Starting my_seq_alt ...", UVM_NONE )
// Generate a sequence item
req = my_seq_item::type_id::create("req");
start_item(req);
randomize(req) with { req.addr > 10'h0ff; req.dir == read; };
finish_item(req);
// Invoke a nested subsequence
subseq = my_other_seq::type_id::create("subseq");
subseq.start(p_sequencer);
endtask : body
endclass : my_seq_alt
typedef uvm_sequencer #(my_seq_item) my_sequencer_t;
class my_driver_t extends uvm_driver #(my_seq_item);
`uvm_component_utils(my_driver_t)
virtual dut_if dut_vi;
uvm_event local_ev1;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
if (!uvm_config_db#(uvm_event)::get(this,"","sync_ev1",local_ev1))
`uvm_fatal(get_type_name(), "my_driver's local_ev1 not configured")
endfunction : build_phase
task run_phase(uvm_phase phase);
int i = 0;
forever
begin
// Pull the next stimulus item from the sequencer
//seq_item_port.get(req);
seq_item_port.get_next_item(req);
i++;
// Raise objection - busy
phase.raise_objection(this);
// Wiggle pins of DUT
@(posedge dut_vi.clock);
dut_vi.addr = req.addr;
dut_vi.data = req.data;
`uvm_info(get_type_name(), $sformatf("Driving transaction # %0d", i), UVM_MEDIUM)
`uvm_info(get_type_name(), req.convert2string(), UVM_MEDIUM)
// Drop objection - idle
phase.drop_objection(this);
seq_item_port.item_done();
local_ev1.trigger();
end
endtask: run_phase
endclass: my_driver_t
class my_monitor_t extends uvm_monitor;
`uvm_component_utils(my_monitor_t)
uvm_analysis_port #(my_seq_item) ap;
// Virtual interface variable points to the interface
virtual dut_if mi;
uvm_event local_ev1;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
ap = new("ap", this);
if (!uvm_config_db#(uvm_event)::get(this,"","sync_ev1",local_ev1))
`uvm_fatal(get_type_name(), "my_monitor's local_ev1 not configured")
endfunction : build_phase
task run_phase(uvm_phase phase);
my_seq_item tr;
tr = my_seq_item::type_id::create();
assert (mi != null) else
`uvm_fatal(get_type_name(), "my_monitor virtual interface is null")
forever
begin
@(posedge mi.clock);
local_ev1.wait_ptrigger();
tr.addr = mi.addr;
tr.data = mi.data;
`uvm_info(get_type_name(), tr.convert2string(), UVM_MEDIUM)
// Send the transaction to the analysis port
ap.write(tr);
end
endtask: run_phase
endclass: my_monitor_t
class my_agent_t extends uvm_agent;
`uvm_component_utils(my_agent_t)
my_sequencer_t m_sequencer;
my_driver_t m_driver;
my_monitor_t m_monitor;
uvm_analysis_port #(my_seq_item) ap;
virtual dut_if v_dut_if;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
m_monitor = my_monitor_t::type_id::create("m_monitor", this);
ap = new("ap", this);
if ( get_is_active() == UVM_ACTIVE ) begin
m_sequencer = my_sequencer_t::type_id::create("m_sequencer", this);
m_driver = my_driver_t ::type_id::create("m_driver", this);
end
endfunction: build_phase
virtual function void connect_phase(uvm_phase phase);
m_monitor.ap.connect(ap);
// code to connect monitor’s virtual interface
if (uvm_config_db#(virtual dut_if)::get(this, "", "dut_if", v_dut_if))
begin
m_monitor.mi = v_dut_if;
if ( get_is_active() == UVM_ACTIVE ) begin
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
// code to connect driver’s virtual interface
m_driver.dut_vi = v_dut_if;
end
end
else
`uvm_fatal(get_type_name(), "my_agent's virtual interface not configured")
endfunction: connect_phase
endclass: my_agent_t
class my_subscriber_t extends uvm_subscriber #(my_seq_item);
`uvm_component_utils(my_subscriber_t)
uvm_report_object my_report = new("my_subscriber");
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void write(input my_seq_item t);
// `uvm_info (get_type_name(), t.convert2string(), UVM_MEDIUM) // uvm_test_top.m_env.m_subscriber [my_subscriber_t]
`uvm_info_context(get_type_name(), t.convert2string(), UVM_MEDIUM, my_report) // my_subscriber [my_subscriber_t]
endfunction : write
endclass : my_subscriber_t
class env extends uvm_env;
`uvm_component_utils(env)
my_agent_t m_agent;
my_subscriber_t m_subscriber;
uvm_event sync_ev1;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
m_agent = my_agent_t ::type_id::create("m_agent", this);
m_subscriber = my_subscriber_t::type_id::create("m_subscriber", this);
sync_ev1 = new();
uvm_config_db #(uvm_event)::set(this,"*","sync_ev1",sync_ev1);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
m_agent.ap.connect(m_subscriber.analysis_export);
endfunction: connect_phase
endclass: env
class test extends uvm_test;
`uvm_component_utils(test)
env m_env;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
m_env = env::type_id::create("m_env", this);
endfunction : build_phase
task run_phase(uvm_phase phase);
uvm_objection objection;
uvm_component comp;
my_sequencer_t seqr;
my_seq seq;
seq = my_seq::type_id::create();
// Do not propagate objections up the hierarchy (always done prior to UVM 1.2)
objection = phase.get_objection();
objection.set_propagate_mode(0);
// seq.starting_phase = phase; // UVM-1.1
seq.set_starting_phase(phase); // UVM-1.2
// Raise objection - busy
phase.raise_objection(this);
if( !seq.randomize() )
`uvm_error(get_type_name(), "Randomize failed")
comp = uvm_top.find("*.m_sequencer");
$cast(seqr, comp);
seq.start( seqr );
// Drop objection - idle
phase.drop_objection(this);
endtask: run_phase
endclass: test
endpackage: my_pkg
interface dut_if;
import my_pkg::*;
logic clock;
bit [31:0] data;
bit [9:0] addr;
dir_t dir;
endinterface
module top;
timeunit 1ns;
timeprecision 1ns;
import uvm_pkg::*;
import my_pkg::*;
dut_if dut_if1();
DUT dut1 ( .dif(dut_if1) );
// Clock generator
initial begin
dut_if1.clock = 0;
forever #5 dut_if1.clock = ~dut_if1.clock;
end
initial begin
uvm_config_db #(virtual dut_if)::set(null, "*", "dut_if", dut_if1);
uvm_top.enable_print_topology = 1;
uvm_top.finish_on_completion = 1;
uvm_top.set_timeout(1ms);
uvm_top.run_test("test");
end
initial begin
// Dump waves
$dumpfile("dump.vcd");
$dumpvars(0, top);
end
endmodule : top
module DUT(dut_if dif);
timeunit 1ns;
timeprecision 1ns;
always @(posedge dif.clock)
begin
end
endmodule
Your account is not validated. If you wish to use commercial simulators, you need a validated account.
If you have already registered (or have recently changed your email address), but have not clicked on the link in the email we sent you, please do so. If you cannot find the email, please check your spam/junk folder. Or click here to resend the email.
If you have not already registered for a full account, you can do so by clicking below. You will then need to provide us with some identification information. You may wish to save your code first.
Creating, deleting, and renaming files is not supported during Collaboration. To encourage development of these features for Collaboration, tweet to @EDAPlayground
This playground may have been modified. Please save or copy before starting collaboration.
Your exercise has been submitted.