Amba Apb Assignment

Download as pdf or txt
Download as pdf or txt
You are on page 1of 19

AMBA -APB UVM TESTBENCH

1. DUT OF SLAVE :

`define PACKET 10 // repeat in sequence

`define ADDR_WIDTH 32
`define DATA_WIDTH 32

`define SEL 4
`define STR 4

module apb_slave
( input clk,
input rst_n,
input [`ADDR_WIDTH-1:0] paddr,
input pwrite,
input penable,
input [`DATA_WIDTH-1:0] pwdata,
input [`SEL-1:0] psel,
input [`STR-1:0] pstrobe,

output logic [`DATA_WIDTH-1:0] prdata,


output logic pready
);

logic [31:0] mem [256];


logic [1:0] apb_st;

logic [31:0] pwdata_temp;

const logic [1:0] SETUP = 0;


const logic [1:0] W_ENABLE = 1;
const logic [1:0] R_ENABLE = 2;

// SETUP -> ENABLE


always @(negedge rst_n or posedge clk)
begin
if (rst_n == 0)
begin
apb_st <= 0;
prdata <= 0;
pready <= 1;
end

else
begin
case (apb_st)
SETUP : begin
prdata <= 0;// clear the prdata
if (psel[0] && !penable)
begin
if (pwrite)
begin
pwdata_temp<=pwdata;

if(pstrobe[0]==0)
pwdata_temp[7:0]<=8'b0;

if(pstrobe[1]==0)
pwdata_temp[15:8]<=8'b0;

if(pstrobe[2]==0)
pwdata_temp[23:16]<=8'b0;

if(pstrobe[3]==0)
pwdata_temp[31:24]<=8'b0;

apb_st <= W_ENABLE;


end
else
begin
apb_st <= R_ENABLE;
end
end
end

W_ENABLE : begin
if (psel[0] && penable && pwrite) // write pwdata to memory
begin
mem[paddr] <=
{pwdata_temp[31:24],pwdata_temp[23:16],pwdata_temp[15:8],pwdata_temp[7:0]};
end
apb_st <= SETUP;
end

R_ENABLE : begin
if (psel[0] && penable && !pwrite)
begin
prdata <= mem[paddr];
end
apb_st <= SETUP; // return to SETUP
end
endcase
end
end

endmodule

2. TRANSACTION CLASS :

//TRANSACTION CLASS

class apb_bridge_dataitem extends uvm_sequence_item;

//master_side.......
randc bit [`ADDR_WIDTH-1:0] PADDR;
randc bit [`DATA_WIDTH-1:0] PWDATA;
rand bit [`SEL-1:0] PSEL;
rand bit PWRITE;
rand bit PENABLE;
rand bit [`STR-1:0] PSTROBE;

//slave_side.....
bit PREADY;
bit [`DATA_WIDTH:0] PRDATA;

constraint p_enable {PENABLE==1'b0;}

constraint p_select{PSEL==4'b0001;} //selects peripheral one (slave one)

constraint P_strobe {PSTROBE==4'b1111;}

//PWRITE==1 then write operation else if zero read operation.


constraint write_or_read{PWRITE==1'b1;}
//to perform read do inline constraint....

constraint data_range{PWDATA inside {[0:300]};}

constraint addr_range1{PADDR inside {[0:100]};}


`uvm_object_utils_begin(apb_bridge_dataitem) //register to factory......
`uvm_field_int(PADDR,UVM_ALL_ON)
`uvm_field_int(PWDATA,UVM_ALL_ON)
`uvm_field_int(PSEL,UVM_ALL_ON)
`uvm_field_int(PWRITE,UVM_ALL_ON)
`uvm_field_int(PREADY,UVM_ALL_ON)
`uvm_field_int(PENABLE,UVM_ALL_ON)
`uvm_field_int(PRDATA,UVM_ALL_ON)
`uvm_field_int(PSTROBE,UVM_ALL_ON)
`uvm_object_utils_end

function new (string name = "apb_bridge_dataitem");


super.new(name);
`uvm_info(get_type_name(),"data_item_object created",UVM_HIGH)
endfunction

endclass

//................end of packet......................................

3. INTERFACE :

//INTERFACE

`define PACKET 10 // repeat in sequence

`define ADDR_WIDTH 32
`define DATA_WIDTH 32

`define SEL 4
`define STR 4

interface apb_interface(input clk,reset);

//master_side.......
logic [`ADDR_WIDTH-1:0] PADDR;
logic [`DATA_WIDTH-1:0] PWDATA;
logic [`SEL-1:0] PSEL;
logic PWRITE;
logic PENABLE;
logic [`STR-1:0] PSTROBE;

//slave_side.....
logic [`DATA_WIDTH-1:0] PRDATA;
logic PREADY;

