|
@@ -0,0 +1,707 @@ |
|
|
|
|
|
`timescale 1ns / 1ps |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
module tb(); |
|
|
|
|
|
|
|
|
|
|
|
reg presetn = 0; |
|
|
|
|
|
reg pclk = 0; |
|
|
|
|
|
reg psel = 0; |
|
|
|
|
|
reg penable = 0 ; |
|
|
|
|
|
reg pwrite = 0; |
|
|
|
|
|
reg [31:0] paddr = 0, pwdata = 0; |
|
|
|
|
|
wire [31:0] prdata; |
|
|
|
|
|
wire pready, pslverr; |
|
|
|
|
|
|
|
|
|
|
|
apb_ram dut (presetn, pclk, psel, penable, pwrite, paddr, pwdata, prdata, pready, pslverr); |
|
|
|
|
|
|
|
|
|
|
|
always #10 pclk = ~pclk; |
|
|
|
|
|
|
|
|
|
|
|
initial begin |
|
|
|
|
|
presetn = 0; |
|
|
|
|
|
repeat(5) @(posedge pclk); |
|
|
|
|
|
presetn = 1; |
|
|
|
|
|
psel = 1; |
|
|
|
|
|
pwrite = 1; |
|
|
|
|
|
paddr = 12; |
|
|
|
|
|
pwdata = 35; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
penable = 1; |
|
|
|
|
|
@(posedge pready); |
|
|
|
|
|
psel = 0; |
|
|
|
|
|
penable = 0; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
psel = 1; |
|
|
|
|
|
pwrite = 1'b0; |
|
|
|
|
|
paddr = 12; |
|
|
|
|
|
pwdata = 35; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
penable = 1'b1; |
|
|
|
|
|
@(posedge pready); |
|
|
|
|
|
psel = 0; |
|
|
|
|
|
penable = 0; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
psel = 1; |
|
|
|
|
|
pwrite = 1; |
|
|
|
|
|
paddr = 45; |
|
|
|
|
|
pwdata = 35; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
penable = 1; |
|
|
|
|
|
@(posedge pready); |
|
|
|
|
|
psel = 0; |
|
|
|
|
|
penable = 0; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
psel = 1; |
|
|
|
|
|
pwrite = 0; |
|
|
|
|
|
paddr = 45; |
|
|
|
|
|
pwdata = 35; |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
penable = 1; |
|
|
|
|
|
@(posedge pready); |
|
|
|
|
|
@(posedge pclk); |
|
|
|
|
|
$stop(); |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endmodule |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
`include "uvm_macros.svh" |
|
|
|
|
|
import uvm_pkg::*; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
class abp_config extends uvm_object; /////configuration of env |
|
|
|
|
|
`uvm_object_utils(abp_config) |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "abp_config"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uvm_active_passive_enum is_active = UVM_ACTIVE; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum bit [1:0] {readd = 0, writed = 1, rst = 2} oper_mode; |
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class transaction extends uvm_sequence_item; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rand oper_mode op; |
|
|
|
|
|
rand logic PWRITE; |
|
|
|
|
|
rand logic [31 : 0] PWDATA; |
|
|
|
|
|
rand logic [31 : 0] PADDR; |
|
|
|
|
|
|
|
|
|
|
|
// Output Signals of DUT for APB UART's transaction |
|
|
|
|
|
logic PREADY; |
|
|
|
|
|
logic PSLVERR; |
|
|
|
|
|
logic [31: 0] PRDATA; |
|
|
|
|
|
|
|
|
|
|
|
`uvm_object_utils_begin(transaction) |
|
|
|
|
|
`uvm_field_int (PWRITE,UVM_ALL_ON) |
|
|
|
|
|
`uvm_field_int (PWDATA,UVM_ALL_ON) |
|
|
|
|
|
`uvm_field_int (PADDR,UVM_ALL_ON) |
|
|
|
|
|
`uvm_field_int (PREADY,UVM_ALL_ON) |
|
|
|
|
|
`uvm_field_int (PSLVERR,UVM_ALL_ON) |
|
|
|
|
|
`uvm_field_int (PRDATA,UVM_ALL_ON) |
|
|
|
|
|
`uvm_field_enum(oper_mode, op, UVM_DEFAULT) |
|
|
|
|
|
`uvm_object_utils_end |
|
|
|
|
|
|
|
|
|
|
|
constraint addr_c { PADDR <= 31; } |
|
|
|
|
|
constraint addr_c_err { PADDR > 31; } |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "transaction"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
endclass : transaction |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
|
|
/* |
|
|
|
|
|
module tb; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
initial begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.randomize(); |
|
|
|
|
|
tr.print(); |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
endmodule |
|
|
|
|
|
*/ |
|
|
|
|
|
////////////////////////////////////////////////////////////////// |
|
|
|
|
|
///////////////////write seq |
|
|
|
|
|
class write_data extends uvm_sequence#(transaction); |
|
|
|
|
|
`uvm_object_utils(write_data) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "write_data"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
repeat(15) |
|
|
|
|
|
begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(1);//enable |
|
|
|
|
|
tr.addr_c_err.constraint_mode(0);//disable |
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = writed; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
////////////////////////////////////////////////////////// |
|
|
|
|
|
////////////////////////read seq |
|
|
|
|
|
class read_data extends uvm_sequence#(transaction); |
|
|
|
|
|
`uvm_object_utils(read_data) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "read_data"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
repeat(15) |
|
|
|
|
|
begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(1); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(0);//disable |
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = readd; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class write_read extends uvm_sequence#(transaction); //////read after write |
|
|
|
|
|
`uvm_object_utils(write_read) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "write_read"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
repeat(15) |
|
|
|
|
|
begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(1); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(0); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = writed; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = readd; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
/////////////////////////////////////////////////////// |
|
|
|
|
|
///////////////write bulk read bulk |
|
|
|
|
|
class writeb_readb extends uvm_sequence#(transaction); |
|
|
|
|
|
`uvm_object_utils(writeb_readb) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "writeb_readb"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
|
|
|
|
|
|
repeat(15) begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(1); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(0); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = writed; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
repeat(15) begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(1); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(0); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = readd; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////// |
|
|
|
|
|
//////////////////////slv_error_write |
|
|
|
|
|
class write_err extends uvm_sequence#(transaction); |
|
|
|
|
|
`uvm_object_utils(write_err) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "write_err"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
repeat(15) |
|
|
|
|
|
begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(0); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(1); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = writed; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
|
|
/////////////////////////read err |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class read_err extends uvm_sequence#(transaction); |
|
|
|
|
|
`uvm_object_utils(read_err) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "read_err"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
repeat(15) |
|
|
|
|
|
begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(0); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(1); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = readd; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class reset_dut extends uvm_sequence#(transaction); |
|
|
|
|
|
`uvm_object_utils(reset_dut) |
|
|
|
|
|
|
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
function new(string name = "reset_dut"); |
|
|
|
|
|
super.new(name); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task body(); |
|
|
|
|
|
repeat(15) |
|
|
|
|
|
begin |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
tr.addr_c.constraint_mode(1); |
|
|
|
|
|
tr.addr_c_err.constraint_mode(0); |
|
|
|
|
|
|
|
|
|
|
|
start_item(tr); |
|
|
|
|
|
assert(tr.randomize); |
|
|
|
|
|
tr.op = rst; |
|
|
|
|
|
finish_item(tr); |
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////// |
|
|
|
|
|
class driver extends uvm_driver #(transaction); |
|
|
|
|
|
`uvm_component_utils(driver) |
|
|
|
|
|
|
|
|
|
|
|
virtual apb_if vif; |
|
|
|
|
|
transaction tr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function new(input string path = "drv", uvm_component parent = null); |
|
|
|
|
|
super.new(path,parent); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
|
|
|
super.build_phase(phase); |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
|
|
|
|
|
|
if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))//uvm_test_top.env.agent.drv.aif |
|
|
|
|
|
`uvm_error("drv","Unable to access Interface"); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
task reset_dut(); |
|
|
|
|
|
|
|
|
|
|
|
repeat(5) |
|
|
|
|
|
begin |
|
|
|
|
|
vif.presetn <= 1'b0; |
|
|
|
|
|
vif.paddr <= 'h0; |
|
|
|
|
|
vif.pwdata <= 'h0; |
|
|
|
|
|
vif.pwrite <= 'b0; |
|
|
|
|
|
vif.psel <= 'b0; |
|
|
|
|
|
vif.penable <= 'b0; |
|
|
|
|
|
`uvm_info("DRV", "System Reset : Start of Simulation", UVM_MEDIUM); |
|
|
|
|
|
@(posedge vif.pclk); |
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
task drive(); |
|
|
|
|
|
reset_dut(); |
|
|
|
|
|
forever begin |
|
|
|
|
|
|
|
|
|
|
|
seq_item_port.get_next_item(tr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(tr.op == rst) |
|
|
|
|
|
begin |
|
|
|
|
|
vif.presetn <= 1'b0; |
|
|
|
|
|
vif.paddr <= 'h0; |
|
|
|
|
|
vif.pwdata <= 'h0; |
|
|
|
|
|
vif.pwrite <= 'b0; |
|
|
|
|
|
vif.psel <= 'b0; |
|
|
|
|
|
vif.penable <= 'b0; |
|
|
|
|
|
@(posedge vif.pclk); |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
else if(tr.op == writed) |
|
|
|
|
|
begin |
|
|
|
|
|
vif.psel <= 1'b1; |
|
|
|
|
|
vif.paddr <= tr.PADDR; |
|
|
|
|
|
vif.pwdata <= tr.PWDATA; |
|
|
|
|
|
vif.presetn <= 1'b1; |
|
|
|
|
|
vif.pwrite <= 1'b1; |
|
|
|
|
|
@(posedge vif.pclk); |
|
|
|
|
|
vif.penable <= 1'b1; |
|
|
|
|
|
`uvm_info("DRV", $sformatf("mode:%0s, addr:%0d, wdata:%0d, rdata:%0d, slverr:%0d",tr.op.name(),tr.PADDR,tr.PWDATA,tr.PRDATA,tr.PSLVERR), UVM_NONE); |
|
|
|
|
|
@(negedge vif.pready); |
|
|
|
|
|
vif.penable <= 1'b0; |
|
|
|
|
|
tr.PSLVERR = vif.pslverr; |
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
else if(tr.op == readd) |
|
|
|
|
|
begin |
|
|
|
|
|
vif.psel <= 1'b1; |
|
|
|
|
|
vif.paddr <= tr.PADDR; |
|
|
|
|
|
vif.presetn <= 1'b1; |
|
|
|
|
|
vif.pwrite <= 1'b0; |
|
|
|
|
|
@(posedge vif.pclk); |
|
|
|
|
|
vif.penable <= 1'b1; |
|
|
|
|
|
`uvm_info("DRV", $sformatf("mode:%0s, addr:%0d, wdata:%0d, rdata:%0d, slverr:%0d",tr.op.name(),tr.PADDR,tr.PWDATA,tr.PRDATA,tr.PSLVERR), UVM_NONE); |
|
|
|
|
|
@(negedge vif.pready); |
|
|
|
|
|
vif.penable <= 1'b0; |
|
|
|
|
|
tr.PRDATA = vif.prdata; |
|
|
|
|
|
tr.PSLVERR = vif.pslverr; |
|
|
|
|
|
end |
|
|
|
|
|
seq_item_port.item_done(); |
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual task run_phase(uvm_phase phase); |
|
|
|
|
|
drive(); |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class mon extends uvm_monitor; |
|
|
|
|
|
`uvm_component_utils(mon) |
|
|
|
|
|
|
|
|
|
|
|
uvm_analysis_port#(transaction) send; |
|
|
|
|
|
transaction tr; |
|
|
|
|
|
virtual apb_if vif; |
|
|
|
|
|
|
|
|
|
|
|
function new(input string inst = "mon", uvm_component parent = null); |
|
|
|
|
|
super.new(inst,parent); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
|
|
|
super.build_phase(phase); |
|
|
|
|
|
tr = transaction::type_id::create("tr"); |
|
|
|
|
|
send = new("send", this); |
|
|
|
|
|
if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))//uvm_test_top.env.agent.drv.aif |
|
|
|
|
|
`uvm_error("MON","Unable to access Interface"); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual task run_phase(uvm_phase phase); |
|
|
|
|
|
forever begin |
|
|
|
|
|
@(posedge vif.pclk); |
|
|
|
|
|
if(!vif.presetn) |
|
|
|
|
|
begin |
|
|
|
|
|
tr.op = rst; |
|
|
|
|
|
`uvm_info("MON", "SYSTEM RESET DETECTED", UVM_NONE); |
|
|
|
|
|
send.write(tr); |
|
|
|
|
|
end |
|
|
|
|
|
else if (vif.presetn && vif.pwrite) |
|
|
|
|
|
begin |
|
|
|
|
|
@(negedge vif.pready); |
|
|
|
|
|
tr.op = writed; |
|
|
|
|
|
tr.PWDATA = vif.pwdata; |
|
|
|
|
|
tr.PADDR = vif.paddr; |
|
|
|
|
|
tr.PSLVERR = vif.pslverr; |
|
|
|
|
|
`uvm_info("MON", $sformatf("DATA WRITE addr:%0d data:%0d slverr:%0d",tr.PADDR,tr.PWDATA,tr.PSLVERR), UVM_NONE); |
|
|
|
|
|
send.write(tr); |
|
|
|
|
|
end |
|
|
|
|
|
else if (vif.presetn && !vif.pwrite) |
|
|
|
|
|
begin |
|
|
|
|
|
@(negedge vif.pready); |
|
|
|
|
|
tr.op = readd; |
|
|
|
|
|
tr.PADDR = vif.paddr; |
|
|
|
|
|
tr.PRDATA = vif.prdata; |
|
|
|
|
|
tr.PSLVERR = vif.pslverr; |
|
|
|
|
|
`uvm_info("MON", $sformatf("DATA READ addr:%0d data:%0d slverr:%0d",tr.PADDR, tr.PRDATA,tr.PSLVERR), UVM_NONE); |
|
|
|
|
|
send.write(tr); |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
endtask |
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class sco extends uvm_scoreboard; |
|
|
|
|
|
`uvm_component_utils(sco) |
|
|
|
|
|
|
|
|
|
|
|
uvm_analysis_imp#(transaction,sco) recv; |
|
|
|
|
|
bit [31:0] arr[32] = '{default:0}; |
|
|
|
|
|
bit [31:0] addr = 0; |
|
|
|
|
|
bit [31:0] data_rd = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function new(input string inst = "sco", uvm_component parent = null); |
|
|
|
|
|
super.new(inst,parent); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
|
|
|
super.build_phase(phase); |
|
|
|
|
|
recv = new("recv", this); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual function void write(transaction tr); |
|
|
|
|
|
if(tr.op == rst) |
|
|
|
|
|
begin |
|
|
|
|
|
`uvm_info("SCO", "SYSTEM RESET DETECTED", UVM_NONE); |
|
|
|
|
|
end |
|
|
|
|
|
else if (tr.op == writed) |
|
|
|
|
|
begin |
|
|
|
|
|
if(tr.PSLVERR == 1'b1) |
|
|
|
|
|
begin |
|
|
|
|
|
`uvm_info("SCO", "SLV ERROR during WRITE OP", UVM_NONE); |
|
|
|
|
|
end |
|
|
|
|
|
else |
|
|
|
|
|
begin |
|
|
|
|
|
arr[tr.PADDR] = tr.PWDATA; |
|
|
|
|
|
`uvm_info("SCO", $sformatf("DATA WRITE OP addr:%0d, wdata:%0d arr_wr:%0d",tr.PADDR,tr.PWDATA, arr[tr.PADDR]), UVM_NONE); |
|
|
|
|
|
end |
|
|
|
|
|
end |
|
|
|
|
|
else if (tr.op == readd) |
|
|
|
|
|
begin |
|
|
|
|
|
if(tr.PSLVERR == 1'b1) |
|
|
|
|
|
begin |
|
|
|
|
|
`uvm_info("SCO", "SLV ERROR during READ OP", UVM_NONE); |
|
|
|
|
|
end |
|
|
|
|
|
else |
|
|
|
|
|
begin |
|
|
|
|
|
data_rd = arr[tr.PADDR]; |
|
|
|
|
|
if (data_rd == tr.PRDATA) |
|
|
|
|
|
`uvm_info("SCO", $sformatf("DATA MATCHED : addr:%0d, rdata:%0d",tr.PADDR,tr.PRDATA), UVM_NONE) |
|
|
|
|
|
else |
|
|
|
|
|
`uvm_info("SCO",$sformatf("TEST FAILED : addr:%0d, rdata:%0d data_rd_arr:%0d",tr.PADDR,tr.PRDATA,data_rd), UVM_NONE) |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$display("----------------------------------------------------------------"); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class agent extends uvm_agent; |
|
|
|
|
|
`uvm_component_utils(agent) |
|
|
|
|
|
|
|
|
|
|
|
abp_config cfg; |
|
|
|
|
|
|
|
|
|
|
|
function new(input string inst = "agent", uvm_component parent = null); |
|
|
|
|
|
super.new(inst,parent); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
driver d; |
|
|
|
|
|
uvm_sequencer#(transaction) seqr; |
|
|
|
|
|
mon m; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
|
|
|
super.build_phase(phase); |
|
|
|
|
|
cfg = abp_config::type_id::create("cfg"); |
|
|
|
|
|
m = mon::type_id::create("m",this); |
|
|
|
|
|
|
|
|
|
|
|
if(cfg.is_active == UVM_ACTIVE) |
|
|
|
|
|
begin |
|
|
|
|
|
d = driver::type_id::create("d",this); |
|
|
|
|
|
seqr = uvm_sequencer#(transaction)::type_id::create("seqr", this); |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual function void connect_phase(uvm_phase phase); |
|
|
|
|
|
super.connect_phase(phase); |
|
|
|
|
|
if(cfg.is_active == UVM_ACTIVE) begin |
|
|
|
|
|
d.seq_item_port.connect(seqr.seq_item_export); |
|
|
|
|
|
end |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class env extends uvm_env; |
|
|
|
|
|
`uvm_component_utils(env) |
|
|
|
|
|
|
|
|
|
|
|
function new(input string inst = "env", uvm_component c); |
|
|
|
|
|
super.new(inst,c); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
agent a; |
|
|
|
|
|
sco s; |
|
|
|
|
|
|
|
|
|
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
|
|
|
super.build_phase(phase); |
|
|
|
|
|
a = agent::type_id::create("a",this); |
|
|
|
|
|
s = sco::type_id::create("s", this); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual function void connect_phase(uvm_phase phase); |
|
|
|
|
|
super.connect_phase(phase); |
|
|
|
|
|
a.m.send.connect(s.recv); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
class test extends uvm_test; |
|
|
|
|
|
`uvm_component_utils(test) |
|
|
|
|
|
|
|
|
|
|
|
function new(input string inst = "test", uvm_component c); |
|
|
|
|
|
super.new(inst,c); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
env e; |
|
|
|
|
|
write_read wrrd; |
|
|
|
|
|
writeb_readb wrrdb; |
|
|
|
|
|
write_data wdata; |
|
|
|
|
|
read_data rdata; |
|
|
|
|
|
write_err werr; |
|
|
|
|
|
read_err rerr; |
|
|
|
|
|
reset_dut rstdut; |
|
|
|
|
|
|
|
|
|
|
|
virtual function void build_phase(uvm_phase phase); |
|
|
|
|
|
super.build_phase(phase); |
|
|
|
|
|
e = env::type_id::create("env",this); |
|
|
|
|
|
wrrd = write_read::type_id::create("wrrd"); |
|
|
|
|
|
wdata = write_data::type_id::create("wdata"); |
|
|
|
|
|
rdata = read_data::type_id::create("rdata"); |
|
|
|
|
|
wrrdb = writeb_readb::type_id::create("wrrdb"); |
|
|
|
|
|
werr = write_err::type_id::create("werr"); |
|
|
|
|
|
rerr = read_err::type_id::create("rerr"); |
|
|
|
|
|
rstdut = reset_dut::type_id::create("rstdut"); |
|
|
|
|
|
endfunction |
|
|
|
|
|
|
|
|
|
|
|
virtual task run_phase(uvm_phase phase); |
|
|
|
|
|
phase.raise_objection(this); |
|
|
|
|
|
wrrdb.start(e.a.seqr); |
|
|
|
|
|
#20; |
|
|
|
|
|
phase.drop_objection(this); |
|
|
|
|
|
endtask |
|
|
|
|
|
endclass |
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
module tb; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apb_if vif(); |
|
|
|
|
|
|
|
|
|
|
|
apb_ram dut (.presetn(vif.presetn), .pclk(vif.pclk), .psel(vif.psel), .penable(vif.penable), .pwrite(vif.pwrite), .paddr(vif.paddr), .pwdata(vif.pwdata), .prdata(vif.prdata), .pready(vif.pready), .pslverr(vif.pslverr)); |
|
|
|
|
|
|
|
|
|
|
|
initial begin |
|
|
|
|
|
vif.pclk <= 0; |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
always #10 vif.pclk <= ~vif.pclk; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initial begin |
|
|
|
|
|
uvm_config_db#(virtual apb_if)::set(null, "*", "vif", vif); |
|
|
|
|
|
run_test("test"); |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initial begin |
|
|
|
|
|
$dumpfile("dump.vcd"); |
|
|
|
|
|
$dumpvars; |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endmodule |