blob: 1352aa68eacebd07c6b3cc389459c67feab37497 [file] [log] [blame]
//
// This example illustrates how to implement a unidirectional sequence-driver
// use model. The example used is an ADPCM like undirectional comms protocol.
// There is no response, so there is no DUT, just an interface ---->
//
// "Open EPWave after run" to see the signal traffic being sent.
//
// To resolve unknown package: `include "uvm_pkg.sv"
package adpcm_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
// Sequence item contains the data and a delay before
// sending the data frame
//
class adpcm_seq_item extends uvm_sequence_item;
rand logic[31:0] data;
rand int delay;
constraint c_delay { delay > 0; delay <= 20; }
`uvm_object_utils(adpcm_seq_item)
function new(string name = "adpcm_seq_item");
super.new(name);
endfunction
function void do_copy(uvm_object rhs);
adpcm_seq_item rhs_;
if(!$cast(rhs_, rhs)) begin
uvm_report_error("do_copy", "cast failed, check types");
end
data = rhs_.data;
delay = rhs_.delay;
endfunction: do_copy
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
adpcm_seq_item rhs_;
do_compare = $cast(rhs_, rhs) &&
super.do_compare(rhs, comparer) &&
data == rhs_.data &&
delay == rhs_.delay;
endfunction: do_compare
function string convert2string();
return $sformatf(" data:\t%0h\n delay:\t%0d", data, delay);
endfunction: convert2string
function void do_print(uvm_printer printer);
if(printer.knobs.sprint == 0) begin
$display(convert2string());
end
else begin
printer.m_string = convert2string();
end
endfunction: do_print
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
`uvm_record_field("data", data);
`uvm_record_field("delay", delay);
endfunction: do_record
endclass: adpcm_seq_item
// Unidirectional driver uses the get_next_item(), item_done() approach
//
class adpcm_driver extends uvm_driver #(adpcm_seq_item);
`uvm_component_utils(adpcm_driver)
adpcm_seq_item req;
virtual adpcm_if.mon_mp ADPCM;
function new(string name = "adpcm_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
task run_phase(uvm_phase phase);
int top_idx = 0;
// Default conditions:
ADPCM.cb.frame <= 0;
ADPCM.cb.data <= 0;
fork
forever
begin
seq_item_port.get_next_item(req); // Gets the sequence_item from the sequence
repeat(req.delay) begin // Delay between packets
@(ADPCM.cb);
end
ADPCM.cb.frame <= 1; // Start of frame
for(int i = 0; i < 8; i++) begin // Send nibbles
@(ADPCM.cb);
ADPCM.cb.data <= req.data[3:0];
req.data = req.data >> 4;
end
ADPCM.cb.frame <= 0; // End of frame
seq_item_port.item_done(); // Indicates that the sequence_item has been consumed
end
forever begin
@(ADPCM.cb);
if (ADPCM.cb.frame === 1'b1) begin
$display($time);
end
end
join_none
endtask: run_phase
endclass: adpcm_driver
class adpcm_sequencer extends uvm_sequencer #(adpcm_seq_item);
`uvm_component_utils(adpcm_sequencer)
function new(string name = "adpcm_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass: adpcm_sequencer
// Sequence part of the use model
//
// The sequence randomizes 10 ADPCM data packets and sends
// them
//
class adpcm_tx_seq extends uvm_sequence #(adpcm_seq_item);
`uvm_object_utils(adpcm_tx_seq)
// ADPCM sequence_item
adpcm_seq_item req;
// Controls the number of request sequence items sent
rand int no_reqs = 10;
function new(string name = "adpcm_tx_seq");
super.new(name);
// do_not_randomize = 1'b1; // Required for ModelSim
endfunction
task body;
req = adpcm_seq_item::type_id::create("req");
for(int i = 0; i < no_reqs; i++) begin
start_item(req);
// req.randomize();
// For ModelSim, use $urandom to achieve randomization for your request
req.delay = $urandom_range(1, 20);
req.data = $urandom();
finish_item(req);
`uvm_info("ADPCM_TX_SEQ_BODY", $sformatf("Transmitted frame %0d", i), UVM_LOW)
end
endtask: body
endclass: adpcm_tx_seq
// Test instantiates, builds and connects the driver and the sequencer
// then runs the sequence
//
class adpcm_test extends uvm_test;
`uvm_component_utils(adpcm_test)
adpcm_tx_seq test_seq;
adpcm_driver m_driver;
adpcm_sequencer m_sequencer;
function new(string name = "adpcm_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
m_driver = adpcm_driver::type_id::create("m_driver", this);
m_sequencer = adpcm_sequencer::type_id::create("m_sequencer", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
if (!uvm_config_db #(virtual adpcm_if.mon_mp)::get(this, "",
"ADPCM_vif", m_driver.ADPCM)) begin
`uvm_error("connect", "ADPCM_vif not found")
end
endfunction: connect_phase
task run_phase(uvm_phase phase);
test_seq = adpcm_tx_seq::type_id::create("test_seq");
phase.raise_objection(this, "starting test_seq");
test_seq.start(m_sequencer);
phase.drop_objection(this, "finished test_seq");
endtask: run_phase
endclass: adpcm_test
endpackage: adpcm_pkg
module top_tb;
import uvm_pkg::*;
import adpcm_pkg::*;
adpcm_if ADPCM();
// Free running clock
initial
begin
ADPCM.clk = 0;
forever begin
#10 ADPCM.clk = ~ADPCM.clk;
end
end
// UVM start up:
initial
begin
uvm_config_db #(virtual adpcm_if.mon_mp)::set(null, "uvm_test_top", "ADPCM_vif" , ADPCM);
run_test("adpcm_test");
end
// Dump waves
initial $dumpvars(0, top_tb);
endmodule: top_tb
// This file has been modified from the original.
// Attribution and license:
//----------------------------------------------------------
// Copyright 2010 Mentor Graphics Corporation
// All Rights Reserved Worldwide
//
// Licensed under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in
// writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See
// the License for the specific language governing
// permissions and limitations under the License.
//----------------------------------------------------------