endinterface

4. PASSIVE AGENT:

class apb_bridge_agentpass extends uvm_agent;


`uvm_component_utils(apb_bridge_agentpass)
apb_bridge_moni_read apb_read;

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
apb_read=apb_bridge_moni_read::type_id::create("apb_read",this);
endfunction

endclass

5. ACTIVE AGENT:

class apb_bridge_agentact extends uvm_agent;

`uvm_component_utils(apb_bridge_agentact)

apb_bridge_sequencer apb_seq;
apb_bridge_dri apb_dri;
apb_bridge_moni_mst apb_moni_mst;

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
apb_moni_mst=apb_bridge_moni_mst::type_id::create("apb_mon_mst",this);
apb_dri=apb_bridge_dri::type_id::create("apb_dri",this);
apb_seq=apb_bridge_sequencer::type_id::create("apb_seq",this);
endfunction

function void connect_phase(uvm_phase phase);


apb_dri.seq_item_port.connect(apb_seq.seq_item_export);
endfunction

endclass

6. DRIVER:

class apb_bridge_dri extends uvm_driver#(apb_bridge_dataitem);

`uvm_component_utils(apb_bridge_dri)
apb_config con;
virtual apb_interface vf;

int count=`PACKET;

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
uvm_config_db #(apb_config)::get(this,"*","confi",con); //getting config object
from config_database.
endfunction

function void connect_phase(uvm_phase phase);


vf=con.vif;
endfunction

virtual task run_phase(uvm_phase phase);

forever
begin

seq_item_port.get_next_item(req);
apb_drive_logic();
seq_item_port.item_done();
req.print();

//.....this logic to make enable low after last packet...................


count=count-1;
begin
if(count==0)
begin
@(posedge vf.clk);
vf.PENABLE<=1'b0;
vf.PSEL<=4'b0;
end
end
end
endtask

extern task apb_drive_logic();


extern task no_transfer();
extern task stimulus();

endclass

task apb_bridge_dri::apb_drive_logic();
begin
@(posedge vf.clk);
// IF THE SELECT AND ENABLE ARE LOW THEN, THERE WILL BE NO
TRANSFER
if(req.PSEL==4'b0 && req.PENABLE==1'b0)
begin
no_transfer();
end

