-------------- burst_test:与single_test不同的是,需要在run_phase中使用fork join 让AHB侧和APB侧同时工作(不能等AHB都发完APB才工作);num_apb_seq为APB已传输的个数,当APB侧传输数据的个数,大于或等于AHB侧的总数据个数后,跳出循环;
class ahbl_mst_burst extends ahb2apb_base_test;
ahbl_mst_burst_seq ahbl_mst_seq_i;
apb_slv_nrdy_seq apb_slv_seq_i;
`uvm_component_utils(ahbl_mst_burst)
function new(string name,uvm_component parent=null);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
ahbl_mst_seq_i = ahbl_mst_burst_seq::type_id::create("ahbl_mst_seq_i",this);
apb_slv_seq_i = apb_slv_nrdy_seq::type_id::create("apb_slv_seq_i",this);
endfunction
virtual task run_phase(uvm_phase phase);
int num_apb_seq;
phase.raise_objection(this);
super.run_phase(phase);
#100us;
fork//使用fork join 让AHB侧和APB侧同时工作(不能等AHB都发完APB才工作)
begin
ahbl_mst_seq_i.start(env_i.ahbl_mst_agt_i.sqr_i);
end
begin
num_apb_seq = 0;
while(1)begin
apb_slv_seq_i.start(env_i.apb_slv_agt_i.sqr_i);
num_apb_seq++;
if(num_apb_seq >= ahbl_mst_seq_i.req.get_bst_beats())begin
break;//APB侧传输数据的个数,大于或等于AHB侧的数据个数后,跳出循环
end
end
end
join
phase.drop_objection(this);
endtask
endclass
burst_seq中:将htrans、hsize、hburst、hwrite注释掉(全部随机)
class ahbl_mst_burst_seq extends ahbl_mst_basic_seq;
function new(string name="ahbl_mst_burst_seq");
super.new(name);
endfunction
`uvm_object_utils(ahbl_mst_burst_seq)
virtual task body();
`uvm_do_with(req,{hsel == 1'b1;
//htrans == ahbl_mst_pkg::NSEQ;
// hsize == ahbl_mst_pkg::WORD;
//hburst == ahbl_mst_pkg::SINGLE;
//hwrite == 1'b1;
})
endtask
endclass
---------- burst_test_slverr:每次传输slv侧slverr为1,随机1:5个周期的nready:
class apb_slv_slverr_seq extends apb_slv_basic_seq;
function new(string name = "apb_slv_slverr_seq");
super.new(name);
endfunction
`uvm_object_utils(apb_slv_slverr_seq)
virtual task body();
`uvm_do_with(req,{slverr == 1'b1;
nready_num inside {[1:5]};})
endtask
endclass
AHB侧收到SLVERR的波形为第一个周期HRESP为高,HREADYOUT为低;第二个周期都为高;
对于AHB协议中所讲,遇到ERRO可以立即停掉或者传输完毕给IDLE;
--------------burst_tight_transfer(紧密传输两个burst):基本相同,例化两个相同的burst_seq,再run_phase中先后使用,并先后分别判断传输数量后跳出循环;
class ahbl_mst_tight_transfer extends ahb2apb_base_test;
ahbl_mst_burst_seq ahbl_mst_seq_0;
ahbl_mst_burst_seq ahbl_mst_seq_1;
apb_slv_nrdy_seq apb_slv_seq_i;
`uvm_component_utils(ahbl_mst_tight_transfer)
function new(string name,uvm_component parent=null);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
ahbl_mst_seq_0 = ahbl_mst_burst_seq::type_id::create("ahbl_mst_seq_0",this);
ahbl_mst_seq_1 = ahbl_mst_burst_seq::type_id::create("ahbl_mst_seq_1",this);
apb_slv_seq_i = apb_slv_nrdy_seq::type_id::create("apb_slv_seq_i",this);
endfunction
virtual task run_phase(uvm_phase phase);
int num_apb_seq;
phase.raise_objection(this);
super.run_phase(phase);
#100us;
fork
begin
ahbl_mst_seq_0.start(env_i.ahbl_mst_agt_i.sqr_i);
ahbl_mst_seq_1.start(env_i.ahbl_mst_agt_i.sqr_i);
end
begin
num_apb_seq = 0;
while(1)begin
apb_slv_seq_i.start(env_i.apb_slv_agt_i.sqr_i);
num_apb_seq++;
if(num_apb_seq >= ahbl_mst_seq_0.req.get_bst_beats())begin
break;
end
end
while(1)begin
apb_slv_seq_i.start(env_i.apb_slv_agt_i.sqr_i);
num_apb_seq++;
if(num_apb_seq >= ahbl_mst_seq_1.req.get_bst_beats())begin
break;
end
end
end
join
phase.drop_objection(this);
endtask
endclass
第一个随机burst是WORD读操作,第二个是HALFWORD写操作;
AHB写操作第一个5666说明写入高两个字节有效为AB6C3EE5;第二个5668说明低两个字节有效为477EF246;APB端地址总是一次加4,PSTRB信号代表了地址是高有效还是低有效,C为1100说明高有效,3为0011说明低有效;(PSTRB仅用于写,说明了哪个字节数据是有效)
-------------------------------地址解读:32位一次传4字节,地址0、4、8、C变化;
16位一次传2字节HalfWord,地址0、2、4、6、8、A…变化;
如地址0X42,HWORD传输,随机出来的32位数据只有高两个字节有效;低两个字节无效;