@@ -0,0 +1,211 @@ | |||||
class axi_driver extends uvm_driver#(axi_seq_item); | |||||
`uvm_component_utils(axi_driver) | |||||
virtual intf vif; | |||||
axi_seq_item tx; | |||||
int temp[]; | |||||
int burst_len; | |||||
int burst_size; | |||||
int total_tr; | |||||
int wrap_lower_boundary; | |||||
int wrap_upper_boundary; | |||||
function new(string name="axi_driver",uvm_component_parent); | |||||
super.new(name,parent); | |||||
endfunction | |||||
function void build_phase(uvm_phase phase); | |||||
super.new(); | |||||
tx=axi_seq_item::type_id::create("tx",this); | |||||
if(!uvm_config_db#(virtual intf)::get("this",*,"intf",vif) | |||||
`uvm_error(get_type_name(),$sformatf("failed for get vif")) | |||||
endfunction | |||||
task run_phase(uvm_phase phase) | |||||
forever begin | |||||
seq_item_port.get_next_item(tx); | |||||
drive(); | |||||
seq_item_port.item_done(tx); | |||||
end | |||||
endtask | |||||
task drive(); | |||||
if(tx.wr_rd) | |||||
begin | |||||
write_address(); | |||||
write_data(); | |||||
write_response(); | |||||
end | |||||
else | |||||
read_address(); | |||||
endtask | |||||
////////write address/////// | |||||
task write_adress(); | |||||
@(posedge vif.clk) | |||||
tx.awvalid<=1; | |||||
vif.awvalid<=tx.awvalid; | |||||
vif.awid<=tx.awid; | |||||
//vif.awaddr<=tx.awaddr; | |||||
vif.awsize<=tx.awsize; | |||||
vif.awlen<=tx.awlen; | |||||
vif.awburst<=tx.awburst; | |||||
//////////fixed burst//////////// | |||||
if(tx.awburst==2'b00) | |||||
vif.awaddr<=tx.awaddr; | |||||
////////increament burst//////// | |||||
else if(awburst==2'b01)begin | |||||
vif.awaddr<=tx.awaddr; | |||||
for(i=0;i<awlen;i++) | |||||
vif.awaddr<=(tx.awaddr+(2**awsize)); | |||||
end | |||||
////////wrap burst///////// | |||||
else if(tx.awburst=2'b10)begin | |||||
begin | |||||
if(((tx.awaddr)%2**awsize)==0)begin | |||||
burst_len=tx.awlen+1; | |||||
burst_size=2**(tx.awsize); | |||||
total_tr=burst_len*burst_size; | |||||
wrap_lower_boundary=int'((tx.awaddr)/(total_tr))*total_tr; | |||||
wrap_upper_boundary=wrap_lower_boundary+total_tr; | |||||
end | |||||
vif.awlock<=tx.awlock; | |||||
@(posedge vif.clk) | |||||
wait(vif.awready) | |||||
@(posedge vif.clk) | |||||
tx.awvalid<=0; | |||||
vif.awvalid<=tx.awvalid; | |||||
endtask | |||||
//////write data/////////// | |||||
task write_data(); | |||||
@posedge vif.clk) | |||||
tx.wvalid<=1; | |||||
vif.wvalid<=tx.wvalid; | |||||
vif.wid<=tx.wid; | |||||
foreach(tx.wdata[i,j]) | |||||
begin | |||||
temp[i][8*i+:8]<=tx.wdata[i][j]; | |||||
end | |||||
for(i=0;i<awlen+1;i++); | |||||
begin | |||||
vif.wdata<=temp[i]; | |||||
tx.wvalid<=1; | |||||
vif.wvalid<=tx.wvalid; | |||||
vif.wlast<=awlen==i?1:0; | |||||
end | |||||
wait(vif.wready); | |||||
//endtask | |||||
@posedge vif.clk) | |||||
tx.wvalid<=0; | |||||
vif.wvalid<=tx.wvalid; | |||||
endtask | |||||
//////////write response ////////// | |||||
task write_response(); | |||||
@posedge vif.clk) | |||||
vif.bid<=tx.bid; | |||||
vif.bresp<=tx.bresp; | |||||
tx.bvalid<=1; | |||||
vif.bvalid<=tx.bvalid; | |||||
@posedge vif.clk) | |||||
wait(vif.bready); | |||||
@posedge vif.clk) | |||||
tx.bvalid<=0; | |||||
vif.bvalid<=tx.bvalid; | |||||
endtask | |||||
/////////read address///////// | |||||
task read_adress(); | |||||
@(posedge vif.clk) | |||||
tx.arvalid<=1; | |||||
vif.arvalid<=tx.arvalid; | |||||
vif.arid<=tx.arid; | |||||
//vif.araddr<=tx.araddr; | |||||
vif.arsize<=tx.arsize; | |||||
vif.arlen<=tx.arlen; | |||||
vif.arburst<=tx.arburst; | |||||
//////////fixed burst//////////// | |||||
if(tx.arburst==2'b00) | |||||
vif.araddr<=tx.araddr; | |||||
vif.arid<=tx.arid; | |||||
////////increament burst//////// | |||||
else if(arburst==2'b01)begin | |||||
vif.araddr<=tx.araddr; | |||||
for(i=0;i<arlen;i++) | |||||
begin | |||||
vif.arid<=tx.arid; | |||||
vif.araddr<=(tx.araddr+(2**arsize)); | |||||
end | |||||
////////wrap burst///////// | |||||
else if(tx.arburst=2'b10)begin | |||||
begin | |||||
if(((tx.araddr)%2**arsize)==0)begin | |||||
vif.arid<=tx.arid; | |||||
burst_len=tx.arlen+1; | |||||
burst_size=2**(tx.arsize); | |||||
total_tr=burst_len*burst_size; | |||||
wrap_lower_boundary=int'((tx.araddr)/(total_tr))*total_tr; | |||||
wrap_upper_boundary=wrap_lower_boundary+total_tr; | |||||
end | |||||
vif.arlock<=tx.arlock; | |||||
@(posedge vif.clk) | |||||
wait(vif.arready) | |||||
@(posedge vif.clk) | |||||
tx.arvalid<=0; | |||||
vif.arvalid<=tx.arvalid; | |||||
endtask | |||||
endclass | |||||
@@ -0,0 +1,85 @@ | |||||
// axi write sequence | |||||
class axi_write_sequence extends uvm_sequence#(axi_seq_item); | |||||
`uvm_object_utils(axi_write_sequence); | |||||
function new(string name="axi_write_sequence"); | |||||
super.new(name); | |||||
endfunction | |||||
task body(); | |||||
req=axi_seq_item::type_id::create(req); | |||||
start_item(req); | |||||
assert(req.randomize()with{req.wr_rd==1;req.awaddr==0x08;req.awburst==2'b 10;req.awlen==3;req.awsize==2;req.wdata==0x22fb;}); | |||||
finish_item(req); | |||||
endtask | |||||
endclass | |||||
// axi_read_sequence | |||||
class axi_read_sequence extends uvm_sequence#(axi_seq_item); | |||||
`uvm_object_utils(axi_read_sequence); | |||||
function new(string name="axi_read_sequence"); | |||||
super.new(name); | |||||
endfunction | |||||
task body(); | |||||
req=axi_seq_item::type_id::create(req); | |||||
start_item(req); | |||||
assert(req.randomize()with{req.wr_rd==0;req.araddr==0x08;arlen==3;arburst==2'b 10;}); | |||||
finish_item(req); | |||||
endtask | |||||
endclass | |||||
// axi aligned sequence | |||||
class axi_aligned_sequence extends uvm_sequence#(axi_seq_item); | |||||
`uvm_object_utils(axi_aligned_sequence); | |||||
function new(string name="axi_aligned_sequence"); | |||||
super.new(name); | |||||
endfunction | |||||
task body(); | |||||
req=axi_seq_item::type_id::create(req); | |||||
start_item(req); | |||||
assert(req.randomize()with{req.wr_rd==1;req.awaddr==0x08;req.awsize==3;req.awburst==2'b 10;req.wdata==0xfa30;}); | |||||
finish_item(req); | |||||
endtask | |||||
endclass | |||||
// write followed by read | |||||
class write_read_sequence extends uvm_sequence#(axi_seq_item); | |||||
`uvm_object_utils(write_read_sequence); | |||||
axi_write_sequence axi_wr_seq; | |||||
axi_read_sequence axi_rd_seq; | |||||
function new(string name="write_read_sequence"); | |||||
super.new(name); | |||||
endfunction | |||||
task body(); | |||||
`uvm_do(axi_wr_seq); | |||||
`uvm_do(axi_rd_seq); | |||||
end | |||||
endclass | |||||
@@ -0,0 +1,125 @@ | |||||
`include "uvm_macros.svh" | |||||
import uvm_pkg::*; | |||||
class axi_seq_item extends uvm_seq_item; | |||||
//'uvm_object_utils(axi_seq_item); | |||||
function new(string name="axi_seq_item") | |||||
super.new(name); | |||||
endfunction | |||||
//write adress channel signals | |||||
rand bit wr_rd; | |||||
rand bit [3:0] awid; | |||||
rand logic[31:0] awaddr; | |||||
rand logic[2:0] awsize; | |||||
rand logic[3:0] awlen; | |||||
rand logic[1:0] awburst; | |||||
rand logic[1:0] awlock; | |||||
logic awvalid; | |||||
logic awready; | |||||
//write data channel | |||||
rand bit [3:0] wid; | |||||
rand logic[31:0] wdata[][]; | |||||
logic[3:0] wstrb; | |||||
logic wlast; | |||||
logic wvalid; | |||||
logic wready; | |||||
// write response channel | |||||
rand bit []3:0]bid; | |||||
logic[1:0] bresp; | |||||
logic bvalid; | |||||
logic bready; | |||||
// read adress channel | |||||
rand bit [3:0] arid; | |||||
rand logic[31:0] araddr; | |||||
rand logic[2:0] arsize; | |||||
rand logic[3:0] arlen; | |||||
rand logic[1:0] arburst; | |||||
rand logic[1:0] arlock; | |||||
logic arvalid; | |||||
logic arready; | |||||
// read data channel | |||||
rand bit [3:0] rid; | |||||
logic[31:0] rdata; | |||||
logic[3:0]rresp; | |||||
logic rlast; | |||||
logic rvalid; | |||||
logic rready; | |||||
`uvm_object_utils_begin(axi_seq_item) | |||||
`uvm_field_int(awid,UVM_ALL_ON) | |||||
`uvm_field_int(awaddr,UVM_ALL_ON) | |||||
`uvm_field_int(awsize,UVM_ALL_ON) | |||||
`uvm_field_int(awlen,UVM_ALL_ON) | |||||
`uvm_field_int(awburst,UVM_ALL_ON) | |||||
`uvm_field_int(awlock,UVM_ALL_ON) | |||||
`uvm_field_int(awvalid,UVM_ALL_ON) | |||||
`uvm_field_int(awready,UVM_ALL_ON) | |||||
`uvm_field_int(wid,UVM_ALL_ON) | |||||
`uvm_field_int(wdata,UVM_ALL_ON) | |||||
`uvm_field_int(wlast,UVM_ALL_ON) | |||||
`uvm_field_int(wstrb,UVM_ALL_ON) | |||||
`uvm_field_int(wvalid,UVM_ALL_ON) | |||||
`uvm_field_int(wready,UVM_ALL_ON) | |||||
`uvm_field_int(bid,UVM_ALL_ON) | |||||
`uvm_field_int(bresp,UVM_ALL_ON) | |||||
`uvm_field_int(bvalid,UVM_ALL_ON) | |||||
`uvm_field_int(bready,UVM_ALL_ON) | |||||
`uvm_field_int(arid,UVM_ALL_ON) | |||||
`uvm_field_int(araddr,UVM_ALL_ON) | |||||
`uvm_field_int(arsize,UVM_ALL_ON) | |||||
`uvm_field_int(arlen,UVM_ALL_ON) | |||||
`uvm_field_int(arsize,UVM_ALL_ON) | |||||
`uvm_field_int(arburst,UVM_ALL_ON) | |||||
`uvm_field_int(arlock,UVM_ALL_ON) | |||||
`uvm_field_int(arvalid,UVM_ALL_ON) | |||||
`uvm_field_int(arready,UVM_ALL_ON) | |||||
`uvm_field_int(rid,UVM_ALL_ON) | |||||
`uvm_field_int(rdata,UVM_ALL_ON) | |||||
`uvm_field_int(rlast,UVM_ALL_ON) | |||||
`uvm_field_int(rresp,UVM_ALL_ON) | |||||
`uvm_field_int(rvalid,UVM_ALL_ON) | |||||
`uvm_field_int(rready,UVM_ALL_ON) | |||||
`uvm_object_utils_end | |||||
//constraints for axi | |||||
constraint aligned_addr{awadd%2**awsize==0;} | |||||
constraint wrap_addr{solve awburst before awlen | |||||
if(awburst==2'b 10) | |||||
awlen inside{1,3,7,15};} | |||||
constraint wid_sig{awid==wid;} | |||||
constraint rid_sig{arid==rid;} | |||||
constraint axi_4kb{awaddr%4096+(2**awsize*(awlen+1))<=4096;} | |||||
//:constrain | |||||
endclass:axi_seq_item | |||||