AHB AMBA Protocol - Verification Code
AHB AMBA Protocol - Verification Code
AHB AMBA Protocol - Verification Code
`include "ahb_pkg.sv"
import ahb_pkg::*;
import uvm_pkg::*;
module top;
//---------------------------CLOCK&RESET------------------------------//
initial begin
RESET = 0;
CLOCK = 0;
#10 RESET = 1;
end
//------------------INTERFACES INSTANCES------------------------//
//------------------DECODER------------------------//
always_comb begin
end
//------------------MASTER READY------------------------//
assign master[0].HREADY = 1;
assign master[1].HREADY = 1;
assign master[2].HREADY = 1;
assign master[3].HREADY = 1;
assign master[4].HREADY = 1;
assign master[5].HREADY = 1;
assign master[6].HREADY = 1;
assign master[7].HREADY = 1;
assign master[8].HREADY = 1;
//------------------MASTER READY------------------------//
assign master[0].HRESP = 1;
assign master[1].HRESP = 1;
assign master[2].HRESP = 1;
assign master[3].HRESP = 1;
assign master[4].HRESP = 1;
assign master[5].HRESP = 1;
assign master[6].HRESP = 1;
assign master[7].HRESP = 1;
assign master[8].HRESP = 1;
// assign slave.HRESP = 1;
//------------------SLAVE WRITE------------------------//
assign slave.HWRITE = 1;
//------------------CONTAINING SIGNALS------------------------//
//------------------INTERFACES CONFIG_DB------------------------//
initial begin
end
//---------------------DUT INSTANCE----------------------------//
generic_arbiter_full DUT (
.hclk(CLOCK),
.hreset(RESET),
.m_hwdata(HWDATA),
.m_haddr(HADDR),
.m_hburst(HBURST),
.m_htrans(HTRANS),
.s_hready(slave.HREADY),
.m_busreq(HBUSREQ),
.m_hlock(HLOCK),
.s_hburst_out(slave.HBURST),
.s_htrans_out(slave.HTRANS),
.s_hmaster_lock(slave.HMASTER_LOCK),
.m_hgrant(HGRANT),
.s_data_out(slave.HWDATA),
.s_addr_out(slave.HADDR),
.s_hmaster(slave.HMASTER)
);
//---------------------RUN()--------------------------//
initial begin
run_test();
end
//------------------------WAVES--------------------------------//
initial begin
$dumpfile("dump.vcd");
$dumpvars();
// #110 $finish;
end
endmodule: top
AHB INTERFACE
endclocking: cb_slave
endclocking: cb_monitor
//------------------ASSERTION BLOCKS------------------------//
property hdata_state;
@(posedge CLOCK) (!HBUSREQ && !HREADY && !RESET && !HGRANT) |=> ((HWDATA ==
0) && (HADDR == 0));
endproperty: hdata_state
property hcontrol_state;
@(posedge CLOCK) (!HBUSREQ && !HREADY && !RESET && !HGRANT) |=> ((HTRANS ==
0) && (HSIZE == 0) && (HBURST == 0));
endproperty: hcontrol_state
property hdata_stable;
@(posedge CLOCK) (!HREADY && !HBUSREQ && !HGRANT) |=> ($stable(HWDATA) &&
$stable(HADDR) && $stable(HTRANS) && $stable(HSIZE) && $stable(HBURST));
endproperty: hdata_stable
assert property(hdata_state);
assert property(hcontrol_state);
assert property(hdata_stable);
endinterface: ahb_if
AHB ITEM
//control fields
rand bit [4:0] TRANSFERS_COUNT; // keep the number of transfers in case of bursts
rand bit BURST_KIND; // 1 - incrementing burst 0 - wrapping burst
rand bit [3:0] ADDR_INCR; // keep the number of bits by which the address should be
incremented in case of bursts
rand bit [2:0] delay_bursts;
rand bit [2:0] delay_transfers;
`uvm_object_utils_begin(ahb_item)
`uvm_field_int(HADDR,UVM_DEFAULT)
`uvm_field_enum(trans_e, HTRANS,UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_field_int(HWDATA,UVM_DEFAULT)
`uvm_field_enum(burst_e,HBURST,UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_field_int(HSIZE,UVM_DEFAULT)
`uvm_field_int(HRDATA,UVM_DEFAULT)
`uvm_field_int(HWRITE,UVM_DEFAULT)
`uvm_field_int(HMASTER,UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_field_int(HBUSREQ,UVM_DEFAULT | UVM_NOCOMPARE|
UVM_NOPRINT)
`uvm_field_int(HGRANT,UVM_NOCOMPARE| UVM_DEFAULT)
`uvm_field_int(HLOCK,UVM_DEFAULT|UVM_NOCOMPARE|UVM_NOPRINT)
`uvm_field_int(TRANSFERS_COUNT,UVM_ALL_ON | UVM_NOCOMPARE |
UVM_NOPACK | UVM_NOPRINT)
`uvm_object_utils_end
super.new(name);
endfunction: new
endclass: ahb_item
super.new(name);
endfunction: new
endclass: ahb_item_delay
AHB MASTER DRIVER
`uvm_component_utils(ahb_master_driver)
uvm_analysis_port#(int) drv_scb_port;
bit first = 1;
mailbox#(ahb_item) mbx;
//---------------------NEW()--------------------------//
super.new(name, parent);
id = count ++;
endfunction: new
extern virtual task run_phase(uvm_phase phase);
endclass: ahb_master_driver
//---------------------BUILD()--------------------------//
super.build_phase(phase);
mbx = new();
endfunction: build_phase
//---------------------RUN()--------------------------//
super.run_phase(phase);
reset_values();
forever begin
drive();
end
endtask: run_phase
//---------------------DRIVE()--------------------------//
task ahb_master_driver::drive();
seq_item_port.get_next_item(req);
if(first) drv_scb_port.write(id);
@(vif.cb_master);
repeat(req.delay_bursts) @(vif.cb_master);
fork
put_address(req);
put_data(req);
join
end
@(vif.cb_master);
vif.cb_master.HBUSREQ <= 0;
seq_item_port.item_done();
transfers_count = 0;
first = 0;
endtask:drive
//---------------------PUT ADDRESS()--------------------------//
// req.print();
NEXT_ADDR = req.HADDR;
repeat(req.TRANSFERS_COUNT) begin // drive the signals for each transfer in the burst
end
if(vif.cb_master.HREADY) @(vif.cb_master);
if(transfers_count == 0) mbx.put(req);
end
reset_values();
endtask: put_address
//---------------------PUT DATA()--------------------------//
mbx.get(item);
repeat(req.TRANSFERS_COUNT) begin
if(req.HWRITE) begin
data_count += 1;
end
if(vif.cb_master.HREADY) @(vif.cb_master);
vif.cb_master.HWDATA <= 0;
repeat(req.delay_transfers) @(vif.cb_master);
end
data_count = 0;
endtask: put_data
//---------------------RESET_VALUES()--------------------------//
task ahb_master_driver::reset_values();
vif.cb_master.HADDR <= 0;
vif.cb_master.HTRANS <= 0;
vif.cb_master.HWRITE <= 0;
vif.cb_master.HSIZE <= 0;
vif.cb_master.HBURST <= 0;
vif.cb_master.HPROT <= 0;
vif.cb_master.HLOCK <= 0;
vif.cb_master.HWDATA <= 0;
endtask: reset_values
uvm_analysis_port#(ahb_item) mon_scb_port;
`uvm_component_utils(ahb_monitor)
ahb_item item_m;
bit first_item;
int id;
bit coverage_enable = 1;
option.per_instance = 1;
option.name = "ahb_transfers_cg";
option.at_least = 40;
option.at_least = 40;
option.at_least = 40;
option.at_least = 2;
}
TRANS_HSIZE: coverpoint item.HSIZE {
endgroup: ahb_transfers_cg
//---------------------NEW()--------------------------//
super.new(name, parent);
id = count ++;
ahb_transfers_cg = new();
endfunction: new
//---------------------EXTERN FUNCTION()--------------------------//
endclass: ahb_monitor
//---------------------BUILD()--------------------------//
super.build_phase(phase);
mbx = new();
endfunction: build_phase
//---------------------RUN()--------------------------//
super.run_phase(phase);
fork
take_address();
take_data();
join
endtask: run_phase
//---------------------TAKE DATA()--------------------------//
task ahb_monitor::take_data();
mbx.get(item_m);
if(coverage_enable) perform_coverage(item_m);
transfer_count += 1;
end end
endtask: take_data
//---------------------TAKE ADDRESS()--------------------------//
task ahb_monitor::take_address();
CUREENT_ADDR = vif.cb_monitor.HADDR;
item.HWRITE = vif.cb_monitor.HWRITE;
item.HBURST = vif.cb_monitor.HBURST;
item.HTRANS = vif.cb_monitor.HTRANS;
item.HLOCK = vif.cb_monitor.HLOCK;
item.HGRANT = vif.cb_monitor.HGRANT;
item.HLOCK = vif.cb_monitor.HMASTER_LOCK;
item.HMASTER = vif.cb_monitor.HMASTER;
end
mbx.put(item);
end
end
end
endtask: take_address
//---------------------CHECK PHASE()--------------------------//
super.check_phase(phase);
if(vif.cb_monitor.HBUSREQ)
else begin
if(id == size) begin
end
end
endfunction: check_phase
//---------------------PERFORM CHECK()--------------------------//
ahb_transfers_cg.sample(item);
endfunction: perform_coverage
//---------------------REPORT PHASE()--------------------------//
super.report_phase(phase);
if(id == 8) begin
$display ("-------------------------------------------------------------------");
end
endfunction: report_phase
AHB SEQUENCES
//************************RANDOM SEQUENCES()****************************//
`uvm_object_utils(random_ahb_transfer_seq)
`uvm_declare_p_sequencer(ahb_sequencer)
super.new(name);
endfunction: new
repeat(num_seq)
endtask: body
endclass: random_ahb_transfer_seq
//************************VIRTUAL SEQUENCES()****************************//
random_ahb_transfer_seq seq_m[];
`uvm_object_utils(virtual_sequences)
`uvm_declare_p_sequencer(virtual_ahb_sequencer)
super.new(name);
seq_m = new[size];
foreach(seq_m[i])
seq_m[i] = random_ahb_transfer_seq::type_id::create($sformatf("seq_m%0d",i));
endfunction: new
fork
`uvm_do_on(seq_m[0], p_sequencer.sequencer[0]);
`uvm_do_on(seq_m[1], p_sequencer.sequencer[1]);
`uvm_do_on(seq_m[2], p_sequencer.sequencer[2]);
`uvm_do_on(seq_m[3], p_sequencer.sequencer[3]);
`uvm_do_on(seq_m[4], p_sequencer.sequencer[4]);
`uvm_do_on(seq_m[5], p_sequencer.sequencer[5]);
`uvm_do_on(seq_m[6], p_sequencer.sequencer[6]);
`uvm_do_on(seq_m[7], p_sequencer.sequencer[7]);
`uvm_do_on(seq_m[8], p_sequencer.sequencer[8]);
join
endtask: body
endclass: virtual_sequences
//************************INCREMENT SEQUENCES()****************************//
`uvm_object_utils(incr_bursts_seq)
`uvm_declare_p_sequencer(ahb_sequencer)
super.new(name);
endfunction: new
endclass: incr_bursts_seq
//************************WRAPPING SEQUENCES()****************************//
`uvm_object_utils(wrap_bursts_seq)
`uvm_declare_p_sequencer(ahb_sequencer)
super.new(name);
endfunction: new
endclass: wrap_bursts_seq
//************************SINGLE TRANSFER
SEQUENCES()****************************//
`uvm_object_utils(single_transfers_seq)
`uvm_declare_p_sequencer(ahb_sequencer)
super.new(name);
endfunction: new
endclass: single_transfers_seq
//************************WRAPPING SEQUENCES()****************************//
`uvm_object_utils(no_busreq_seq)
`uvm_declare_p_sequencer(ahb_sequencer)
super.new(name);
endfunction: new
endclass: no_busreq_seq
`uvm_object_utils(all_busreq_seq)
`uvm_declare_p_sequencer(ahb_sequencer)
super.new(name);
endfunction: new
endclass: all_busreq_seq
AHB SEQUENCER
//---------------------SEQUENCER CLASS--------------------------//
`uvm_sequencer_utils(ahb_sequencer)
//---------------------NEW()--------------------------//
super.new(name, parent);
endfunction: new
endclass: ahb_sequencer
`uvm_sequencer_utils(virtual_ahb_sequencer)
ahb_sequencer sequencer[];
//---------------------NEW()--------------------------//
super.new(name, parent);
sequencer = new[size];
foreach (sequencer[i])
endfunction: new
endclass: virtual_ahb_sequencer
AHB AGENT
`uvm_component_utils_begin(ahb_agent)
`uvm_component_utils_end
//---------------------NEW()--------------------------//
super.new(name, parent);
id = count ++;
endfunction: new
//---------------------BUILD()--------------------------//
super.build_phase(phase);
endfunction: build_phase
`uvm_component_utils(base_test)
ahb_env ahb_env_h;
//---------------------NEW()--------------------------//
super.new(name, parent);
endfunction: new
//---------------------BUILD()--------------------------//
super.build_phase(phase);
endfunction: build_phase
endclass: base_test
AHB SCOREBOARD
`uvm_analysis_imp_decl(_mon_m)
`uvm_analysis_imp_decl(_mon_s)
`uvm_analysis_imp_decl(_drv)
`uvm_component_utils(scoreboard)
ahb_item q[$];
int q_master[$];
int start_test = 1;
ahb_item expected_item;
int HMASTER, NEXT_HMASTER;
//---------------------NEW()--------------------------//
super.new(name,parent);
endfunction: new
q.push_back(expected_item);
endfunction: write_mon_m
//---------------------CHECK ARBITRATION()--------------------------//
if(start_test) begin
`uvm_info("SCOREBOARD", "The order of the masters who will receive access to the bus is:",
UVM_MEDIUM)
end
HMASTER = q_master[0];
start_test = 0;
endfunction: check_arbitration
`uvm_info("SCOREBOARD", "Compare packages: first packet is from slave, second packet is from
master", UVM_MEDIUM)
if(q.size()) begin
expected_item = q.pop_front();
check_arbitration(arrived_item.HMASTER);
// arrived_item.print();
// expected_item.print();
if(arrived_item.compare(expected_item))
else
end else
endfunction: write_mon_s
//---------------------WRITE FROM DRIVER()--------------------------//
q_master.push_back(master);
endfunction: write_drv
//---------------------CHECK PHASE()--------------------------//
super.check_phase(phase);
if(q.size() != 0)
`uvm_fatal("FATAL SCOREBOARD", $sformatf("Did not receive all the packages. %0h packages
in the list", q.size()))
else
endfunction: check_phase
endclass: scoreboard
AHB ENVIRONMENT
virtual_ahb_sequencer virtual_ahb_sequencer_h;
scoreboard scoreboard_h;
ahb_agent master[];
ahb_agent slave;
ahb_config cfg;
`uvm_component_utils_begin(ahb_env)
`uvm_field_object(cfg, UVM_DEFAULT)
`uvm_component_utils_end
//---------------------NEW()--------------------------//
super.new(name, parent);
endfunction: new
//---------------------BUILD()--------------------------//
super.build_phase(phase);
assert(cfg.randomize());
end
master = new[NumMaster];
master[i].cfg = cfg.master_config[i];
end
slave.cfg = cfg.slave_config;
endfunction: build_phase
//---------------------CONNECT()--------------------------//
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
master[i].driver_master.seq_item_port.connect(virtual_ahb_sequencer_h.sequencer[i].seq_item_exp
ort);
master[i].driver_master.drv_scb_port.connect(scoreboard_h.ahb_drv);
end
master[i].monitor.mon_scb_port.connect(scoreboard_h.ahb_mon_m);
end
slave.monitor.mon_scb_port.connect(scoreboard_h.ahb_mon_s);
endfunction: connect_phase
endclass: ahb_env
`uvm_component_utils(ahb_slave_driver)
//---------------------NEW()--------------------------//
function new( string name="ahb_slave_driver", uvm_component parent);
super.new(name, parent);
endfunction: new
endclass: ahb_slave_driver
//---------------------BUILD()--------------------------//
super.build_phase(phase);
endfunction: build_phase
//---------------------RUN()--------------------------//
super.run_phase(phase);
vif.cb_slave.HREADY <= 0;
vif.cb_slave.HRDATA <= 0;
vif.cb_slave.HRESP <= 0;
forever begin
drive();
end
endtask: run_phase
//---------------------DRIVE()--------------------------//
task ahb_slave_driver::drive();
@(vif.cb_slave);
vif.cb_slave.HREADY <= 1;
if(!vif.HWRITE)
@(vif.cb_slave);
endtask:drive
AHB CONFIG
//---------------------AHB_AGENT_CONFIG()--------------------------//
`uvm_object_utils(ahb_agent_config)
//---------------------NEW()--------------------------//
super.new(name);
endfunction: new
endclass: ahb_agent_config
//---------------------AHB_CONFIG()--------------------------//
`uvm_object_utils(ahb_config)
constraint c_master {
foreach (master_config[i])
master_config[i].agent_mode == UVM_ACTIVE_MASTER;
//---------------------NEW()--------------------------//
super.new(name);
master_config = new[NumMaster];
foreach (master_config[i])
master_config[i] = ahb_agent_config::type_id::create($psprintf("master_config[%0d]",i));
slave_config = ahb_agent_config::type_id::create("slave_config");
endfunction: new
endclass: ahb_config
AHB TEST
`uvm_component_utils(ahb_test)
virtual_sequences seq;
super.new(name, parent);
endfunction: new
super.build_phase(phase);
// set_type_override_by_type(ahb_item::get_type(), ahb_item_delay::get_type());
// set_type_override_by_type(random_ahb_transfer_seq::get_type(), incr_bursts_seq::get_type());
// set_type_override_by_type(random_ahb_transfer_seq::get_type(), wrap_bursts_seq::get_type());
// set_type_override_by_type(random_ahb_transfer_seq::get_type(), single_transfers_seq::get_type());
// set_type_override_by_type(random_ahb_transfer_seq::get_type(), no_busreq_seq::get_type());
// set_type_override_by_type(random_ahb_transfer_seq::get_type(), all_busreq_seq::get_type());
seq = virtual_sequences::type_id::create("seq");
endfunction: build_phase
//---------------------RUN()--------------------------//
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
seq.start(ahb_env_h.virtual_ahb_sequencer_h);
#100
phase.drop_objection(this);
endtask: run_phase
endclass: ahb_test