KEMBAR78
Amba Apb Assignment | PDF | Software Engineering | Telecommunications
0% found this document useful (0 votes)
333 views19 pages

Amba Apb Assignment

The document describes a UVM testbench for an AMBA APB slave module. It includes: 1. The slave DUT module definition 2. A transaction class for the APB interface 3. An interface definition for the APB signals

Uploaded by

Divya srivastava
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
333 views19 pages

Amba Apb Assignment

The document describes a UVM testbench for an AMBA APB slave module. It includes: 1. The slave DUT module definition 2. A transaction class for the APB interface 3. An interface definition for the APB signals

Uploaded by

Divya srivastava
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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