//WRITE MODE
else if(req.PSEL!=4'b0 && req.PENABLE==1'b0 &&
req.PWRITE==1'b1)
begin
//req.print();
stimulus();
vf.PRDATA <=32'b0;
vf.PWDATA <=req.PWDATA;
vf.PSTROBE<=req.PSTROBE;
#1 @(posedge vf.clk);
vf.PENABLE <=1'b1;
wait(vf.PREADY==1'b1);
end

//READ MODE
else if(req.PSEL==1'b1 && req.PENABLE==1'b0 &&
req.PWRITE==1'b0)
begin
// req.print();
stimulus();
vf.PWDATA <=32'b0;
#1 @(posedge vf.clk);
vf.PENABLE <=1'b1;
wait(vf.PREADY==1'b1);
wait(vf.PRDATA);
end
end
endtask

task apb_bridge_dri::no_transfer();
begin
vf.PADDR <=0;
vf.PWDATA <=0;
vf.PSEL <=0;
vf.PWRITE <=0;
vf.PENABLE<=0;
vf.PSTROBE<=0;
end
endtask

task apb_bridge_dri::stimulus();
begin
vf.PENABLE<=req.PENABLE;
vf.PADDR <=req.PADDR;
vf.PSEL <=req.PSEL;
vf.PWRITE <=req.PWRITE;
end
endtask

//............end of driver................................

7. MONITOR READ:

class apb_bridge_moni_read extends uvm_monitor;

`uvm_component_utils(apb_bridge_moni_read)
uvm_analysis_port #(apb_bridge_dataitem) item_collect_readport;

virtual apb_interface vf;


apb_bridge_dataitem monitor_tr;
apb_config con;

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
uvm_config_db #(apb_config)::get(this,"*","confi",con); //getting config object
from config_database.
item_collect_readport=new("item_collect_readport",this);
endfunction

function void connect_phase(uvm_phase phase);


vf=con.vif;
endfunction

virtual task run_phase(uvm_phase phase);


forever
begin
monitor_tr=apb_bridge_dataitem::type_id::create("monitor_tr",this);
@(vf.PWRITE);
if(vf.PWRITE==1'b0)
begin
wait(vf.PRDATA);
monitor_tr.PADDR=vf.PADDR;
monitor_tr.PRDATA=vf.PRDATA;
monitor_tr.PSEL=vf.PSEL;
monitor_tr.PWRITE=vf.PWRITE;
monitor_tr.PENABLE=vf.PENABLE;
monitor_tr.print();
item_collect_readport.write(monitor_tr);
end
end
endtask
endclass

8. MONITOR MASTER:

class apb_bridge_moni_mst extends uvm_monitor;

`uvm_component_utils(apb_bridge_moni_mst)
uvm_analysis_port #(apb_bridge_dataitem) item_collect_port;

virtual apb_interface vf;


apb_bridge_dataitem monitor_tr;
apb_config con;
function new(string name="apb_bridge_moni_mst",uvm_component parent);
super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
uvm_config_db #(apb_config)::get(this,"*","confi",con); //getting config object
from config_database.
item_collect_port=new("item_collect_port",this);
endfunction

function void connect_phase(uvm_phase phase);


vf=con.vif;
endfunction

virtual task run_phase(uvm_phase phase);


forever
begin
monitor_tr=apb_bridge_dataitem::type_id::create("monitor_tr",this);
apb_moni_logic();
item_collect_port.write(monitor_tr);
monitor_tr.print();
end
endtask

extern task apb_moni_logic();


extern task get_stimulus();

endclass

task apb_bridge_moni_mst::apb_moni_logic();
begin
@(posedge vf.clk);
if(vf.PSEL==4'b0 && vf.PENABLE==1'b0)
begin
get_stimulus();
end

else if(vf.PSEL!=4'b0 && vf.PENABLE==1'b0 &&


vf.PWRITE==1'b1)
begin
@(posedge vf.clk);
if(vf.PENABLE !=1'b1)
`uvm_error(get_type_name(), " the protocol voilation enable is not
asserting")

wait(vf.PREADY==1'b1);
get_stimulus();
end
end
endtask

task apb_bridge_moni_mst::get_stimulus();
begin
monitor_tr.PENABLE=vf.PENABLE;
monitor_tr.PADDR =vf.PADDR;
monitor_tr.PSEL =vf.PSEL;
monitor_tr.PWRITE =vf.PWRITE;
monitor_tr.PWDATA =vf.PWDATA;
monitor_tr.PSTROBE=vf.PSTROBE;
end
endtask

//....................end of monitor......................

9. SEQUENCE:

// sanitory test case one write and one read ..next 256 write and read

class apb_bridge_seq extends uvm_sequence#(apb_bridge_dataitem);

`uvm_object_utils(apb_bridge_seq)

static bit[7:0] i; //control signal to control the write and reads


static bit[7:0] q; //store address for read operation at same address

function new(string name= "apb_bridge_seq");


super.new(name);
`uvm_info(get_type_name(),"sequence_object created",UVM_HIGH)
endfunction

virtual task body();


repeat(`PACKET)
begin
if(i[0]==1'b0)
begin
`uvm_info(get_type_name(),"sanitory test case one write and one
read",UVM_MEDIUM)
`uvm_do(req)
q=req.PADDR;
i=i+1;
end
else if(i[0]==1'b1)
begin
`uvm_info(get_type_name(),"$sequence_read ",UVM_MEDIUM)
req=apb_bridge_dataitem::type_id::create("req");
start_item(req);
req.write_or_read.constraint_mode(0);
req.data_range.constraint_mode(0);
assert(req.randomize() with {req.PWRITE==1'b0;req.PADDR==q;});
finish_item(req);
i=i+1;
end
end
endtask
endclass

class apb_bridge_seq1 extends apb_bridge_seq;

`uvm_object_utils(apb_bridge_seq1)

function new(string name= "apb_bridge_seq11111");


super.new(name);
`uvm_info(get_type_name(),"write values to all the locations",UVM_MEDIUM)
endfunction

virtual task body();


req=apb_bridge_dataitem::type_id::create("req");

repeat(`PACKET)
begin
start_item(req);
assert(req.randomize());
finish_item(req);
end
endtask

endclass

//..................the end ................only two sequence........


10. SEQUENCER:

class apb_bridge_sequencer extends uvm_sequencer #(apb_bridge_dataitem);

`uvm_component_utils(apb_bridge_sequencer)

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


super.new(name,parent);
`uvm_info(get_type_name(),"sequencer created",UVM_HIGH)
endfunction

endclass

//...............end of sequencer.....................

11. SUBSCRIBER CLASS:

class apb_subscriber extends uvm_subscriber#(apb_bridge_dataitem);

`uvm_component_utils(apb_subscriber)

apb_bridge_dataitem trc;

covergroup apb_coverage;

coverpoint trc.PWRITE { bins read={0};


bins write={1};
}
coverpoint trc.PADDR {bins min[10]={[0:100]};}

endgroup

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


super.new(name,parent);
apb_coverage=new();
endfunction

function void write(apb_bridge_dataitem t);


this.trc=t;
apb_coverage.sample();
endfunction
endclass

//..........simple coverage checking ...........................

12. SCOREBORD:

`uvm_analysis_imp_decl(_WRT)
`uvm_analysis_imp_decl(_RED)

class apb_bridge_scoreboard extends uvm_scoreboard;

`uvm_component_utils(apb_bridge_scoreboard)

uvm_analysis_imp_WRT #(apb_bridge_dataitem,apb_bridge_scoreboard)
apb_write_export;
uvm_analysis_imp_RED #(apb_bridge_dataitem,apb_bridge_scoreboard)
apb_read_export;

bit [7:0] addr_write[$]; bit [31:0] data_write[$];

bit [7:0] addr_read[$]; bit [31:0] data_read[$];

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
apb_write_export=new("apb_write_export",this);
apb_read_export =new("apb_read_export", this);
endfunction

virtual function void write_WRT(apb_bridge_dataitem pkt);


begin
if(pkt.PWRITE==1'b1)
begin
addr_write.push_back(pkt.PADDR);
data_write.push_back(pkt.PWDATA);
end
end
endfunction

virtual function void write_RED(apb_bridge_dataitem pk);


begin
if(pk.PWRITE==1'b0)
begin
addr_read.push_back(pk.PADDR);
data_read.push_back(pk.PRDATA);
end
end
endfunction

virtual function void extract_phase(uvm_phase phase);


repeat(addr_write.size)
begin
int aw,dw,ar,dr;
aw=addr_write.pop_front();
dw=data_write.pop_front();
ar=addr_read.pop_front();
dr=data_read.pop_front();
begin
if({aw,dw}=={ar,dr})
`uvm_info(get_type_name(),$sformatf("the data matches
[writeaddress=%0d writedata=%0d]=[readaddress=%0d
readdata=%0d]",aw,dw,ar,dr),UVM_MEDIUM)
else
`uvm_info(get_type_name(),$sformatf("the data is not
matching !!!!!! [writeaddress=%0d writedata=%0d]=[readaddress=%0d
readdata=%0d]",aw,dw,ar,dr),UVM_MEDIUM)
end

end
endfunction

endclass

13. ENVIRONMENT:

class apb_top_environ extends uvm_env;

`uvm_component_utils(apb_top_environ)
apb_bridge_agentact active_agent;
apb_bridge_scoreboard score_board;
apb_bridge_agentpass pasiv_agent;
apb_subscriber subscribe;

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
active_agent =apb_bridge_agentact ::type_id::create("active_agent",this);
//agent is D/SEQR/M for write
pasiv_agent =apb_bridge_agentpass ::type_id::create("pasiv_agent",
this); //agent is MONITOR for read
score_board
=apb_bridge_scoreboard ::type_id::create("score_board",this);

subscribe =apb_subscriber ::type_id::create("subscribe", this);


endfunction

function void connect_phase(uvm_phase phase);

active_agent.apb_moni_mst.item_collect_port.connect(score_board.apb_write_export);

pasiv_agent.apb_read.item_collect_readport.connect(score_board.apb_read_export);

active_agent.apb_moni_mst.item_collect_port.connect(subscribe.analysis_export);
endfunction

endclass

14. TEST:

class base_test extends uvm_test;

`uvm_component_utils(base_test)
apb_top_environ env;
apb_config con_t;

apb_bridge_seq seq; //default seq

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


super.new(name,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase(phase);
con_t=apb_config::type_id::create("con_t",this);
uvm_config_db #(virtual apb_interface)::get(this,"","vif",con_t.vif);
uvm_config_db #(apb_config)::set(this,"*","confi",con_t);
env=apb_top_environ::type_id::create("env",this);
seq=apb_bridge_seq::type_id::create("seq",this);
endfunction

task run_phase(uvm_phase phase);


phase.raise_objection(this);
seq.start(env.active_agent.apb_seq);
#19;
phase.drop_objection(this);
endtask

endclass

15. CONFIG :

class apb_config extends uvm_object;

`uvm_object_utils(apb_config)

virtual apb_interface vif;

function new(string name="apb_config");


super.new(name);
endfunction

endclass

16. TOP :

//top module

`include "uvm_macros.svh"
import uvm_pkg::*;
`include "define.sv"
`include "apb_interface.sv"
`include "apb_slave.sv"
`include "apb_config.sv"
`include "apb_bridge_dataitem.sv"
`include "apb_bridge_sequencer.sv"
`include "apb_bridge_dri.sv"
`include "apb_bridge_moni_mst.sv"
`include "apb_bridge_moni_read.sv"
`include "apb_bridge_agentact.sv"
`include "apb_bridge_agentpass.sv"
`include "apb_bridge_scoreboard.sv"
`include "apb_subscriber.sv"
`include "apb_top_environ.sv"
`include "apb_bridge_seq.sv"
`include "base_test.sv"

module apb_top;

bit clock,reset;

apb_interface intf(.clk(clock),.reset(reset));

apb_slave
dt(.clk(clock),.rst_n(reset),.paddr(intf.PADDR),.pwrite(intf.PWRITE),.psel(intf.PSEL),.p
enable(intf.PENABLE),.pwdata(intf.PWDATA),.prdata(intf.PRDATA),.pready(intf.PRE
ADY));

initial forever #5 clock=!clock;

initial
begin
#5 reset=1'b1;
end

initial
begin
uvm_config_db #(virtual apb_interface)::set(null,"*","vif",intf);
run_test("base_test");
end
endmodule
17. COVERAGE REPORT :

You might also like