init
This commit is contained in:
117
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_config.sv
Normal file
117
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_config.sv
Normal file
@@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_config.sv
|
||||
|
||||
DESCRIPTION contains main and default configurations
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_CONFIG_SV
|
||||
`define APB_CONFIG_SV
|
||||
|
||||
/**
|
||||
* Class: apb_config
|
||||
*/
|
||||
class apb_config extends uvm_object;
|
||||
|
||||
// number of master and slave agents
|
||||
int unsigned num_of_slaves; // total number of slaves (DUT or agents)
|
||||
int unsigned num_of_slave_agents; // number of UVM slave agents
|
||||
bit has_master;
|
||||
|
||||
// configurations for every agent
|
||||
apb_slave_config slave_cfg_queue[$];
|
||||
apb_master_config master_cfg;
|
||||
|
||||
// control
|
||||
bit has_pslverr = 1; // APB peripherals are not required to support the PSLVERR pin
|
||||
bit has_checks = 1;
|
||||
bit has_coverage = 1;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils_begin(apb_config)
|
||||
`uvm_field_int(num_of_slaves, UVM_DEFAULT)
|
||||
`uvm_field_int(num_of_slave_agents, UVM_DEFAULT)
|
||||
`uvm_field_int(has_master, UVM_DEFAULT)
|
||||
`uvm_field_queue_object(slave_cfg_queue, UVM_DEFAULT)
|
||||
`uvm_field_object(master_cfg, UVM_DEFAULT)
|
||||
`uvm_field_int(has_pslverr, UVM_DEFAULT)
|
||||
`uvm_field_int(has_checks, UVM_DEFAULT)
|
||||
`uvm_field_int(has_coverage, UVM_DEFAULT)
|
||||
`uvm_object_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_config");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// additional class methods
|
||||
extern function void add_slave( bit [ADDR_WIDTH - 1 : 0] start_addr,
|
||||
bit [ADDR_WIDTH - 1 : 0] end_addr,
|
||||
int unsigned psel_indx,
|
||||
bit create_agent = 1,
|
||||
uvm_active_passive_enum is_active = UVM_ACTIVE);
|
||||
extern function void add_master(uvm_active_passive_enum is_active = UVM_ACTIVE);
|
||||
extern function int unsigned get_slave_psel_by_addr(bit [ADDR_WIDTH - 1 : 0] addr);
|
||||
|
||||
endclass : apb_config
|
||||
|
||||
// creates and configures a slave agent config and adds to a queue
|
||||
function void apb_config::add_slave(bit [ADDR_WIDTH - 1 : 0] start_addr,
|
||||
bit [ADDR_WIDTH - 1 : 0] end_addr,
|
||||
int unsigned psel_indx,
|
||||
bit create_agent = 1,
|
||||
uvm_active_passive_enum is_active = UVM_ACTIVE);
|
||||
apb_slave_config tmp_cfg;
|
||||
++num_of_slaves;
|
||||
if(create_agent == 1) ++num_of_slave_agents;
|
||||
tmp_cfg = apb_slave_config::type_id::create("slave_cfg");
|
||||
tmp_cfg.start_address = start_addr;
|
||||
tmp_cfg.end_address = end_addr;
|
||||
tmp_cfg.psel_index = psel_indx;
|
||||
tmp_cfg.create_agent = create_agent;
|
||||
tmp_cfg.is_active = is_active;
|
||||
tmp_cfg.has_checks = has_checks;
|
||||
tmp_cfg.has_coverage = has_coverage;
|
||||
slave_cfg_queue.push_back(tmp_cfg);
|
||||
endfunction : add_slave
|
||||
|
||||
// creates and configures a master agent configuration
|
||||
function void apb_config::add_master(uvm_active_passive_enum is_active = UVM_ACTIVE);
|
||||
has_master = 1;
|
||||
master_cfg = apb_master_config::type_id::create("master_cfg");
|
||||
master_cfg.is_active = is_active;
|
||||
master_cfg.has_checks = has_checks;
|
||||
master_cfg.has_coverage = has_coverage;
|
||||
endfunction : add_master
|
||||
|
||||
// returns the slave psel index
|
||||
function int unsigned apb_config::get_slave_psel_by_addr(bit [ADDR_WIDTH - 1 : 0] addr);
|
||||
for (int i = 0; i < slave_cfg_queue.size(); i++)
|
||||
if(slave_cfg_queue[i].check_address_range(addr)) begin
|
||||
return slave_cfg_queue[i].psel_index;
|
||||
end
|
||||
return 0;
|
||||
endfunction : get_slave_psel_by_addr
|
||||
|
||||
/**
|
||||
* Class: default_apb_config
|
||||
*
|
||||
* Description: default configuration - one master, no slaves
|
||||
*/
|
||||
class default_apb_config extends apb_config;
|
||||
|
||||
`uvm_object_utils(default_apb_config)
|
||||
|
||||
function new(string name = "default_apb_config");
|
||||
super.new(name);
|
||||
add_master(UVM_ACTIVE);
|
||||
add_slave(0, 2**ADDR_WIDTH - 1, 1, 1, UVM_ACTIVE); // TODO : remove after debug
|
||||
endfunction : new
|
||||
|
||||
endclass : default_apb_config
|
||||
|
||||
`endif
|
||||
75
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_env.sv
Normal file
75
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_env.sv
Normal file
@@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_env.sv
|
||||
|
||||
DESCRIPTION environment containing the master and slave agents
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_ENV_SV
|
||||
`define APB_ENV_SV
|
||||
|
||||
/**
|
||||
* Class: apb_env
|
||||
*/
|
||||
class apb_env extends uvm_env;
|
||||
|
||||
apb_slave_agent slaves[]; // can have more than one slave
|
||||
apb_master_agent master; // one master
|
||||
|
||||
apb_config cfg; // uvc configuration
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_env)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_env", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
|
||||
// get configuration from db or use default configuration if none is set
|
||||
if(!uvm_config_db#(apb_config)::get(this, "", "apb_config", cfg)) begin
|
||||
`uvm_info("NOCONFIG", "Using default_apb_config", UVM_LOW)
|
||||
apb_config::type_id::set_type_override(default_apb_config::get_type(), 1);
|
||||
cfg = apb_config::type_id::create("cfg");
|
||||
end
|
||||
|
||||
// set the master configuration
|
||||
if(cfg.has_master) begin
|
||||
uvm_config_db#(apb_config)::set(this, "master*", "apb_config", cfg);
|
||||
end
|
||||
// set the slave configurations
|
||||
foreach(cfg.slave_cfg_queue[i]) begin
|
||||
string sname;
|
||||
sname = $sformatf("slave[%0d]*", i);
|
||||
uvm_config_db#(apb_slave_config)::set(this, sname, "apb_slave_config", cfg.slave_cfg_queue[i]);
|
||||
end
|
||||
|
||||
// create agents
|
||||
if(cfg.has_master) begin
|
||||
master = apb_master_agent::type_id::create("master",this);
|
||||
end
|
||||
if(cfg.num_of_slave_agents != 0) begin
|
||||
slaves = new[cfg.num_of_slave_agents];
|
||||
for(int i = 0; i < cfg.slave_cfg_queue.size(); i++) begin
|
||||
if(cfg.slave_cfg_queue[i].create_agent == 1) begin
|
||||
slaves[i] = apb_slave_agent::type_id::create($sformatf("slave[%0d]", i), this);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endfunction : build_phase
|
||||
|
||||
endclass : apb_env
|
||||
|
||||
`endif
|
||||
|
||||
48
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_if.sv
Normal file
48
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_if.sv
Normal file
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_if.sv
|
||||
|
||||
DESCRIPTION apb interface
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_IF_SV
|
||||
`define APB_IF_SV
|
||||
|
||||
/**
|
||||
* Interface: apb_if
|
||||
*/
|
||||
interface apb_if (input logic pclk, input logic presetn);
|
||||
|
||||
parameter ADDR_WIDTH = 32; // up to 32 bits
|
||||
parameter RDATA_WIDTH = 32; // up to 32 bits
|
||||
parameter WDATA_WIDTH = 32; // up to 32 bits
|
||||
parameter SLV_NUM = 15;
|
||||
|
||||
// source is master
|
||||
logic [ADDR_WIDTH - 1 : 0] paddr; // the APB address bus
|
||||
logic [SLV_NUM - 1 : 0] psel; // select; the slave device is selected
|
||||
// and that a data transfer is required
|
||||
logic penable; // enable; the second and subsequent
|
||||
// cycles of an APB transfer
|
||||
logic pwrite; // direction
|
||||
logic [WDATA_WIDTH - 1 : 0] pwdata; // write data
|
||||
|
||||
// source is slave
|
||||
logic pready; // ready; the slave uses this signal to
|
||||
// extend an APB transfer
|
||||
logic [RDATA_WIDTH - 1 : 0] prdata; // read data
|
||||
logic pslverr; // indicates a transfer failure
|
||||
|
||||
// control
|
||||
bit has_checks = 1;
|
||||
bit has_coverage = 1;
|
||||
|
||||
// TODO : coverage and assertions go here...
|
||||
|
||||
endinterface : apb_if
|
||||
|
||||
`endif
|
||||
83
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_pkg.sv
Normal file
83
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_pkg.sv
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_pkg.sv
|
||||
|
||||
DESCRIPTION package containing all parameters and includes
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_PKG_SV
|
||||
`define APB_PKG_SV
|
||||
|
||||
/**
|
||||
* Package: apb_pkg
|
||||
*/
|
||||
package apb_pkg;
|
||||
|
||||
parameter ADDR_WIDTH = 32; // up to 32 bits
|
||||
parameter RDATA_WIDTH = 32; // up to 32 bits
|
||||
parameter WDATA_WIDTH = 32; // up to 32 bits
|
||||
parameter SLV_NUM = 15; // up to 15 slaves
|
||||
|
||||
// ==================== OBJECTS ==============================
|
||||
typedef class apb_transaction;
|
||||
typedef class apb_master_config;
|
||||
typedef class apb_slave_config;
|
||||
typedef class apb_config;
|
||||
// ==========================================================
|
||||
|
||||
// ==================== SLAVE ===============================
|
||||
typedef class apb_slave_driver;
|
||||
typedef class apb_slave_sequencer;
|
||||
typedef class apb_slave_monitor;
|
||||
typedef class apb_slave_agent;
|
||||
// ==========================================================
|
||||
|
||||
// ==================== MASTER ==============================
|
||||
typedef class apb_master_driver;
|
||||
typedef class apb_master_sequencer;
|
||||
typedef class apb_master_monitor;
|
||||
typedef class apb_master_agent;
|
||||
// ==========================================================
|
||||
|
||||
// ==================== TOP ==================================
|
||||
typedef class apb_env;
|
||||
// ==========================================================
|
||||
|
||||
import uvm_pkg::*;
|
||||
`include "uvm_macros.svh"
|
||||
|
||||
`include "apb_types.sv"
|
||||
`include "apb_config.sv"
|
||||
|
||||
// ==================== MASTER ==============================
|
||||
`include "master/sequences/apb_master_seq_lib.sv"
|
||||
`include "master/apb_master_config.sv"
|
||||
`include "master/apb_master_driver.sv"
|
||||
`include "master/apb_master_monitor.sv"
|
||||
`include "master/apb_master_sequencer.sv"
|
||||
`include "master/apb_master_agent.sv"
|
||||
// ==========================================================
|
||||
|
||||
// ==================== SLAVE ===============================
|
||||
`include "slave/sequences/apb_slave_seq_lib.sv"
|
||||
`include "slave/apb_slave_config.sv"
|
||||
`include "slave/apb_slave_driver.sv"
|
||||
`include "slave/apb_slave_monitor.sv"
|
||||
`include "slave/apb_slave_sequencer.sv"
|
||||
`include "slave/apb_slave_agent.sv"
|
||||
// ==========================================================
|
||||
|
||||
// ==================== TOP =================================
|
||||
`include "apb_env.sv"
|
||||
`include "apb_transaction.sv"
|
||||
// ==========================================================
|
||||
|
||||
endpackage : apb_pkg
|
||||
|
||||
`include "apb_if.sv"
|
||||
|
||||
`endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_transaction.sv
|
||||
|
||||
DESCRIPTION sequence item
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_TRANSACTION_SV
|
||||
`define APB_TRANSACTION_SV
|
||||
|
||||
/**
|
||||
* Class: apb_transaction
|
||||
*/
|
||||
class apb_transaction extends uvm_sequence_item;
|
||||
|
||||
// fields
|
||||
rand bit [ADDR_WIDTH - 1 : 0] addr;
|
||||
rand apb_direction_enum dir;
|
||||
rand bit [RDATA_WIDTH - 1 : 0] rdata;
|
||||
rand bit [WDATA_WIDTH - 1 : 0] wdata;
|
||||
rand int unsigned delay = 0;
|
||||
bit error;
|
||||
|
||||
// constraints
|
||||
constraint c_delay { delay <= 10 ; }
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils_begin(apb_transaction)
|
||||
`uvm_field_int(addr, UVM_DEFAULT)
|
||||
`uvm_field_enum(apb_direction_enum, dir, UVM_DEFAULT)
|
||||
`uvm_field_int(rdata, UVM_DEFAULT)
|
||||
`uvm_field_int(wdata, UVM_DEFAULT)
|
||||
`uvm_field_int(delay, UVM_DEFAULT)
|
||||
`uvm_field_int(error, UVM_DEFAULT)
|
||||
`uvm_object_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_transaction");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
endclass : apb_transaction
|
||||
|
||||
`endif
|
||||
22
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_types.sv
Normal file
22
code/Vezba 13 - prateci materijal/apb_uvc/sv/apb_types.sv
Normal file
@@ -0,0 +1,22 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_types.sv
|
||||
|
||||
DESCRIPTION contains all typedef-s used in project
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_TYPES_SV
|
||||
`define APB_TYPES_SV
|
||||
|
||||
// APB direction - read or write
|
||||
typedef enum {
|
||||
APB_READ = 0,
|
||||
APB_WRITE = 1
|
||||
} apb_direction_enum;
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_agent.sv
|
||||
|
||||
DESCRIPTION master agent
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_AGENT_SV
|
||||
`define APB_MASTER_AGENT_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_agent
|
||||
*/
|
||||
class apb_master_agent extends uvm_agent;
|
||||
|
||||
// configuration object
|
||||
apb_config cfg;
|
||||
|
||||
// components
|
||||
apb_master_driver drv;
|
||||
apb_master_sequencer seqr;
|
||||
apb_master_monitor mon;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_master_agent)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_agent", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_config)::get(this, "", "apb_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
|
||||
// create driver and sequencer if agent is active
|
||||
if(cfg.master_cfg.is_active == UVM_ACTIVE) begin
|
||||
seqr = apb_master_sequencer::type_id::create("seqr", this);
|
||||
drv = apb_master_driver::type_id::create("drv", this);
|
||||
end
|
||||
// always create monitor
|
||||
mon = apb_master_monitor::type_id::create("mon", this);
|
||||
endfunction : build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
function void connect_phase(uvm_phase phase);
|
||||
super.connect_phase(phase);
|
||||
// connect driver and sequencer if agent is active
|
||||
if(cfg.master_cfg.is_active == UVM_ACTIVE) begin
|
||||
drv.seq_item_port.connect(seqr.seq_item_export);
|
||||
end
|
||||
endfunction : connect_phase
|
||||
|
||||
endclass : apb_master_agent
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_config.sv
|
||||
|
||||
DESCRIPTION master configuration object
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_CONFIG_SV
|
||||
`define APB_MASTER_CONFIG_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_config
|
||||
*/
|
||||
class apb_master_config extends uvm_object;
|
||||
|
||||
// is agent active or passive
|
||||
uvm_active_passive_enum is_active = UVM_ACTIVE;
|
||||
// checks and coverage control
|
||||
bit has_checks = 1;
|
||||
bit has_coverage = 1;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils_begin(apb_master_config)
|
||||
`uvm_field_enum(uvm_active_passive_enum, is_active, UVM_DEFAULT)
|
||||
`uvm_field_int(has_checks, UVM_DEFAULT)
|
||||
`uvm_field_int(has_coverage, UVM_DEFAULT)
|
||||
`uvm_object_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_config");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
endclass : apb_master_config
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_driver.sv
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_DRIVER_SV
|
||||
`define APB_MASTER_DRIVER_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_driver
|
||||
*/
|
||||
class apb_master_driver extends uvm_driver #(apb_transaction, apb_transaction);
|
||||
|
||||
// apb virtual interface
|
||||
virtual apb_if vif;
|
||||
|
||||
// configuration
|
||||
apb_config cfg;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_master_driver)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_driver", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
virtual function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_config)::get(this, "*", "apb_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
endfunction: build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
virtual function void connect_phase(uvm_phase phase);
|
||||
super.connect_phase(phase);
|
||||
// get interface from db
|
||||
if(!uvm_config_db#(virtual apb_if)::get(this, "", "apb_if", vif))
|
||||
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
|
||||
endfunction : connect_phase
|
||||
|
||||
// additional class methods
|
||||
extern virtual task run_phase(uvm_phase phase);
|
||||
extern virtual task get_and_drive();
|
||||
extern virtual task reset();
|
||||
extern virtual task drive_tr (apb_transaction tr);
|
||||
|
||||
endclass : apb_master_driver
|
||||
|
||||
// UVM run_phase
|
||||
task apb_master_driver::run_phase(uvm_phase phase);
|
||||
reset(); // init.
|
||||
forever begin
|
||||
fork
|
||||
get_and_drive(); // thread killed at reset
|
||||
@(negedge vif.presetn); // reset is active low
|
||||
join_any
|
||||
disable fork;
|
||||
reset();
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
// reset signals
|
||||
task apb_master_driver::reset();
|
||||
`uvm_info(get_type_name(), "Reset observed", UVM_MEDIUM)
|
||||
vif.paddr <= {ADDR_WIDTH {1'b0}};
|
||||
vif.pwdata <= {WDATA_WIDTH {1'b0}};
|
||||
vif.pwrite <= 1'b0;
|
||||
vif.psel <= {SLV_NUM {1'b0}};
|
||||
vif.penable <= 1'b0;
|
||||
@(posedge vif.presetn); // reset dropped
|
||||
endtask : reset
|
||||
|
||||
// sequencer/driver handshake
|
||||
task apb_master_driver::get_and_drive();
|
||||
forever begin
|
||||
seq_item_port.get_next_item(req);
|
||||
drive_tr(req);
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
endtask : get_and_drive
|
||||
|
||||
// drive transaction
|
||||
task apb_master_driver::drive_tr (apb_transaction tr);
|
||||
int unsigned slave_index;
|
||||
|
||||
// delay
|
||||
@(posedge vif.pclk);
|
||||
if (tr.delay > 0) begin
|
||||
repeat(tr.delay) @(posedge vif.pclk);
|
||||
end
|
||||
|
||||
// address phase
|
||||
slave_index = cfg.get_slave_psel_by_addr(tr.addr);
|
||||
if(slave_index == 0) begin
|
||||
`uvm_warning(get_type_name(), "No slave with choosed address")
|
||||
return;
|
||||
end
|
||||
vif.paddr <= tr.addr;
|
||||
vif.psel <= (1 << (slave_index - 1));
|
||||
vif.penable <= 0;
|
||||
vif.pwrite <= apb_direction_enum'(tr.dir);
|
||||
if (tr.dir == APB_WRITE) begin
|
||||
vif.pwdata <= tr.wdata;
|
||||
end
|
||||
|
||||
// data phase
|
||||
@(posedge vif.pclk);
|
||||
vif.penable <= 1;
|
||||
@(posedge vif.pclk iff vif.pready);
|
||||
tr.error = vif.pslverr;
|
||||
if (tr.dir == APB_READ) begin
|
||||
tr.rdata = vif.prdata;
|
||||
end
|
||||
vif.penable <= 0;
|
||||
vif.psel <= 0;
|
||||
|
||||
`uvm_info(get_type_name(), $sformatf("APB Finished Driving tr \n%s", tr.sprint()), UVM_HIGH)
|
||||
endtask : drive_tr
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_monitor.sv
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_MONITOR_SV
|
||||
`define APB_MASTER_MONITOR_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_monitor
|
||||
*/
|
||||
class apb_master_monitor extends uvm_monitor;
|
||||
|
||||
// apb virtual interface
|
||||
virtual apb_if vif;
|
||||
|
||||
// configuration
|
||||
apb_config cfg;
|
||||
|
||||
// TLM - from monitor to other components
|
||||
uvm_analysis_port #(apb_transaction) item_collected_port;
|
||||
|
||||
// keep track of number of transactions
|
||||
int unsigned num_transactions = 0;
|
||||
|
||||
// current transaction
|
||||
apb_transaction tr_collected;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_master_monitor)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// coverage
|
||||
covergroup cg_apb_master;
|
||||
// cover direction - read or write
|
||||
cp_direction : coverpoint tr_collected.dir {
|
||||
bins write = {APB_WRITE};
|
||||
bins read = {APB_READ};
|
||||
}
|
||||
// cover delay - zero or more
|
||||
cp_delay : coverpoint tr_collected.delay {
|
||||
bins zero = {0};
|
||||
bins other = default;
|
||||
}
|
||||
// TODO : add others
|
||||
endgroup : cg_apb_master;
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_monitor", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
item_collected_port = new("item_collected_port", this);
|
||||
cg_apb_master = new();
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_config)::get(this, "", "apb_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
endfunction: build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
function void connect_phase(uvm_phase phase);
|
||||
super.connect_phase(phase);
|
||||
// get interface from db
|
||||
if(!uvm_config_db#(virtual apb_if)::get(this, "", "apb_if", vif))
|
||||
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
|
||||
endfunction : connect_phase
|
||||
|
||||
// additional class methods
|
||||
extern virtual task run_phase(uvm_phase phase);
|
||||
extern virtual task collect_transactions();
|
||||
extern virtual function void report_phase(uvm_phase phase);
|
||||
|
||||
endclass : apb_master_monitor
|
||||
|
||||
// UVM run_phase
|
||||
task apb_master_monitor::run_phase(uvm_phase phase);
|
||||
forever begin
|
||||
@(posedge vif.presetn); // reset dropped
|
||||
`uvm_info(get_type_name(), "Reset dropped", UVM_MEDIUM)
|
||||
|
||||
fork
|
||||
collect_transactions(); // thread killed at reset
|
||||
@(negedge vif.presetn); // reset is active low
|
||||
join_any
|
||||
disable fork;
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
// monitor apb interface and collect transactions
|
||||
task apb_master_monitor::collect_transactions();
|
||||
forever begin
|
||||
tr_collected = apb_transaction::type_id::create("tr_collected");
|
||||
|
||||
// wait for valid transaction
|
||||
@(posedge vif.pclk iff (vif.psel != 0));
|
||||
tr_collected.addr = vif.paddr;
|
||||
tr_collected.dir = apb_direction_enum'(vif.pwrite);
|
||||
if(tr_collected.dir == APB_WRITE)
|
||||
tr_collected.wdata = vif.pwdata;
|
||||
|
||||
@(posedge vif.pclk); // enable
|
||||
@(posedge vif.pclk); // ready
|
||||
while (vif.pready !== 1'b1) begin
|
||||
@(posedge vif.pclk);
|
||||
tr_collected.delay++;
|
||||
end
|
||||
if(tr_collected.dir == APB_READ) begin
|
||||
tr_collected.rdata = vif.prdata;
|
||||
tr_collected.error = vif.pslverr;
|
||||
end
|
||||
|
||||
item_collected_port.write(tr_collected); // TLM
|
||||
// collect coverage if enabled
|
||||
if(cfg.has_coverage == 1) begin
|
||||
cg_apb_master.sample();
|
||||
end
|
||||
`uvm_info(get_type_name(), $sformatf("Tr collected :\n%s", tr_collected.sprint()), UVM_MEDIUM)
|
||||
num_transactions++;
|
||||
end // forever
|
||||
endtask : collect_transactions
|
||||
|
||||
// UVM report_phase
|
||||
function void apb_master_monitor::report_phase(uvm_phase phase);
|
||||
// final report
|
||||
`uvm_info(get_type_name(), $sformatf("Report: APB monitor collected %0d transfers", num_transactions), UVM_LOW);
|
||||
endfunction : report_phase
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_sequencer.sv
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_SEQUENCER_SV
|
||||
`define APB_MASTER_SEQUENCER_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_sequencer
|
||||
*/
|
||||
class apb_master_sequencer extends uvm_sequencer #(apb_transaction, apb_transaction);
|
||||
|
||||
// configuration
|
||||
apb_config cfg;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_master_sequencer)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_sequencer", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_config)::get(this, "", "apb_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
endfunction: build_phase
|
||||
|
||||
endclass : apb_master_sequencer
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_base_seq.sv
|
||||
|
||||
DESCRIPTION base sequence to be extended by other sequences
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_BASE_SEQ_SV
|
||||
`define APB_MASTER_BASE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_base_seq
|
||||
*/
|
||||
class apb_master_base_seq extends uvm_sequence #(apb_transaction, apb_transaction);
|
||||
|
||||
// p_sequencer for APB master sequences
|
||||
`uvm_declare_p_sequencer(apb_master_sequencer)
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_base_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_base_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
endclass : apb_master_base_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_read_after_write_seq.sv
|
||||
|
||||
DESCRIPTION sequence for writing and reading from one address
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_READ_AFTER_WRITE_SEQ_SV
|
||||
`define APB_MASTER_READ_AFTER_WRITE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_read_after_write_seq
|
||||
*/
|
||||
class apb_master_read_after_write_seq extends apb_master_base_seq;
|
||||
|
||||
rand int unsigned delay; // transaction delay
|
||||
rand bit [ADDR_WIDTH - 1 : 0] addr; // address to write/read
|
||||
|
||||
// constraints
|
||||
constraint delay_cst { delay inside {[1 : 10]};}
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_read_after_write_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_read_after_write_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
// write
|
||||
`uvm_do_with( req,
|
||||
{req.addr == addr;
|
||||
req.dir == APB_READ;
|
||||
req.delay == delay;})
|
||||
// read
|
||||
`uvm_do_with( req,
|
||||
{req.addr == addr;
|
||||
req.dir == APB_READ;
|
||||
req.delay == delay;})
|
||||
endtask : body
|
||||
endclass : apb_master_read_after_write_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_read_all_seq.sv
|
||||
|
||||
DESCRIPTION sequence for reading from all valid addresses
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_READ_ALL_SEQ_SV
|
||||
`define APB_MASTER_READ_ALL_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_read_all_seq
|
||||
*/
|
||||
class apb_master_read_all_seq extends apb_master_base_seq;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_read_all_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_read_all_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
bit [ADDR_WIDTH - 1 : 0] end_addr, curr_addr;
|
||||
|
||||
// read from all addresses in all slaves
|
||||
foreach (p_sequencer.cfg.slave_cfg_queue[i]) begin
|
||||
curr_addr = p_sequencer.cfg.slave_cfg_queue[i].start_address;
|
||||
end_addr = p_sequencer.cfg.slave_cfg_queue[i].end_address;
|
||||
while (curr_addr != end_addr) begin
|
||||
`uvm_do_with( req, {
|
||||
req.addr == curr_addr;
|
||||
req.dir == APB_READ;})
|
||||
curr_addr++;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endtask : body
|
||||
|
||||
endclass : apb_master_read_all_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_read_seq.sv
|
||||
|
||||
DESCRIPTION sequence for reading from one address
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_READ_SEQ_SV
|
||||
`define APB_MASTER_READ_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_read_seq
|
||||
*/
|
||||
class apb_master_read_seq extends apb_master_base_seq;
|
||||
|
||||
rand int unsigned delay; // transaction delay
|
||||
rand bit [ADDR_WIDTH - 1 : 0] addr; // address to read
|
||||
|
||||
// constraints
|
||||
constraint delay_cst { delay inside {[1 : 10]};}
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_read_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_read_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
`uvm_do_with( req,
|
||||
{req.addr == addr;
|
||||
req.dir == APB_READ;
|
||||
req.delay == delay;})
|
||||
endtask : body
|
||||
endclass : apb_master_read_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_seq_lib.sv
|
||||
|
||||
DESCRIPTION sequence includes
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_SEQ_LIB_SV
|
||||
`define APB_MASTER_SEQ_LIB_SV
|
||||
|
||||
`include "master/sequences/apb_master_base_seq.sv"
|
||||
`include "master/sequences/apb_master_simple_seq.sv"
|
||||
`include "master/sequences/apb_master_read_seq.sv"
|
||||
`include "master/sequences/apb_master_write_seq.sv"
|
||||
`include "master/sequences/apb_master_read_all_seq.sv"
|
||||
`include "master/sequences/apb_master_write_all_seq.sv"
|
||||
`include "master/sequences/apb_master_read_after_write_seq.sv"
|
||||
|
||||
`endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_simple_seq.sv
|
||||
|
||||
DESCRIPTION simple sequence; random transactions
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_SIMPLE_SEQ_SV
|
||||
`define APB_MASTER_SIMPLE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_simple_seq
|
||||
*/
|
||||
class apb_master_simple_seq extends apb_master_base_seq;
|
||||
|
||||
rand int unsigned num_of_tr;
|
||||
|
||||
// constraints
|
||||
constraint num_of_tr_cst { num_of_tr inside {[1 : 10]};}
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_simple_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_simple_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
repeat(num_of_tr) begin
|
||||
`uvm_do(req)
|
||||
end
|
||||
endtask : body
|
||||
|
||||
endclass : apb_master_simple_seq
|
||||
|
||||
`endif
|
||||
@@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_write_all_seq.sv
|
||||
|
||||
DESCRIPTION sequence for writing to all valid addresses
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_WRITE_ALL_SEQ_SV
|
||||
`define APB_MASTER_WRITE_ALL_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_write_all_seq
|
||||
*/
|
||||
class apb_master_write_all_seq extends apb_master_base_seq;
|
||||
|
||||
bit data_is_rand = 1; // 1 = data will be randomly chosen for every write
|
||||
// 0 = used data from "data_to_write" field
|
||||
bit [WDATA_WIDTH - 1 : 0] data_to_write;
|
||||
rand bit [WDATA_WIDTH - 1 : 0] data;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_write_all_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_write_all_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
bit [ADDR_WIDTH - 1 : 0] end_addr, curr_addr;
|
||||
|
||||
// write to all addresses in all slaves
|
||||
foreach (p_sequencer.cfg.slave_cfg_queue[i]) begin
|
||||
curr_addr = p_sequencer.cfg.slave_cfg_queue[i].start_address;
|
||||
end_addr = p_sequencer.cfg.slave_cfg_queue[i].end_address;
|
||||
while (curr_addr != end_addr) begin
|
||||
if (data_is_rand) begin
|
||||
assert(this.randomize());
|
||||
end
|
||||
else begin
|
||||
data = data_to_write;
|
||||
end
|
||||
|
||||
`uvm_do_with( req, {
|
||||
req.addr == curr_addr;
|
||||
req.wdata == data;
|
||||
req.dir == APB_WRITE;})
|
||||
curr_addr++;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
endtask : body
|
||||
|
||||
endclass : apb_master_write_all_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_master_write_seq.sv
|
||||
|
||||
DESCRIPTION sequence for writing to one address
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_MASTER_WRITE_SEQ_SV
|
||||
`define APB_MASTER_WRITE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_master_write_seq
|
||||
*/
|
||||
class apb_master_write_seq extends apb_master_base_seq;
|
||||
|
||||
rand int unsigned delay; // transaction delay
|
||||
rand bit [ADDR_WIDTH - 1 : 0] addr; // address to write
|
||||
rand bit [WDATA_WIDTH - 1 : 0] data; // data to write
|
||||
|
||||
// constraints
|
||||
constraint delay_cst { delay inside {[1 : 10]};}
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_master_write_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_master_write_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
`uvm_do_with( req, {
|
||||
req.addr == addr;
|
||||
req.dir == APB_WRITE;
|
||||
req.wdata == data;
|
||||
req.delay == delay;})
|
||||
endtask : body
|
||||
|
||||
endclass : apb_master_write_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_agent.sv
|
||||
|
||||
DESCRIPTION slave agent
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_AGENT_SV
|
||||
`define APB_SLAVE_AGENT_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_agent
|
||||
*/
|
||||
class apb_slave_agent extends uvm_agent;
|
||||
|
||||
// configuration object
|
||||
apb_slave_config cfg;
|
||||
|
||||
// components
|
||||
apb_slave_driver drv;
|
||||
apb_slave_sequencer seqr;
|
||||
apb_slave_monitor mon;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_slave_agent)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_agent", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_slave_config)::get(this, "", "apb_slave_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
|
||||
// create driver and sequencer if agent is active
|
||||
if(cfg.is_active == UVM_ACTIVE) begin
|
||||
seqr = apb_slave_sequencer::type_id::create("seqr", this);
|
||||
drv = apb_slave_driver::type_id::create("drv", this);
|
||||
end
|
||||
// always create monitor
|
||||
mon = apb_slave_monitor::type_id::create("mon", this);
|
||||
endfunction : build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
function void connect_phase(uvm_phase phase);
|
||||
super.connect_phase(phase);
|
||||
// connect driver and sequencer if agent is active
|
||||
if(cfg.is_active == UVM_ACTIVE) begin
|
||||
drv.seq_item_port.connect(seqr.seq_item_export);
|
||||
end
|
||||
endfunction : connect_phase
|
||||
|
||||
endclass : apb_slave_agent
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_config.sv
|
||||
|
||||
DESCRIPTION slave configuration object
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_CONFIG_SV
|
||||
`define APB_SLAVE_CONFIG_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_config
|
||||
*/
|
||||
class apb_slave_config extends uvm_object;
|
||||
|
||||
// is agent active or passive
|
||||
uvm_active_passive_enum is_active = UVM_ACTIVE;
|
||||
// checks and coverage control
|
||||
bit has_checks = 1;
|
||||
bit has_coverage = 1;
|
||||
// address range
|
||||
rand bit [ADDR_WIDTH - 1 : 0] start_address;
|
||||
rand bit [ADDR_WIDTH - 1 : 0] end_address;
|
||||
// slave index
|
||||
rand int unsigned psel_index;
|
||||
// create agent or just use cfg for address and psel purposes
|
||||
bit create_agent = 1;
|
||||
|
||||
// constraints
|
||||
constraint addr_cst { start_address <= end_address; }
|
||||
constraint psel_cst { psel_index inside {[0 : SLV_NUM]};} // max 15 slaves
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils_begin(apb_slave_config)
|
||||
`uvm_field_enum(uvm_active_passive_enum, is_active, UVM_DEFAULT)
|
||||
`uvm_field_int(has_checks, UVM_DEFAULT)
|
||||
`uvm_field_int(has_coverage, UVM_DEFAULT)
|
||||
`uvm_field_int(start_address, UVM_DEFAULT)
|
||||
`uvm_field_int(end_address, UVM_DEFAULT)
|
||||
`uvm_field_int(psel_index, UVM_DEFAULT)
|
||||
`uvm_field_int(create_agent, UVM_DEFAULT)
|
||||
`uvm_object_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_config");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// checks to see if an address is in the configured range
|
||||
function bit check_address_range(bit [ADDR_WIDTH - 1 : 0] addr);
|
||||
return (!((start_address > addr) || (end_address < addr)));
|
||||
endfunction : check_address_range
|
||||
|
||||
// checks to see if current psel index is for this slave
|
||||
function bit check_psel_index(logic [SLV_NUM - 1 : 0] psel);
|
||||
for (int i = 0; i < SLV_NUM; i++) begin
|
||||
if((psel[i] == 1) && (psel_index == (i + 1)))
|
||||
return 1;
|
||||
end
|
||||
return 0;
|
||||
endfunction : check_psel_index
|
||||
|
||||
endclass : apb_slave_config
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_driver.sv
|
||||
|
||||
DESCRIPTION drives slave response
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_DRIVER_SV
|
||||
`define APB_SLAVE_DRIVER_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_driver
|
||||
*/
|
||||
class apb_slave_driver extends uvm_driver #(apb_transaction, apb_transaction);
|
||||
|
||||
// apb virtual interface
|
||||
virtual apb_if vif;
|
||||
|
||||
// configuration
|
||||
apb_slave_config cfg;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_slave_driver)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_driver", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_slave_config)::get(this, "", "apb_slave_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
endfunction: build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
function void connect_phase(uvm_phase phase);
|
||||
super.connect_phase(phase);
|
||||
// get interface from db
|
||||
if(!uvm_config_db#(virtual apb_if)::get(this, "", "apb_if", vif))
|
||||
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
|
||||
endfunction : connect_phase
|
||||
|
||||
// additional class methods
|
||||
extern virtual task run_phase(uvm_phase phase);
|
||||
extern virtual task get_and_drive();
|
||||
extern virtual task reset();
|
||||
extern virtual task drive_tr (apb_transaction tr);
|
||||
|
||||
endclass : apb_slave_driver
|
||||
|
||||
// UVM run_phase
|
||||
task apb_slave_driver::run_phase(uvm_phase phase);
|
||||
reset(); // init.
|
||||
forever begin
|
||||
fork
|
||||
get_and_drive(); // thread killed at reset
|
||||
@(negedge vif.presetn); // reset is active low
|
||||
join_any
|
||||
disable fork;
|
||||
|
||||
reset();
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
// reset signals
|
||||
task apb_slave_driver::reset();
|
||||
`uvm_info(get_type_name(), "Reset observed", UVM_MEDIUM)
|
||||
vif.prdata <= {WDATA_WIDTH {1'bZ}};
|
||||
vif.pready <= 1'b0;
|
||||
vif.pslverr <= 1'b0;
|
||||
@(posedge vif.presetn); // reset dropped
|
||||
endtask : reset
|
||||
|
||||
// sequencer/driver handshake
|
||||
task apb_slave_driver::get_and_drive();
|
||||
forever begin
|
||||
seq_item_port.get_next_item(req);
|
||||
drive_tr(req);
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
endtask : get_and_drive
|
||||
|
||||
// drive transaction
|
||||
task apb_slave_driver::drive_tr (apb_transaction tr);
|
||||
|
||||
// wait for the master to initiate the transaction
|
||||
@(posedge vif.pclk iff (vif.penable && cfg.check_psel_index(vif.psel)));
|
||||
|
||||
tr.dir = apb_direction_enum'(vif.pwrite);
|
||||
|
||||
// delay
|
||||
if (tr.delay > 0) begin
|
||||
repeat(tr.delay) @(posedge vif.pclk);
|
||||
end
|
||||
// respond
|
||||
vif.pslverr <= tr.error;
|
||||
vif.pready <= 1'b1;
|
||||
if (tr.dir == APB_READ)
|
||||
vif.prdata <= tr.rdata;
|
||||
@(posedge vif.pclk);
|
||||
vif.prdata <= {WDATA_WIDTH {1'bZ}};
|
||||
vif.pready <= 1'b0;
|
||||
|
||||
`uvm_info(get_type_name(), $sformatf("APB Finished Driving tr \n%s", tr.sprint()), UVM_HIGH)
|
||||
endtask : drive_tr
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_monitor.sv
|
||||
|
||||
DESCRIPTION monitors transactions for slave
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_MONITOR_SV
|
||||
`define APB_SLAVE_MONITOR_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_monitor
|
||||
*/
|
||||
class apb_slave_monitor extends uvm_monitor;
|
||||
|
||||
// apb virtual interface
|
||||
virtual apb_if vif;
|
||||
|
||||
// configuration
|
||||
apb_slave_config cfg;
|
||||
|
||||
// TLM - from monitor to other components
|
||||
uvm_analysis_port #(apb_transaction) item_collected_port;
|
||||
|
||||
// keep track of number of transactions
|
||||
int unsigned num_transactions = 0;
|
||||
|
||||
// current transaction
|
||||
apb_transaction tr_collected;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils_begin(apb_slave_monitor)
|
||||
`uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
|
||||
`uvm_component_utils_end
|
||||
|
||||
// coverage
|
||||
covergroup cg_apb_slave;
|
||||
// cover direction - read or write
|
||||
cp_direction : coverpoint tr_collected.dir {
|
||||
bins write = {APB_WRITE};
|
||||
bins read = {APB_READ};
|
||||
}
|
||||
// cover delay - zero or more
|
||||
cp_delay : coverpoint tr_collected.delay {
|
||||
bins zero = {0};
|
||||
bins other = default;
|
||||
}
|
||||
// TODO : add others
|
||||
endgroup : cg_apb_slave;
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_monitor", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
item_collected_port = new("item_collected_port", this);
|
||||
cg_apb_slave = new();
|
||||
endfunction : new
|
||||
|
||||
// UVM build_phase
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
// get configuration object from db
|
||||
if(!uvm_config_db#(apb_slave_config)::get(this, "", "apb_slave_config", cfg))
|
||||
`uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"})
|
||||
endfunction: build_phase
|
||||
|
||||
// UVM connect_phase
|
||||
function void connect_phase(uvm_phase phase);
|
||||
super.connect_phase(phase);
|
||||
// get interface from db
|
||||
if(!uvm_config_db#(virtual apb_if)::get(this, "", "apb_if", vif))
|
||||
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
|
||||
endfunction : connect_phase
|
||||
|
||||
// additional class methods
|
||||
extern virtual task run_phase(uvm_phase phase);
|
||||
extern virtual task collect_transactions();
|
||||
extern virtual function void report_phase(uvm_phase phase);
|
||||
|
||||
endclass : apb_slave_monitor
|
||||
|
||||
// UVM run_phase
|
||||
task apb_slave_monitor::run_phase(uvm_phase phase);
|
||||
forever begin
|
||||
@(posedge vif.presetn); // reset dropped
|
||||
`uvm_info(get_type_name(), "Reset dropped", UVM_MEDIUM)
|
||||
|
||||
fork
|
||||
collect_transactions(); // thread killed at reset
|
||||
@(negedge vif.presetn); // reset is active low
|
||||
join_any
|
||||
disable fork;
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
// monitor apb interface and collect transactions
|
||||
task apb_slave_monitor::collect_transactions();
|
||||
forever begin
|
||||
tr_collected = apb_transaction::type_id::create("tr_collected");
|
||||
|
||||
// collect transactions only for this slave
|
||||
@(posedge vif.pclk iff (cfg.check_psel_index(vif.psel)));
|
||||
tr_collected.addr = vif.paddr;
|
||||
tr_collected.dir = apb_direction_enum'(vif.pwrite);
|
||||
if(tr_collected.dir == APB_WRITE)
|
||||
tr_collected.wdata = vif.pwdata;
|
||||
|
||||
@(posedge vif.pclk); // enable
|
||||
@(posedge vif.pclk); // ready
|
||||
// wait for ready
|
||||
while (vif.pready !== 1'b1) begin
|
||||
@(posedge vif.pclk);
|
||||
tr_collected.delay++;
|
||||
end
|
||||
if(tr_collected.dir == APB_READ) begin
|
||||
tr_collected.rdata = vif.prdata;
|
||||
tr_collected.error = vif.pslverr;
|
||||
end
|
||||
|
||||
item_collected_port.write(tr_collected); // TLM
|
||||
// collect coverage if enabled
|
||||
if(cfg.has_coverage == 1) begin
|
||||
cg_apb_slave.sample();
|
||||
end
|
||||
`uvm_info(get_type_name(), $sformatf("Tr collected :\n%s", tr_collected.sprint()), UVM_MEDIUM)
|
||||
num_transactions++;
|
||||
end // forever
|
||||
endtask : collect_transactions
|
||||
|
||||
// UVM report_phase
|
||||
function void apb_slave_monitor::report_phase(uvm_phase phase);
|
||||
// final report
|
||||
`uvm_info(get_type_name(), $sformatf("Report: APB monitor collected %0d transfers", num_transactions), UVM_LOW);
|
||||
endfunction : report_phase
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_sequencer.sv
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_SEQUENCER_SV
|
||||
`define APB_SLAVE_SEQUENCER_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_sequencer
|
||||
*/
|
||||
class apb_slave_sequencer extends uvm_sequencer #(apb_transaction, apb_transaction);
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_component_utils (apb_slave_sequencer)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_sequencer", uvm_component parent = null);
|
||||
super.new(name, parent);
|
||||
endfunction : new
|
||||
|
||||
// Note: equivalent to
|
||||
// typedef uvm_sequencer#(apb_transaction, apb_transaction) apb_slave_sequencer;
|
||||
|
||||
endclass : apb_slave_sequencer
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_base_seq.sv
|
||||
|
||||
DESCRIPTION base sequence to be extended by other sequences
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_BASE_SEQ_SV
|
||||
`define APB_SLAVE_BASE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_base_seq
|
||||
*/
|
||||
class apb_slave_base_seq extends uvm_sequence #(apb_transaction, apb_transaction);
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_slave_base_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_base_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
endclass : apb_slave_base_seq
|
||||
|
||||
`endif
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_seq_lib.sv
|
||||
|
||||
DESCRIPTION sequence includes
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_SEQ_LIB_SV
|
||||
`define APB_SLAVE_SEQ_LIB_SV
|
||||
|
||||
`include "slave/sequences/apb_slave_base_seq.sv"
|
||||
`include "slave/sequences/apb_slave_simple_seq.sv"
|
||||
|
||||
`endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|F|u|n|c|t|i|o|n|a|l| |V|e|r|i|f|i|c|a|t|i|o|n| |o|f| |H|a|r|d|w|a|r|e|
|
||||
+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+ +-+-+-+-+-+-+-+-+
|
||||
|
||||
FILE apb_slave_simple_seq.sv
|
||||
|
||||
DESCRIPTION simple sequence; always respond with random data
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
`ifndef APB_SLAVE_SIMPLE_SEQ_SV
|
||||
`define APB_SLAVE_SIMPLE_SEQ_SV
|
||||
|
||||
/**
|
||||
* Class: apb_slave_simple_seq
|
||||
*/
|
||||
class apb_slave_simple_seq extends apb_slave_base_seq;
|
||||
|
||||
// UVM factory registration
|
||||
`uvm_object_utils(apb_slave_simple_seq)
|
||||
|
||||
// new - constructor
|
||||
function new(string name = "apb_slave_simple_seq");
|
||||
super.new(name);
|
||||
endfunction : new
|
||||
|
||||
// sequence generation logic in body
|
||||
virtual task body();
|
||||
forever begin
|
||||
`uvm_do(req)
|
||||
end
|
||||
endtask : body
|
||||
|
||||
endclass : apb_slave_simple_seq
|
||||
|
||||
`endif
|
||||
|
||||
Reference in New Issue
Block a user