|
发表于 2017-12-6 15:00:32
|
显示全部楼层
写得一般,但是能用:
bit [31:0] mem[*];
bit [31:0] apb_base_addr;
bit [31:0] apb_seg_size;
`uvm_component_utils_begin(apb_bfm)
`uvm_component_utils_end
//////////////////////////////////////////////////////////////////////
/// Creates new ntb_gsyncPxl_monitor object.
function new(string name = "apb_bfm", uvm_component parent);
super.new(name, parent);
endfunction
//////////////////////////////////////////////////////////////////////
/// Called automatically during UVM build phase.
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_int::get(this,"","apb_base_addr", apb_base_addr)) begin
`uvm_fatal("ERROR", "APB base address should be assigned to apb_bfm")
end
if (!uvm_config_int::get(this,"","apb_seg_size", apb_seg_size)) begin
`uvm_fatal("ERROR", "APB segment size should be assigned to apb_bfm")
end
endfunction
//////////////////////////////////////////////////////////////////////
/// Called automatically during UVM connect phase.
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// Hook up the virtual interface here
if (!uvm_config_db#(virtual nitro_apb_slave_if)::get(this, "", "apb_slv_if", apb_slv_if)) begin
`uvm_fatal("HDCP/KEY/RAM/IF", "No virtual interface specified for this monitor instance")
end
endfunction
//////////////////////////////////////////////////////////////////////
/// Called automatically during UVM end of elaboration phase.
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
endfunction
//////////////////////////////////////////////////////////////////////
/// Called automatically during UVM start of simulation phase.
function void start_of_simulation_phase(uvm_phase phase);
super.start_of_simulation_phase(phase);
endfunction
//////////////////////////////////////////////////////////////////////
/// Called automatically during UVM reset phase.
task reset_phase(uvm_phase phase);
super.reset_phase(phase);
endtask
//////////////////////////////////////////////////////////////////////
/// Called automatically during UVM configure phase.
task configure_phase(uvm_phase phase);
super.configure_phase(phase);
endtask
task apb_op_with_random_ready();
bit [7:0] ready_on;
bit [7:0] ready_off;
forever begin
@(apb_slv_if.sck);
if(apb_slv_if.presetn !== 1) begin
apb_slv_if.prdata <= 'h0;
apb_slv_if.pready <= 1'b0;
continue;
end
else begin
std::randomize(ready_on, ready_off) with {ready_on dist {1 :/ 1, [2:16] :/ 1}; ready_off dist {1 :/ 1, [2:128] :/ 3, [128:256] :/ 1};};
apb_slv_if.pready <= 1'b1;
repeat(ready_on) @(apb_slv_if.sck);
apb_slv_if.pready <= 1'b0;
repeat(ready_off) @(apb_slv_if.sck);
end
end
endtask
task apb_access_op();
bit [20:0] apb_addr;
forever begin
@(apb_slv_if.sck);
if(apb_slv_if.presetn !== 1) begin
continue;
end
else begin
if(apb_slv_if.psel == 1'b1 && apb_slv_if.penable == 1'b1) begin
apb_addr = apb_slv_if.paddr[13:0];
if(apb_slv_if.pwrite == 1'b1) begin
// get pwdata
mem[apb_addr] = apb_slv_if.pwdata;
`uvm_info(get_name, $psprintf("Ext_APB Write %h to Addr %h", apb_slv_if.pwdata, apb_addr), UVM_INFO)
end
else begin
// send prdata
`uvm_info(get_name, $psprintf("Ext_APB Read %h, and return %h", apb_addr, mem[apb_addr]), UVM_INFO)
if(mem.exists(apb_addr)) begin
apb_slv_if.prdata <= mem[apb_addr];
end
else begin
apb_slv_if.prdata <= 'h0;
end
end
end
end
end
endtask
task apb_sel_check();
forever begin
@(apb_slv_if.sck);
if(apb_slv_if.presetn !== 1) begin
continue;
end
else begin
if(!(apb_slv_if.paddr >= apb_base_addr && apb_slv_if.paddr < apb_base_addr + apb_seg_size)) begin
if(apb_slv_if.psel == 1) begin
`uvm_error("ERROR", $psprintf("psel should not be set 1"));
end
end
end
end
endtask
task apb_op_with_ready();
bit [20:0] apb_addr;
forever begin
@(apb_slv_if.sck);
if(apb_slv_if.presetn !== 1) begin
apb_slv_if.prdata <= 'h0;
apb_slv_if.pready <= 1'b0;
continue;
end
else begin
apb_slv_if.pready <= 1'b1;
end
end
endtask
//////////////////////////////////////////////////////////////////////
/// Automatically runs during the UVM run phase.
task run_phase(uvm_phase phase);
int apb_ready_random;
super.run_phase(phase);
if($value$plusargs("apb_ready_random=%d", apb_ready_random)) begin
if(apb_ready_random == 1) begin
fork
apb_op_with_random_ready();
join_none
end
else begin
fork
apb_op_with_ready();
join_none
end
end
else begin
fork
apb_op_with_ready();
join_none
end
fork
apb_access_op();
apb_sel_check();
join_none
endtask |
|