/********************************************** _ _ Cook Darwin __
_ descript: author : Cook.Darwin Version: VERA.0.0 creaded: 2016/8/21 madified: ***********************************************/ `timescale 1ns / 1ps `include “define_macro.sv” module axi_mirror #(
parameter ASIZE = 32, parameter DSIZE = 64, parameter IDSIZE= 4, parameter LSIZE = 8, parameter ID = 0, parameter LOCK_ID= "OFF", parameter ADDR_STEP = 1, parameter REV_SAVE_TOTAL=0, parameter TRS_SAVE_TOTAL=0, `parameter_string REV_SAVE_NAME = "mirror_rev.txt", `parameter_string TRS_SAVE_NAME = "mirror_trs.txt", parameter SAVE_SPLIT = 32
)(
axi_inf.mirror inf
); import StreamFilePkg::*;
string rev_info; string trs_info;
event enough_data_event,enough_trs_data_event; int enough_rev_data_threshold = REV_SAVE_TOTAL; int enough_trs_data_threshold = TRS_SAVE_TOTAL;
logic rev_addr,trs_addr; logic rev_data [bit]; logic trs_data [bit]; int rev_burst_len,trs_burst_len; int rev_id,trs_id;
integer wdata_array [DSIZE/32-1:0]; integer rdata_array [DSIZE/32-1:0];
// assign wdata_array = {>>{inf.axi_wdata}}; // assign rdata_array = {>>{inf.axi_rdata}};
task automatic start_recieve_task();
// sr = new(0,100,3,4); // II = sr.randomize(); while(1)begin @(posedge inf.axi_aclk); rev_info = "start rev addr wr"; if(inf.axi_awvalid)begin if(ID == inf.axi_awid || LOCK_ID=="OFF") // @(posedge inf.axi_aclk); break; end end rev_addr = inf.axi_awaddr; rev_burst_len = inf.axi_awlen+1; rev_id = inf.axi_awid; // @(posedge inf.axi_aclk); rev_info = "addr wr done"; $display("%t,AXI WRITE: ADDR=%h LENGTH=%d",$time,rev_addr,rev_burst_len);
endtask:start_recieve_task
task automatic start_transmit_task;
while(1)begin @(posedge inf.axi_aclk); trs_info = "start addr rd"; if(inf.axi_arvalid)begin if(ID == inf.axi_arid || LOCK_ID=="OFF") // @(posedge inf.axi_aclk); break; end end trs_addr = inf.axi_araddr; trs_burst_len = inf.axi_arlen+1; trs_id = inf.axi_arid; // @(posedge inf.axi_aclk); trs_info = "addr rd done"; $display("%t,AXI READ: ADDR=%h LENGTH=%d",$time,trs_addr,trs_burst_len);
endtask:start_transmit_task
int rev_cnt; task automatic rev_data_task(); int data_cnt;
data_cnt = 0; forever begin @(negedge inf.axi_aclk); rev_info = "start rev data"; if(inf.axi_wvalid && inf.axi_wready)begin data_cnt++; rev_cnt = data_cnt; rev_data[rev_addr] = inf.axi_wdata; rev_addr = rev_addr + ADDR_STEP; if(enough_rev_data_threshold <= rev_data.size && enough_rev_data_threshold != 0)begin -> enough_data_event; save_rev_cache_data(); enough_rev_data_threshold = 0; end if(inf.axi_wlast)begin assert(data_cnt == rev_burst_len) else begin $warning("BURST REAL->%d EXPECT->%d LENGTH ERROR",data_cnt,rev_burst_len); end @(posedge inf.axi_aclk); break; end end @(posedge inf.axi_aclk); end // @(posedge inf.axi_aclk); rev_info = "data wr done"; // repeat(10) @(posedge inf.axi_aclk);
endtask:rev_data_task
int trans_data_cnt; task automatic trans_data_task; int data_cnt;
data_cnt = 0; forever begin @(negedge inf.axi_aclk); trs_info = "data rd"; if(inf.axi_rvalid && inf.axi_rready)begin data_cnt++; trans_data_cnt = data_cnt; trs_data[trs_addr] = inf.axi_rdata; trs_addr = trs_addr + ADDR_STEP; if(enough_trs_data_threshold <= trs_data.size && enough_trs_data_threshold != 0)begin -> enough_trs_data_event; save_trs_cache_data(); enough_trs_data_threshold = 0; end if(inf.axi_rlast)begin assert(data_cnt == trs_burst_len) else begin $warning("BURST REAL->%d EXPECT->%d LENGTH ERROR",data_cnt,rev_burst_len); $stop; end break; end end @(posedge inf.axi_aclk); end trs_info = "data rd done";
endtask:trans_data_task
task automatic trans_resp_task();
wait(inf.axi_bready);//@(posedge axi_aclk); rev_info = "resp wr"; @(posedge inf.axi_aclk); rev_info = "resp wr done";
endtask:trans_resp_task
task slaver_recieve_burst(int num);
fork repeat(num) begin start_recieve_task; fork rev_data_task; join trans_resp_task; end join_none
endtask:slaver_recieve_burst
task slaver_transmit_busrt(int num);
fork repeat(num) begin start_transmit_task; // fork trans_data_task; // join end // join_none join
endtask:slaver_transmit_busrt
//—>> save data to file <<——– StreamFileClass sf;
task automatic save_cache_data(string filename,int split_bits=32,ref logic rev_data [bit]); longint data []; logic data_32 []; logic data_24 []; logic data_16 []; logic data_8 []; string str; int index; int KK; int compact_index; int start_index,end_index; logic tmp_data;
sf = new(filename); sf.head_mark = "AXI slaver cache data"; index = 0; foreach(rev_data[i])begin start_index = index*(DSIZE/split_bits + (DSIZE%split_bits!=0? 1 : 0)); end_index = start_index+(DSIZE/split_bits + (DSIZE%split_bits!=0? 1 : 0))-1; $sformat(str,">>%d->%d<< ADDR %h : ",start_index,end_index,i); index++; sf.str_write(str); case(split_bits) 32:begin data_32 = {>>32{rev_data[i]}}; data = new[data_32.size]; foreach(data_32[j]) data[j] = data_32[j]; // sf.puts('{data}); end 24:begin compact_index = (i / ADDR_STEP) % 3; case(compact_index) 0: tmp_data = rev_data[i]; 1: tmp_data = rev_data[i]<<8; 2: tmp_data = rev_data[i]<<16; default:; endcase data_24 = {>>24{tmp_data[DSIZE-1-:((DSIZE/24)*24)],{tmp_data[0+:8],16'd0}}}; data = new[data_24.size]; foreach(data_24[j]) data[j] = data_24[j]; end 16:begin data_16 = {>>16{rev_data[i]}}; data = new[data_16.size]; foreach(data_16[j])begin data[j] = data_16[j]; end end 8:begin data_8 = {>>8{rev_data[i]}}; data = new[data_8.size]; foreach(data_8[j]) data[j] = data_8[j]; end default:; endcase sf.puts(data); end sf.close_file;
endtask:save_cache_data
task automatic save_rev_cache_data(int split_bits=SAVE_SPLIT);
save_cache_data(REV_SAVE_NAME,split_bits,rev_data);
endtask:save_rev_cache_data
task automatic save_trs_cache_data(int split_bits=SAVE_SPLIT);
save_cache_data(TRS_SAVE_NAME,split_bits,trs_data);
endtask:save_trs_cache_data
task automatic wait_rev_enough_data(int num);
enough_rev_data_threshold = num; @(enough_data_event);
endtask:wait_rev_enough_data
task automatic wait_trs_enough_data(int num);
enough_trs_data_threshold = num; @(enough_trs_data_event);
endtask:wait_trs_enough_data
endmodule