You are on page 1of 12

//********************DRIVER SLAVE V1********************************//

class ahb_slave_driver extends uvm_driver #(ahb_item, ahb_item);

`uvm_component_utils(ahb_slave_driver)

virtual ahb_if vif;

mailbox#(ahb_item) mbx; // mailbox for sending information from address phase


to data phase

//---------------------NEW()--------------------------//

function new( string name="ahb_slave_driver", uvm_component parent);

super.new(name, parent);

endfunction: new

extern virtual task run_phase(uvm_phase phase);

extern function void build_phase(uvm_phase phase);

extern task drive_address();

extern task drive_data();

endclass: ahb_slave_driver

//---------------------BUILD()--------------------------//

function void ahb_slave_driver::build_phase(uvm_phase phase);

super.build_phase(phase);

mbx = new();

if(!uvm_config_db #(virtual ahb_if)::get(this, "*","vif", vif))

`uvm_fatal("DRIVER_SLAVE", "Interface Not Received Properly");

endfunction: build_phase

//---------------------RUN()--------------------------//

task ahb_slave_driver:: run_phase(uvm_phase phase);

super.run_phase(phase);

vif.cb_slave.HREADY <= 0;

vif.cb_slave.HRDATA <= $urandom();


vif.cb_slave.HRESP <= 0;

@(vif.cb_slave iff (vif.RESET));

drive_address();

endtask: run_phase

//---------------------DRIVE ADDRESS()--------------------------//

task ahb_slave_driver::drive_address();

forever begin

seq_item_port.get_next_item(req); // take an item from sequence

repeat(req.delay_request) @(vif.cb_slave);

vif.cb_slave.HREADY <= 1;

req.HWRITE = vif.cb_slave.HWRITE;

req.HTRANS = vif.cb_slave.HTRANS;

if(mbx.num() > 0) begin

fork

drive_data();

join_none

end

if(vif.cb_slave.HTRANS == 2 || vif.cb_slave.HTRANS == 3) begin

mbx.put(req);

@(vif.cb_slave);

vif.cb_slave.HREADY <= 0;

end else begin

@(vif.cb_slave);

vif.cb_slave.HREADY <= 0;

end

seq_item_port.item_done(req);

end

endtask: drive_address
//---------------------DRIVE DATA()--------------------------//

task ahb_slave_driver::drive_data();

ahb_item item;

item = ahb_item::type_id::create("item");

mbx.get(item);

if(!req.HWRITE) vif.cb_slave.HRDATA <= req.HRDATA;

@(vif.cb_slave);

vif.cb_slave.HRDATA <= 32'h0;

endtask: drive_data

//********************DRIVER SLAVE V2********************************//

`uvm_analysis_imp_decl(_hrdata)

class ahb_slave_driver extends uvm_driver #(ahb_item, ahb_item);

`uvm_component_utils(ahb_slave_driver)

virtual ahb_if vif;

uvm_analysis_imp_hrdata #(bit [31:0], ahb_slave_driver) ahb_hrdata;

bit [31:0] q[$];

mailbox#(ahb_item) mbx; // mailbox for sending information from address phase


to data phase

//---------------------NEW()--------------------------//

function new( string name="ahb_slave_driver", uvm_component parent);

super.new(name, parent);

ahb_hrdata = new("ahb_hrdata", this);

endfunction: new
extern virtual task run_phase(uvm_phase phase);

extern function void build_phase(uvm_phase phase);

extern task drive_address();

extern task drive_data();

extern virtual function void write_hrdata(bit [31:0] HRDATA);

endclass: ahb_slave_driver

//---------------------BUILD()--------------------------//

function void ahb_slave_driver::build_phase(uvm_phase phase);

super.build_phase(phase);

mbx = new();

