package AxiIllegalBfmPkg ; typedef struct {
logic [32-1:0] addr; logic [32-1:0] data; string name = "";
} AddrData;
typedef struct {
int id; int addr; int len;
} IdAddrLen_S ;
task automatic sync_clk_wait(ref bit clock,ref logic condition);
forever begin @(posedge clock); if(condition) break; end
endtask:sync_clk_wait
typedef struct {
int offset_len; bit last_off; bit aw_off; bit ar_off;
} axi4_illegal_s;
//——————————————————————— // AXI 4 Master BFM //__ class Axi4IllMasterBfm_c #(
parameter IDSIZE = 1, parameter ASIZE = 32, parameter LSIZE = 1, parameter DSIZE = 32, parameter MSG = "ON", parameter ADDR_STEP = 32'hFFFF_FFFF
); mailbox wid_box; // typedef struct { // logic [IDSIZE-1:0] id; // logic [ASIZE-1:0] addr; // logic [LSIZE-1:0] len; // } IdAddrLen_S ;
IdAddrLen_S tra_ar_od [$];
virtual axi_inf #(
.IDSIZE (IDSIZE ), .ASIZE (ASIZE ), .LSIZE (LSIZE ), .DSIZE (DSIZE ), .ADDR_STEP (ADDR_STEP)
) inf;
function new (virtual axi_inf #(.IDSIZE(IDSIZE),.ASIZE(ASIZE),.LSIZE(LSIZE),.DSIZE(DSIZE),.ADDR_STEP(ADDR_STEP)) b);
inf = b; wid_box = new();
endfunction:new
task wr_reset_status;
inf.axi_awid = 0; inf.axi_awaddr = 0; inf.axi_awlen = 0; inf.axi_awsize = 0; inf.axi_awburst = 0; inf.axi_awlock = 0; inf.axi_awcache = 0; inf.axi_awprot = 0; inf.axi_awqos = 0; inf.axi_awvalid = 0; inf.axi_wdata = 0; inf.axi_wstrb = 0; inf.axi_wlast = 0; inf.axi_wvalid = 0; inf.axi_bready = 0;
endtask:wr_reset_status task rd_reset_status;
inf.axi_arid = 0; inf.axi_araddr = 0; inf.axi_arlen = 0; inf.axi_arsize = 0; inf.axi_arburst = 0; inf.axi_arlock = 0; inf.axi_arcache = 0; inf.axi_arprot = 0; inf.axi_arqos = 0; inf.axi_arvalid = 0; inf.axi_rready = 0;
endtask:rd_reset_status
task automatic init ();
fork wr_reset_status(); rd_reset_status(); join
endtask:init
task automatic sync_wait(ref logic condition);
forever begin @(posedge inf.axi_aclk); if(condition) break; end
endtask:sync_wait
task automatic aw_task(logic [ASIZE-1:0] addr,logic [LSIZE-1:0] len,bit aw_off=0);
wr_reset_status(); if(MSG=="ON") $display("AXI4 Write ADDR[%h],LEN[%d]",addr,len); @(posedge inf.axi_aclk); if(~aw_off)begin inf.axi_awvalid = 1; inf.axi_awlen = len-1; inf.axi_awaddr = addr; inf.axi_awid = $urandom_range(10,0); sync_wait(inf.axi_awready); inf.axi_awvalid = 0; end else begin if(MSG=="ON") $display("AXI4 Write AW ON"); @(posedge inf.axi_aclk); end // wid_box.put(inf.axi_awid);
endtask:aw_task
task automatic wdata_task(
bit last_off, int length, int valid_ramdon_percent, ref [DSIZE-1:0] data_s [$]
);
if(MSG=="ON") ; gen_axi_stream(last_off,length,valid_ramdon_percent,data_s);
endtask:wdata_task
task automatic wbrep_task();
inf.axi_bready = 1; sync_wait(inf.axi_bvalid); inf.axi_bready = 0; if(MSG=="ON") $display("WRITE BURST COMPLETE!!!");
endtask:wbrep_task
task automatic ar_task(logic [ASIZE-1:0] addr,logic [LSIZE-1:0] len);
// @(posedge inf.axi_aclk); inf.axi_arvalid = 1; // @(posedge inf.axi_aclk); // $stop; inf.axi_arid = $urandom_range(10,0); inf.axi_arlen = len-1; inf.axi_araddr = addr; sync_wait(inf.axi_arready); inf.axi_arvalid = 0; if(MSG=="ON") $display("%t,MASTER AXI4 READ ADDR[%h]",$time,addr);
endtask:ar_task
task automatic ar_od_task(int id,int addr,int len); IdAddrLen_S ial;
inf.axi_arvalid = 1; inf.axi_arlen = len-1; inf.axi_araddr = addr; inf.axi_arid = id; sync_wait(inf.axi_arready); ial.id = inf.axi_arid; ial.addr = inf.axi_araddr; ial.len = inf.axi_arlen; inf.axi_arvalid = 0; if(MSG=="ON") $display("%t,MASTER AXI4 READ ADDR[%h]",$time,addr); tra_ar_od.push_back(ial);
endtask:ar_od_task
task automatic gen_axi_stream (
bit last_off, int length, int valid_ramdon_percent, ref [DSIZE-1:0] data_s [$]
); int index; int cc = 0; int data_len; int rt; logic [DSIZE-1:0] data_ss; logic curr_data; int real_len; bit virtual_last;
data_len = data_s.size(); cc=0; if(length==0) real_len = data_len; else real_len = length; repeat(real_len)begin index = cc%data_len; data_ss[cc] = data_s[index]; cc++; end // $display("ORIGIN LENGTH: %d,REAL LENGTH: %d",data_s.size(),data_ss.size()); if(MSG=="ON")begin $display("__________________________________"); $display("GEN AXI4 write burst STREAM LEN = %d",data_ss.size()); end while(1)begin rt = $urandom_range(99,0); if(rt < valid_ramdon_percent)begin inf.axi_wvalid = 1; inf.axi_wdata = data_ss.size() != 0? data_ss.pop_front : inf.axi_wdata; virtual_last = data_ss.size() == 0; if(~last_off)begin inf.axi_wlast = data_ss.size() == 0; end sync_wait(inf.axi_wready); if(virtual_last) break; end else begin inf.axi_wvalid = 0; inf.axi_wlast = 0; virtual_last = 0; @(posedge inf.axi_aclk); end end #1 inf.axi_wvalid = 0; inf.axi_wlast = 0; virtual_last = 0; if(MSG=="ON") $display("==================================");
endtask:gen_axi_stream
task automatic get_axi_data(int rate = 100,ref logic [DSIZE-1:0] data [$]); int rm;
data = {}; forever begin rm = $urandom_range(0,99); if(rm < rate) inf.axi_rready = 1; else inf.axi_rready = 0; if(inf.axi_rready)begin sync_wait(inf.axi_rvalid); data.push_back(inf.axi_rdata); if(inf.axi_rlast)begin break; end end else begin @(posedge inf.axi_aclk); end end inf.axi_rready = 0; if(MSG=="ON") $display("%t,MASTER AXI4 READ LENGTH [%d] DATA DONE!!!",$time,data.size());
endtask:get_axi_data
//public task automatic write_burst(
ref axi4_illegal_s illegal_s, input logic[ASIZE-1:0] addr, input int length, input int valid_ramdon_percent, ref [DSIZE-1:0] data_s [$]
); int len ;
if(length==0) len = data_s.size(); else len = length; aw_task(addr,len,illegal_s.aw_off); wdata_task(illegal_s.last_off,len+illegal_s.offset_len,valid_ramdon_percent,data_s); wbrep_task();
endtask:write_burst
task automatic read_burst(
logic[ASIZE-1:0] addr, int length, int ready_ramdon_percent, ref [DSIZE-1:0] data_s [$]
);
ar_task(addr,length); get_axi_data(ready_ramdon_percent,data_s);
endtask:read_burst
logic [DSIZE-1:0] rd_queue [$];
task automatic out_of_order_read_burst(
ref IdAddrLen_S ial [$], int ready_ramdon_percent, ref [DSIZE-1:0] data_s [$]
); fork
foreach(ial[i]) ar_od_task(ial[i].id,ial[i].addr,ial[i].len); foreach(ial[i]) get_axi_data(ready_ramdon_percent,data_s);
join endtask:out_of_order_read_burst
endclass:Axi4IllMasterBfm_c //———————————————————————- // AXI 4 Slaver BFM //__ class Axi4IllSlaverBfm_c #(
parameter IDSIZE = 1, parameter ASIZE = 32, parameter LSIZE = 1, parameter DSIZE = 32, parameter MSG = "ON", parameter ADDR_STEP = 32'hFFFF_FFFF
); mailbox wid_box; mailbox rid_box;
virtual axi_inf #(
.IDSIZE (IDSIZE ), .ASIZE (ASIZE ), .LSIZE (LSIZE ), .DSIZE (DSIZE ), .ADDR_STEP (ADDR_STEP)
) inf;
IdAddrLen_S rev_ar_OD [$];
function new (virtual axi_inf #(.IDSIZE(IDSIZE),.ASIZE(ASIZE),.LSIZE(LSIZE),.DSIZE(DSIZE),.ADDR_STEP(ADDR_STEP)) b);
inf = b; wid_box = new(); rid_box = new(); inf.axi_rvalid = 0; inf.axi_arready = 0;
endfunction:new
task automatic sync_wait(ref logic condition);
forever begin @(posedge inf.axi_aclk); if(condition) break; end
endtask:sync_wait
task automatic create_wr_transaction();
inf.axi_awready = 1; inf.axi_wready = 1; inf.axi_bid = 0; inf.axi_bvalid = 0; inf.axi_bresp = 0;
endtask:create_wr_transaction
task automatic create_rd_transaction();
inf.axi_arready = 1; inf.axi_rvalid = 0; inf.axi_rid = 0; inf.axi_rdata = 0; inf.axi_rlast = 0; inf.axi_rresp = 0;
endtask:create_rd_transaction
task automatic create_transaction();
create_wr_transaction(); create_rd_transaction();
endtask:create_transaction
task automatic aw_task(ref logic addr,ref logic len);
inf.axi_awready = 1; sync_wait(inf.axi_awvalid); if(MSG=="ON")begin $display("%t,SLAVER AXI4 WRITE BURST REQ ADDR[%h],LEN[%d]",$time,inf.axi_awaddr,inf.axi_awlen); end addr = inf.axi_awaddr; len = inf.axi_awlen; wid_box.put(inf.axi_awid);
endtask:aw_task
task automatic ar_task(ref logic addr,ref logic len);
inf.axi_arready = 1; sync_wait(inf.axi_arvalid); if(MSG=="ON")begin $display("%t,SLAVER AXI4 READ BURST REQ ADDR[%h],LEN[%d]",$time,inf.axi_araddr,inf.axi_arlen); end addr = inf.axi_araddr; len = inf.axi_arlen; rid_box.put(inf.axi_arid);
endtask:ar_task
task automatic ar_od_task(); IdAddrLen_S ial;
inf.axi_arready = 1; sync_wait(inf.axi_arvalid); ial.id = inf.axi_arid; ial.addr = inf.axi_araddr; ial.len = inf.axi_arlen; rid_box.put(inf.axi_arid); if(MSG=="ON")begin $display("%t,SLAVER AXI4 READ BURST REQ ID [%d] ADDR[%h],LEN[%d]",$time,ial.id,ial.addr,ial.len); end rev_ar_OD.push_back(ial);
endtask:ar_od_task
task automatic wdata_task(
int ready_ramdon_percent, ref logic[DSIZE-1:0] data [$]);
int rt;
data = {}; forever begin rt = $urandom_range(99,0); if(rt < ready_ramdon_percent)begin inf.axi_wready = 1; sync_wait(inf.axi_wvalid); data = {data,inf.axi_wdata}; if(inf.axi_wlast) break; end else begin inf.axi_wready = 0; @(posedge inf.axi_aclk); end end if(MSG=="ON") $display("%t,AXI4 GET DATA LEN [%d]",$time,data.size());
endtask:wdata_task
task automatic rdata_task(
int len, int valid_ramdon_percent, ref logic[DSIZE-1:0] data [$]
); int rt; logic data_queue;
resize_queue(len+1,data,data_queue); // $display("AXI4 READ BURST SLAVER DONE !!! LEN [%d]",len); rid_box.get(inf.axi_rid); forever begin rt = $urandom_range(99,0); if(rt < valid_ramdon_percent)begin inf.axi_rvalid = 1; inf.axi_rdata = data_queue.size() != 0? data_queue.pop_front : inf.axi_rdata; inf.axi_rlast = data_queue.size() == 0; sync_wait(inf.axi_rready); if(inf.axi_rlast) break; end else begin inf.axi_rvalid = 0; inf.axi_rlast = 0; @(posedge inf.axi_aclk); end end inf.axi_rvalid = 0; inf.axi_rlast = 0; if(MSG=="ON") $display("%t,AXI4 READ BURST SLAVER DONE !!! LEN [%0d]",$time,len);
endtask:rdata_task
task automatic rdata_od_task(
int id, int len, int valid_ramdon_percent, ref logic[DSIZE-1:0] data [$]
); int rt; logic data_queue;
resize_queue(len,data,data_queue); // $display(">>>>>>AXI4 READ BURST SLAVER DONE !!! LEN [%d][%d]",len,data_queue.size()); rid_box.get(inf.axi_rid); forever begin rt = $urandom_range(99,0); // inf.axi_rid = id; if(rt < valid_ramdon_percent)begin inf.axi_rvalid = 1; inf.axi_rdata = data_queue.size() != 0? data_queue.pop_front : inf.axi_rdata; inf.axi_rlast = data_queue.size() == 0; sync_wait(inf.axi_rready); if(inf.axi_rlast)begin @(posedge inf.axi_aclk); break; end end else begin inf.axi_rvalid = 0; inf.axi_rlast = 0; @(posedge inf.axi_aclk); end end inf.axi_rvalid = 0; inf.axi_rlast = 0; if(MSG=="ON") $display("%t,AXI4 READ BURST SLAVER DONE !!! LEN [%d]",$time,len);
endtask:rdata_od_task
task automatic wbresp_task();
inf.axi_bresp = '0; inf.axi_bvalid = 1; wid_box.get(inf.axi_bid); sync_wait(inf.axi_bready); inf.axi_bvalid = 0; if(MSG=="ON") $display("%t,AXI4 WRITE BUSRT BRESP DONE !!!",$time);
endtask:wbresp_task
task automatic resize_queue(
int len, ref logic [DSIZE-1:0] in_queue [$], ref logic [DSIZE-1:0] out_queue[$]
); int real_len; int d_len; int r_len; out_queue = {}; if(len == 0)
out_queue = in_queue;
else if(len <= in_queue.size())
out_queue = in_queue[0:(len-1)];
else begin
real_len = in_queue.size(); d_len = len/real_len; r_len = len%real_len; for(int i=0;i<d_len;i++) out_queue = {out_queue,in_queue}; out_queue = {out_queue,in_queue[0:(r_len-1)]};
end // $display(“—%d–%d–%d”,len,in_queue.size(),out_queue.size()); endtask:resize_queue
task automatic burst_write(
ref logic[ASIZE-1:0] addr, ref logic[LSIZE-1:0] length, input int ready_ramdon_percent, ref [DSIZE-1:0] data_s [$]
);
aw_task(addr,length); wdata_task(ready_ramdon_percent,data_s); wbresp_task();
endtask:burst_write
task automatic burst_read(
ref logic[ASIZE-1:0] addr, ref logic[LSIZE-1:0] length, int valid_ramdon_percent, ref [DSIZE-1:0] data_s [$]
);
ar_task(addr,length); rdata_task(int'(length),valid_ramdon_percent,data_s);
endtask:burst_read
logic [ASIZE-1:0] wr_addr,rd_addr; logic [LSIZE-1:0] wr_len,rd_len; logic [DSIZE-1:0] wr_queue [$]; logic [DSIZE-1:0] rd_queue [$];
task automatic run (int valid_ramdon_percent,int ready_ramdon_percent);
create_transaction(); fork forever begin burst_write(wr_addr,wr_len,ready_ramdon_percent,wr_queue); end forever begin burst_read(rd_addr,rd_len,valid_ramdon_percent,rd_queue); end join_none
endtask:run
task automatic out_fo_order_burst_read(
int valid_ramdon_percent
); IdAddrLen_S idl; logic [DSIZE-1:0] rd_queue [$]; rd_queue = {0,1,2,3,4,5,6,7,8,9}; fork
forever begin ar_od_task(); end forever begin forever begin @(posedge inf.axi_aclk); if(rev_ar_OD.size()>0) break; end idl = rev_ar_OD.pop_front(); rdata_od_task(idl.id,int'(idl.len+1),valid_ramdon_percent,rd_queue); end
join_none endtask:out_fo_order_burst_read
endclass:Axi4IllSlaverBfm_c
endpackage