关于axi_slave需要考虑如下的随机性:
(1)size,数据长度;
(2)burst length,数据包长度;
(3)4kB地址对齐;
(4)传输类型,wrap,incr;
(5)delay,分为两种,一种是写,这种delay一个burst只包含一个delay;第二种是读,这种delay一个burst包含len长度个delay;
(6)strobe信号,这个信号的随机只存在于写操作中;
(7)时钟和复位的随机性,关于时钟和复位的随机性,具体参考下面代码:
package clk_rst_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
class clk_rst_trans extends uvm_sequence_item;
logic hclk;
logic hrst;
logic pclk;
logic prst;
rand logic [31:0] hclk_high_time;
rand logic [31:0] hclk_low_time;
rand logic [31:0] pclk_high_time;
rand logic [31:0] pclk_low_time;
rand logic [31:0] hrst_time;
rand logic [31:0] prst_time;
rand logic [31:0] ahb_transfer_reset_delay;
rand logic [31:0] apb_transfer_reset_delay;
constraint cstr{
soft hclk_high_time == 5;
soft hclk_low_time == 5;
soft pclk_high_time == 10;
soft pclk_low_time == 10;
soft hrst_time == 32;
soft prst_time == 32;};
`uvm_object_utils_begin(clk_rst_trans)
`uvm_field_int(hclk_high_time,UVM_ALL_ON)
`uvm_field_int(hclk_low_time,UVM_ALL_ON)
`uvm_field_int(pclk_high_time,UVM_ALL_ON)
`uvm_field_int(pclk_low_time,UVM_ALL_ON)
`uvm_field_int(hrst_time,UVM_ALL_ON)
`uvm_field_int(prst_time,UVM_ALL_ON)
`uvm_field_int(ahb_transfer_reset_delay,UVM_ALL_ON)
`uvm_field_int(apb_transfer_reset_delay,UVM_ALL_ON)
`uvm_object_utils_end
function new (string name = "clk_rst_trans");
super.new(name);
endfunction
endclass
仅仅从item上来看有这几个随机的点:(1)时钟为高的时间、为低的时间;(2)一开始复位需要的delay时间(3)传输过程中复位需要的时间。这三点在driver中都有体现。
class clk_rst_driver extends uvm_driver#(clk_rst_trans);
virtual ahb_clk_rst_if ahb_intf;
virtual apb_clk_rst_if apb_intf;
uvm_event transfer_ahb_rst;
uvm_event transfer_apb_rst;
function new (string name = "clk_rst_driver");
super.new(name);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual ahb_clk_rst_if)::get(this, "", "ahb_intf",ahb_intf))
`uvm_fatal("driver", "can not get ahb clk interface")
if(!uvm_config_db#(virtual apb_clk_rst_if)::get(this, "", "apb_intf",apb_intf))
`uvm_fatal("driver", "can not get apb clk interface")
transfer_ahb_rst = uvm_event_pool::get_global("transfer_ahb_rst");
transfer_apb_rst = uvm_event_pool::get_global("transfer_apb_rst");
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction
virtual task run_phase(uvm_phase phase);
fork
run_hclk();
run_pclk();
run_hrst();
run_prst();
join
endtask
task run_hclk();
forever begin
ahb_intf.drv_ck.clk <= 1'b1;
#(this.hclk_high_time);
ahb_intf.drv_ck.clk <= 1'b0;
#(this.hclk_low_time);
end
endtask
task run_pclk();
forever begin
apb_intf.drv_ck.clk <= 1'b1;
#(this.pclk_high_time);
apb_intf.drv_ck.clk <= 1'b0;
#(this.pclk_low_time);
end
endtask
task run_hrst();
uvm_object tmp;
clk_rst_trans trans;
ahb_intf.drv_ck.rst <= 1'b0;
#(this.hrst_time);
ahb_intf.drv_ck.clk <= 1'b1;
forever begin
transfer_ahb_rst.wait_trigger_data(tmp);
void'($cast(trans,tmp));
ahb_intf.drv_ck.rst <= 1'b0;
#(this.trans.ahb_transfer_reset_delay);
ahb_intf.drv_ck.clk <= 1'b1;
end
endtask
task run_prst();
uvm_object tmp;
clk_rst_trans trans;
apb_intf.drv_ck.rst <= 1'b0;
#(this.prst_time);
apb_intf.drv_ck.clk <= 1'b1;
forever begin
transfer_apb_rst.wait_trigger_data(tmp);
void'($cast(trans,tmp));
apb_intf.drv_ck.rst <= 1'b0;
#(this.trans.apb_transfer_reset_delay);
ahb_intf.drv_ck.clk <= 1'b1;
end
endtask
endclass
class clk_rst_sqr extends uvm_sequencer #(clk_rst_trans);
`uvm_component_utils(ahb_clk_rst_sqr)
function new(string name = "clk_rst_sqr", uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.new(name,parent);
endclass
endclass
class clk_rst_agent extends uvm_agent;
virtual ahb_clk_rst_if ahb_intf;
virtual apb_clk_rst_if apb_intf;
clk_rst_driver dri;
clk_rst_sqr sqr;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual ahb_clk_rst_if)::get(this, "", "ahb_intf", ahb_intf))
`uvm_fatal("clk_rst_agent", "can not get ahb interface in clk_rst_agent")
if(!uvm_config_db#(virtual apb_clk_rst_if)::get(this, "", "apb_intf", apb_intf))
`uvm_fatal("clk_rst_agent", "can not get apb interface in clk_rst_agent")
dri = clk_rst_driver::type_id::create("dri",this);
sqr = clk_rst_sqr::type_id::create("sqr",this);
uvm_config_db#(virtual ahb_clk_rst_if)::set(this, "dri", "ahb_intf", ahb_intf);
uvm_config_db#(virtual apb_clk_rst_if)::set(this, "dri", "apb_intf", apb_intf);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
dri.seq_item_port.connect(sqr.seq_item_export);
endfunction
endclass
endpackage
除此以外还可以考虑时钟抖动问题:
时钟抖动的类型包含高斯分布、周期性抖动、随机分布、占空比失真抖动等。