if(!uvm_config_db #(virtual ahb_if)::get(this, "*","vif", vif))

`uvm_fatal(get_type_name(), "Interface Not Received Properly");

endfunction: build_phase

//---------------------RUN()--------------------------//

task ahb_slave_driver:: run_phase(uvm_phase phase);

super.run_phase(phase);

vif.cb_slave.HREADY <= 0;

vif.cb_slave.HRDATA <= $urandom();

vif.cb_slave.HRESP <= 0;

@(vif.cb_slave iff (vif.RESET));

drive_address();

endtask: run_phase

//---------------------DRIVE ADDRESS()--------------------------//

task ahb_slave_driver::drive_address();

forever begin

seq_item_port.get_next_item(req); // take an item from sequence


repeat(req.delay_request) @(vif.cb_slave);

vif.cb_slave.HREADY <= 1;

req.HWRITE = vif.cb_slave.HWRITE;

req.HTRANS = vif.cb_slave.HTRANS;

if(mbx.num() > 0) begin

fork

drive_data();

join_none

end

if(vif.cb_slave.HTRANS == 2 || vif.cb_slave.HTRANS == 3) begin

mbx.put(req);

@(vif.cb_slave);

vif.cb_slave.HREADY <= 0;

end else begin

@(vif.cb_slave);

vif.cb_slave.HREADY <= 0;

end

seq_item_port.item_done();

end

endtask: drive_address

//---------------------DRIVE DATA()--------------------------//

task ahb_slave_driver::drive_data();

ahb_item item;

item = ahb_item::type_id::create("item");

mbx.get(item);

if(!req.HWRITE) begin

if(q.size() > 0)

vif.cb_slave.HRDATA <= q.pop_front();

else
`uvm_fatal(get_type_name(), "Not enough item in the list for HRDATA")

end

@(vif.cb_slave);

vif.cb_slave.HRDATA <= 32'h0;

endtask: drive_data

//---------------------WRITE()--------------------------//

function void ahb_slave_driver::write_hrdata(bit [31:0] HRDATA);

q.push_back(HRDATA);

endfunction: write_hrdata

//********************Sequence SLAVE V2********************************//

class slave_ahb_sequences extends uvm_sequence #(ahb_item);

`uvm_object_utils(slave_ahb_sequences)

`uvm_declare_p_sequencer(ahb_sequencer)

rand int unsigned num_seq; // send a random number of sequences

rand int unsigned request_delay; // control the delay from request

function new(string name = "slave_ahb_sequences");

super.new(name);

endfunction: new

virtual task body();

req = ahb_item::type_id::create("req_slave");

repeat(num_seq) begin

start_item(req);

assert(req.randomize with { delay_request == request_delay; });


finish_item(req);

end

endtask: body

endclass: slave_ahb_sequences

//********************Sequence SLAVE V1********************************//

class slave_ahb_sequences extends uvm_sequence #(ahb_item);

`uvm_object_utils(slave_ahb_sequences)

`uvm_declare_p_sequencer(ahb_sequencer)

rand int unsigned num_seq; // send a random number of sequences

rand int unsigned request_delay; // control the delay from request

bit keep_hrdata = 1;

bit [31:0] RHRDATA;

function new(string name = "slave_ahb_sequences");

super.new(name);

endfunction: new

virtual task body();

req = ahb_item::type_id::create("req_slave");

repeat(num_seq) begin

start_item(req);

if(!keep_hrdata) assert(req.randomize with { delay_request ==


request_delay; });

else assert(req.randomize with { HRDATA == RHRDATA; delay_request ==


request_delay; });

finish_item(req);
get_response(rsp);

keep_hrdata = (rsp.HTRANS == IDLE) ? 1 : 0;

if(keep_hrdata) RHRDATA = req.HRDATA;

end

endtask: body

endclass: slave_ahb_sequences

//*****************MONITOR **************************//

class ahb_monitor extends uvm_component;

uvm_analysis_port#(ahb_item) mon_scb_port;

`uvm_component_utils(ahb_monitor)

virtual ahb_if vif;

int transfer_count = 0; // keep the number of all transfers made

bit coverage_enable = 1; // control the coverage

mailbox #(ahb_item) mbx; // mailbox for sending information from address


phase to data phase

//---------------------NEW()--------------------------//

function new( string name, uvm_component parent);

super.new(name, parent);

mon_scb_port = new("mon_scb_port", this);

endfunction: new

//---------------------EXTERN FUNCTION()--------------------------//

extern virtual task run_phase(uvm_phase phase);


extern task take_data();

extern task take_address();

extern virtual function void build_phase(uvm_phase phase);

extern virtual function void check_phase(uvm_phase phase);

extern function void perform_coverage(ahb_item item);

extern virtual function void report_phase(uvm_phase phase);

endclass: ahb_monitor

//---------------------BUILD()--------------------------//

function void ahb_monitor::build_phase(uvm_phase phase);

super.build_phase(phase);

mbx = new();

if(!uvm_config_db #(virtual ahb_if)::get(this, "*", "vif", vif)) // take the


virtual interface

`uvm_fatal(get_type_name(), "Interface Not Received Properly")

endfunction: build_phase

//---------------------RUN()--------------------------//

task ahb_monitor::run_phase(uvm_phase phase);

super.run_phase(phase);

@(vif.cb_monitor iff (vif.RESET)); // wait for reset to finish

fork

take_address();

take_data();

join

endtask: run_phase

//---------------------TAKE DATA()--------------------------//

task ahb_monitor::take_data();
ahb_item item_m;

forever begin

mbx.get(item_m); // take the item from address phase

@(vif.cb_monitor iff(vif.cb_monitor.HREADY)); // wait for ready

if(!vif.cb_monitor.HRESP) // if HRESP is ERROR send and fatal error

`uvm_fatal(get_type_name(), "SLAVE Response 0, drop packet!")

if(item_m.HWRITE) item_m.HWDATA = vif.cb_monitor.HWDATA; // if write


transfer take HWDATA

else item_m.HRDATA = vif.cb_monitor.HRDATA; // if read transfer take


HRDATA

if(coverage_enable) perform_coverage(item_m); // coverage the item

transfer_count += 1; // count the transfers

mon_scb_port.write(item_m); // send to scoreboard

end

endtask: take_data

//---------------------TAKE ADDRESS()--------------------------//

task ahb_monitor::take_address();

ahb_item item;

forever begin

@(vif.cb_monitor iff(vif.cb_monitor.HREADY)); // wait for ready

if(vif.cb_monitor.HTRANS == 2 || vif.cb_monitor.HTRANS == 3) begin // if


trans NONSEQ or SEQ take the HADDR and control signals ** if HTRANS = IDLE not
collect the information

item = ahb_item::type_id::create("item");

item.HSIZE = vif.cb_monitor.HSIZE;

item.HADDR = vif.cb_monitor.HADDR;

item.HWRITE = vif.cb_monitor.HWRITE;

item.HBURST = vif.cb_monitor.HBURST;

item.HTRANS = vif.cb_monitor.HTRANS;

item.HMASTER = vif.cb_monitor.HMASTER;

mbx.put(item); // send to data phase the item


end

end

endtask: take_address

//********************AGENT *****************//

class ahb_agent extends uvm_agent;

ahb_sequencer ahb_sequencer_h;
ahb_master_driver driver_master;
ahb_slave_driver driver_slave;
ahb_monitor monitor;
ahb_agent_config cfg;

`uvm_component_utils(ahb_agent)

//---------------------NEW()--------------------------//

function new( string name="ahb_agent", uvm_component parent);

super.new(name, parent);

endfunction: new

extern virtual function void build_phase(uvm_phase phase);

extern virtual function void connect_phase(uvm_phase phase);

endclass: ahb_agent

//---------------------BUILD()--------------------------//

function void ahb_agent::build_phase(uvm_phase phase);

super.build_phase(phase);

if(!uvm_config_db #(ahb_agent_config)::get(this, "*", "cfg", cfg)) // take the


configuration clasa for agent

`uvm_fatal("FATAL MSG", "Config Not Received Properly");


if(cfg.agent_mode == UVM_ACTIVE_MASTER || cfg.agent_mode ==
UVM_ACTIVE_SLAVE) // if ACITVE agent create the sequencer

ahb_sequencer_h = ahb_sequencer::type_id::create("ahb_sequencer_h", this);

if(cfg.agent_mode == UVM_ACTIVE_MASTER) // if ACITVE MASTER agent create the


MASTER DRIVER

driver_master = ahb_master_driver::type_id::create("driver_master", this);

else if(cfg.agent_mode == UVM_ACTIVE_SLAVE) // if ACITVE SLAVE agent create


the SLAVE DRIVER

driver_slave = ahb_slave_driver::type_id::create("driver_slave", this);

monitor = ahb_monitor::type_id::create("monitor", this); // create monitor


anyway

endfunction: build_phase

//---------------------CONNECT_PHASE()--------------------------//

function void ahb_agent::connect_phase(uvm_phase phase);

super.connect_phase(phase);

if(cfg.agent_mode == UVM_ACTIVE_MASTER) // if ACITVE MASTER agent connect the


sequencer export to DRIVER MASTER port

driver_master.seq_item_port.connect(ahb_sequencer_h.seq_item_export);

else if(cfg.agent_mode == UVM_ACTIVE_SLAVE) // if ACITVE SLAVE agent connect


the sequencer export to DRIVER SLAVE port

driver_slave.seq_item_port.connect(ahb_sequencer_h.seq_item_export);

endfunction: connect_phase

You might also like