OpenCores
URL https://opencores.org/ocsvn/axi_master/axi_master/trunk

Subversion Repositories axi_master

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /axi_master/trunk
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/src/base/def_axi_master_static.txt
26,62 → 26,63
//// details. http://www.gnu.org/licenses/lgpl.html ////
//// ////
//////////////////////////////////////////////////////////////////##>
 
VERIFY (DATA_BITS <= 64) else stub supports 32 or 64 bits data bus
VERIFY (SIZE_BITS <= 3) else stub supports 32 or 64 bits data bus
 
GROUP STUB_AXI_A is {
ID ID_BITS output
ADDR ADDR_BITS output
LEN LEN_BITS output
SIZE SIZE_BITS output
BURST 2 output
CACHE 4 output
PROT 3 output
LOCK 2 output
VALID 1 output
READY 1 input
}
 
GROUP STUB_AXI_W is {
ID ID_BITS output
DATA DATA_BITS output
STRB DATA_BITS/8 output
LAST 1 output
VALID 1 output
READY 1 input
}
 
GROUP STUB_AXI_B is {
ID ID_BITS input
RESP 2 input
VALID 1 input
READY 1 output
}
 
GROUP STUB_AXI_R is {
ID ID_BITS input
DATA DATA_BITS input
RESP 2 input
LAST 1 input
VALID 1 input
READY 1 output
}
 
GROUP STUB_AXI joins {
GROUP STUB_AXI_A prefix_AW
GROUP STUB_AXI_W prefix_W
GROUP STUB_AXI_B prefix_B
GROUP STUB_AXI_A prefix_AR
GROUP STUB_AXI_R prefix_R
}
 
GROUP AXI_MASTER_RAND is {
len_min SON(DEFAULT 0)
len_max SON(DEFAULT 15)
size_min SON(DEFAULT 0)
size_max SON(DEFAULT 3)
addr_min SON(DEFAULT 0)
addr_max SON(DEFAULT {DATA_BITS{1'b1}})
}
 
VERIFY (DATA_BITS <= 64) else stub supports 32 or 64 bits data bus
VERIFY (SIZE_BITS <= 3) else stub supports 32 or 64 bits data bus
 
GROUP STUB_AXI_A is {
ID ID_BITS output
ADDR ADDR_BITS output
LEN LEN_BITS output
SIZE SIZE_BITS output
BURST 2 output
CACHE 4 output
PROT 3 output
LOCK 2 output
VALID 1 output
READY 1 input
}
 
GROUP STUB_AXI_W is {
ID ID_BITS output
DATA DATA_BITS output
STRB DATA_BITS/8 output
LAST 1 output
VALID 1 output
READY 1 input
}
 
GROUP STUB_AXI_B is {
ID ID_BITS input
RESP 2 input
VALID 1 input
READY 1 output
}
 
GROUP STUB_AXI_R is {
ID ID_BITS input
DATA DATA_BITS input
RESP 2 input
LAST 1 input
VALID 1 input
READY 1 output
}
 
GROUP STUB_AXI joins {
GROUP STUB_AXI_A prefix_AW
GROUP STUB_AXI_W prefix_W
GROUP STUB_AXI_B prefix_B
GROUP STUB_AXI_A prefix_AR
GROUP STUB_AXI_R prefix_R
}
 
GROUP AXI_MASTER_RAND is {
use_addr_base SON(DEFAULT 0)
len_min SON(DEFAULT 0)
len_max SON(DEFAULT 15)
size_min SON(DEFAULT 0)
size_max SON(DEFAULT 3)
addr_min SON(DEFAULT 0)
addr_max SON(DEFAULT {DATA_BITS{1'b1}})
}
/src/base/axi_master.v
26,276 → 26,311
//// details. http://www.gnu.org/licenses/lgpl.html ////
//// ////
/////////////////////////////////////////////////////////////////////
 
OUTFILE PREFIX.v
 
INCLUDE def_axi_master.txt
 
 
//////////////////////////////////////
//
// General:
// The AXI master has an internal master per ID.
// These internal masters work simultaniously and an interconnect matrix connets them.
//
//
// I/F :
// idle - all internal masters emptied their command FIFOs
// scrbrd_empty - all scoreboard checks have been completed (for random testing)
//
//
// Tasks:
//
// enable(input master_num)
// Description: Enables master
// Parameters: master_num - number of internal master
//
// enable_all()
// Description: Enables all masters
//
// write_single(input master_num, input addr, input wdata)
// Description: write a single AXI burst (1 data cycle)
// Parameters: master_num - number of internal master
// addr - address
// wdata - write data
//
// read_single(input master_num, input addr, output rdata)
// Description: read a single AXI burst (1 data cycle)
// Parameters: master_num - number of internal master
// addr - address
// rdata - return read data
//
// insert_wr_cmd(input master_num, input addr, input len, input size)
// Description: add an AXI write burst to command FIFO
// Parameters: master_num - number of internal master
// addr - address
// len - AXI LEN (data strobe number)
// size - AXI SIZE (data width)
//
// insert_rd_cmd(input master_num, input addr, input len, input size)
// Description: add an AXI read burst to command FIFO
// Parameters: master_num - number of internal master
// addr - address
// len - AXI LEN (data strobe number)
// size - AXI SIZE (data width)
//
// insert_wr_data(input master_num, input wdata)
// Description: add a single data to data FIFO (to be used in write bursts)
// Parameters: master_num - number of internal master
// wdata - write data
//
// insert_wr_incr_data(input master_num, input addr, input len, input size)
// Description: add an AXI write burst to command FIFO will use incremental data (no need to use insert_wr_data)
// Parameters: master_num - number of internal master
// addr - address
// len - AXI LEN (data strobe number)
// size - AXI SIZE (data width)
//
// insert_rand_chk(input master_num, input burst_num)
// Description: add multiple commands to command FIFO. Each command writes incremental data to a random address, reads the data back and checks the data. Useful for random testing.
// Parameters: master_num - number of internal master
// burst_num - total number of bursts to check
//
 
//
// Parameters:
//
// For random testing: (changing these values automatically update interanl masters)
// len_min - minimum burst LEN (length)
// len_max - maximum burst LEN (length)
// size_min - minimum burst SIZE (length)
// size_max - maximum burst SIZE (length)
// addr_min - minimum address (in bytes)
// addr_max - maximum address (in bytes)
//
//////////////////////////////////////
 
ITER IX ID_NUM
module PREFIX(PORTS);
 
input clk;
input reset;
port GROUP_STUB_AXI;
 
output idle;
output scrbrd_empty;
//random parameters
integer GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND.DEFAULT;
wire GROUP_STUB_AXI_IX;
wire idle_IX;
wire scrbrd_empty_IX;
 
 
always @(*)
begin
#FFD;
PREFIX_singleIX.GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND;
end
assign idle = CONCAT(idle_IX &);
assign scrbrd_empty = CONCAT(scrbrd_empty_IX &);
CREATE axi_master_single.v
 
LOOP IX ID_NUM
PREFIX_single #(IX, IDIX_VAL, CMD_DEPTH)
PREFIX_singleIX(
.clk(clk),
.reset(reset),
.GROUP_STUB_AXI(GROUP_STUB_AXI_IX),
.idle(idle_IX),
.scrbrd_empty(scrbrd_empty_IX)
);
ENDLOOP IX
 
IFDEF TRUE(ID_NUM==1)
assign GROUP_STUB_AXI.OUT = GROUP_STUB_AXI_0.OUT;
assign GROUP_STUB_AXI_0.IN = GROUP_STUB_AXI.IN;
ELSE TRUE(ID_NUM==1)
 
CREATE ic.v DEFCMD(SWAP.GLOBAL PARENT PREFIX) DEFCMD(SWAP.GLOBAL MASTER_NUM ID_NUM) DEFCMD(SWAP.GLOBAL CONST(ID_BITS) ID_BITS) DEFCMD(SWAP.GLOBAL CONST(CMD_DEPTH) CMD_DEPTH) DEFCMD(SWAP.GLOBAL CONST(DATA_BITS) DATA_BITS) DEFCMD(SWAP.GLOBAL CONST(ADDR_BITS) ADDR_BITS)
LOOP IX ID_NUM
STOMP NEWLINE
DEFCMD(LOOP.GLOBAL MIX_IDX 1)
STOMP NEWLINE
DEFCMD(SWAP.GLOBAL ID_MIX_ID0 IDIX_VAL)
ENDLOOP IX
 
PREFIX_ic PREFIX_ic(
.clk(clk),
.reset(reset),
.MIX_GROUP_STUB_AXI(GROUP_STUB_AXI_IX),
.S0_GROUP_STUB_AXI(GROUP_STUB_AXI),
STOMP ,
);
 
ENDIF TRUE(ID_NUM==1)
 
 
task check_master_num;
input [24*8-1:0] task_name;
input [31:0] master_num;
begin
if (master_num >= ID_NUM)
begin
$display("FATAL ERROR: task %0s called for master %0d that does not exist.\tTime: %0d ns.", task_name, master_num, $time);
end
end
endtask
task enable;
input [31:0] master_num;
begin
check_master_num("enable", master_num);
case (master_num)
IX : PREFIX_singleIX.enable = 1;
endcase
end
endtask
 
task enable_all;
begin
PREFIX_singleIX.enable = 1;
end
endtask
task write_single;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
begin
check_master_num("write_single", master_num);
case (master_num)
IX : PREFIX_singleIX.write_single(addr, wdata);
endcase
end
endtask
 
task read_single;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
begin
check_master_num("read_single", master_num);
case (master_num)
IX : PREFIX_singleIX.read_single(addr, rdata);
endcase
end
endtask
 
task insert_wr_cmd;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
check_master_num("insert_wr_cmd", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_wr_cmd(addr, len, size);
endcase
end
endtask
 
task insert_rd_cmd;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
check_master_num("insert_rd_cmd", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_rd_cmd(addr, len, size);
endcase
end
endtask
 
task insert_wr_data;
input [31:0] master_num;
input [DATA_BITS-1:0] wdata;
begin
check_master_num("insert_wr_data", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_wr_data(wdata);
endcase
end
endtask
 
task insert_wr_incr_data;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
check_master_num("insert_wr_incr_data", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_wr_incr_data(addr, len, size);
endcase
end
endtask
 
task insert_rand_chk;
input [31:0] master_num;
input [31:0] burst_num;
begin
check_master_num("insert_rand_chk", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_rand_chk(burst_num);
endcase
end
endtask
 
 
endmodule
 
 
 
//////////////////////////////////////
//
// General:
// The AXI master has an internal master per ID.
// These internal masters work simultaniously and an interconnect matrix connets them.
//
//
// I/F :
// idle - all internal masters emptied their command FIFOs
// scrbrd_empty - all scoreboard checks have been completed (for random testing)
//
//
// Tasks:
//
// enable(input master_num)
// Description: Enables master
// Parameters: master_num - number of internal master
//
// enable_all()
// Description: Enables all masters
//
// write_single(input master_num, input addr, input wdata)
// Description: write a single AXI burst (1 data cycle)
// Parameters: master_num - number of internal master
// addr - address
// wdata - write data
//
// read_single(input master_num, input addr, output rdata)
// Description: read a single AXI burst (1 data cycle)
// Parameters: master_num - number of internal master
// addr - address
// rdata - return read data
//
// check_single(input master_num, input addr, input expected)
// Description: read a single AXI burst and gives an error if the data read does not match expected
// Parameters: master_num - number of internal master
// addr - address
// expected - expected read data
//
// write_and_check_single(input master_num, input addr, input data)
// Description: write a single AXI burst read it back and compare the write and read data
// Parameters: master_num - number of internal master
// addr - address
// data - data to write and expect on read
//
// insert_wr_cmd(input master_num, input addr, input len, input size)
// Description: add an AXI write burst to command FIFO
// Parameters: master_num - number of internal master
// addr - address
// len - AXI LEN (data strobe number)
// size - AXI SIZE (data width)
//
// insert_rd_cmd(input master_num, input addr, input len, input size)
// Description: add an AXI read burst to command FIFO
// Parameters: master_num - number of internal master
// addr - address
// len - AXI LEN (data strobe number)
// size - AXI SIZE (data width)
//
// insert_wr_data(input master_num, input wdata)
// Description: add a single data to data FIFO (to be used in write bursts)
// Parameters: master_num - number of internal master
// wdata - write data
//
// insert_wr_incr_data(input master_num, input addr, input len, input size)
// Description: add an AXI write burst to command FIFO will use incremental data (no need to use insert_wr_data)
// Parameters: master_num - number of internal master
// addr - address
// len - AXI LEN (data strobe number)
// size - AXI SIZE (data width)
//
// insert_rand_chk(input master_num, input burst_num)
// Description: add multiple commands to command FIFO. Each command writes incremental data to a random address, reads the data back and checks the data. Useful for random testing.
// Parameters: master_num - number of internal master
// burst_num - total number of bursts to check
//
 
//
// Parameters:
//
// For random testing: (changing these values automatically update interanl masters)
// len_min - minimum burst AXI LEN (length)
// len_max - maximum burst AXI LEN (length)
// size_min - minimum burst AXI SIZE (width)
// size_max - maximum burst AXI SIZE (width)
// addr_min - minimum address (in bytes)
// addr_max - maximum address (in bytes)
//
//////////////////////////////////////
 
OUTFILE PREFIX.v
 
INCLUDE def_axi_master.txt
 
ITER IX ID_NUM
module PREFIX(PORTS);
 
input clk;
input reset;
port GROUP_STUB_AXI;
 
output idle;
output scrbrd_empty;
//random parameters
integer GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND.DEFAULT;
wire GROUP_STUB_AXI_IX;
wire idle_IX;
wire scrbrd_empty_IX;
 
 
always @(*)
begin
#FFD;
PREFIX_singleIX.GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND;
end
assign idle = CONCAT(idle_IX &);
assign scrbrd_empty = CONCAT(scrbrd_empty_IX &);
CREATE axi_master_single.v
 
LOOP IX ID_NUM
PREFIX_single #(IX, IDIX_VAL, CMD_DEPTH)
PREFIX_singleIX(
.clk(clk),
.reset(reset),
.GROUP_STUB_AXI(GROUP_STUB_AXI_IX),
.idle(idle_IX),
.scrbrd_empty(scrbrd_empty_IX)
);
ENDLOOP IX
 
IFDEF TRUE(ID_NUM==1)
assign GROUP_STUB_AXI.OUT = GROUP_STUB_AXI_0.OUT;
assign GROUP_STUB_AXI_0.IN = GROUP_STUB_AXI.IN;
ELSE TRUE(ID_NUM==1)
 
CREATE ic.v DEFCMD(SWAP.GLOBAL PARENT PREFIX) DEFCMD(SWAP.GLOBAL MASTER_NUM ID_NUM) DEFCMD(SWAP.GLOBAL CONST(ID_BITS) ID_BITS) DEFCMD(SWAP.GLOBAL CONST(CMD_DEPTH) CMD_DEPTH) DEFCMD(SWAP.GLOBAL CONST(DATA_BITS) DATA_BITS) DEFCMD(SWAP.GLOBAL CONST(ADDR_BITS) ADDR_BITS)
LOOP IX ID_NUM
STOMP NEWLINE
DEFCMD(LOOP.GLOBAL MIX_IDX 1)
STOMP NEWLINE
DEFCMD(SWAP.GLOBAL ID_MIX_ID0 IDIX_VAL)
ENDLOOP IX
 
PREFIX_ic PREFIX_ic(
.clk(clk),
.reset(reset),
.MIX_GROUP_STUB_AXI(GROUP_STUB_AXI_IX),
.S0_GROUP_STUB_AXI(GROUP_STUB_AXI),
STOMP ,
);
 
ENDIF TRUE(ID_NUM==1)
 
 
task check_master_num;
input [24*8-1:0] task_name;
input [31:0] master_num;
begin
if (master_num >= ID_NUM)
begin
$display("FATAL ERROR: task %0s called for master %0d that does not exist.\tTime: %0d ns.", task_name, master_num, $time);
end
end
endtask
task enable;
input [31:0] master_num;
begin
check_master_num("enable", master_num);
case (master_num)
IX : PREFIX_singleIX.enable = 1;
endcase
end
endtask
 
task enable_all;
begin
PREFIX_singleIX.enable = 1;
end
endtask
task write_single;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
begin
check_master_num("write_single", master_num);
case (master_num)
IX : PREFIX_singleIX.write_single(addr, wdata);
endcase
end
endtask
 
task read_single;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
begin
check_master_num("read_single", master_num);
case (master_num)
IX : PREFIX_singleIX.read_single(addr, rdata);
endcase
end
endtask
 
task check_single;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] expected;
begin
check_master_num("check_single", master_num);
case (master_num)
IX : PREFIX_singleIX.check_single(addr, expected);
endcase
end
endtask
 
task write_and_check_single;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] data;
begin
check_master_num("write_and_check_single", master_num);
case (master_num)
IX : PREFIX_singleIX.write_and_check_single(addr, data);
endcase
end
endtask
 
task insert_wr_cmd;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
check_master_num("insert_wr_cmd", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_wr_cmd(addr, len, size);
endcase
end
endtask
 
task insert_rd_cmd;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
check_master_num("insert_rd_cmd", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_rd_cmd(addr, len, size);
endcase
end
endtask
 
task insert_wr_data;
input [31:0] master_num;
input [DATA_BITS-1:0] wdata;
begin
check_master_num("insert_wr_data", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_wr_data(wdata);
endcase
end
endtask
 
task insert_wr_incr_data;
input [31:0] master_num;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
check_master_num("insert_wr_incr_data", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_wr_incr_data(addr, len, size);
endcase
end
endtask
 
task insert_rand_chk;
input [31:0] master_num;
input [31:0] burst_num;
begin
check_master_num("insert_rand_chk", master_num);
case (master_num)
IX : PREFIX_singleIX.insert_rand_chk(burst_num);
endcase
end
endtask
 
 
endmodule
 
 
/src/base/axi_master_single.v
26,807 → 26,830
//// details. http://www.gnu.org/licenses/lgpl.html ////
//// ////
/////////////////////////////////////////////////////////////////////
 
OUTFILE PREFIX_single.v
 
INCLUDE def_axi_master.txt
 
module PREFIX_single(PORTS);
 
parameter MASTER_NUM = 0;
parameter MASTER_ID = 0;
parameter MASTER_PEND = 0;
`include "prgen_rand.v"
parameter MAX_CMDS = 16; //Depth of command FIFO
parameter DATA_LOG = LOG2(EXPR(DATA_BITS/8));
parameter PEND_BITS =
(MAX_CMDS <= 16) ? 4 :
(MAX_CMDS <= 32) ? 5 :
(MAX_CMDS <= 64) ? 6 :
(MAX_CMDS <= 128) ? 7 :
(MAX_CMDS <= 256) ? 8 :
(MAX_CMDS <= 512) ? 9 : 0; //0 is ilegal
input clk;
input reset;
port GROUP_STUB_AXI;
 
output idle;
output scrbrd_empty;
 
//random parameters
integer GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND.DEFAULT;
reg AWVALID_pre;
reg WVALID_pre;
wire BREADY_pre;
reg ARVALID_pre;
wire RREADY_pre;
reg enable = 0;
reg rd_enable = 0;
reg wr_enable = 0;
reg wait_for_write = 0;
reg scrbrd_enable = 0;
reg [LEN_BITS-1:0] wvalid_cnt;
 
reg rd_cmd_push = 0;
wire rd_cmd_pop;
wire [PEND_BITS:0] rd_cmd_fullness;
wire rd_cmd_empty;
wire rd_cmd_full;
reg [ADDR_BITS-1:0] rd_cmd_addr_in;
reg [LEN_BITS-1:0] rd_cmd_len_in;
reg [SIZE_BITS-1:0] rd_cmd_size_in;
wire [ADDR_BITS-1:0] rd_cmd_addr;
wire [LEN_BITS-1:0] rd_cmd_len;
wire [SIZE_BITS-1:0] rd_cmd_size;
reg rd_resp_push = 0;
wire rd_resp_pop;
wire rd_resp_empty;
wire rd_resp_full;
reg [ADDR_BITS-1:0] rd_resp_addr_in;
reg [SIZE_BITS-1:0] rd_resp_size_in;
wire [ADDR_BITS-1:0] rd_resp_addr;
wire [SIZE_BITS-1:0] rd_resp_size;
reg wr_cmd_push = 0;
wire wr_cmd_pop;
wire [PEND_BITS:0] wr_cmd_fullness;
wire wr_cmd_empty;
wire wr_cmd_full;
reg [ADDR_BITS-1:0] wr_cmd_addr_in;
reg [LEN_BITS-1:0] wr_cmd_len_in;
reg [SIZE_BITS-1:0] wr_cmd_size_in;
wire [ADDR_BITS-1:0] wr_cmd_addr;
wire [LEN_BITS-1:0] wr_cmd_len;
wire [SIZE_BITS-1:0] wr_cmd_size;
reg wr_data_push = 0;
wire wr_data_pop;
wire [PEND_BITS:0] wr_data_fullness;
wire wr_data_empty;
wire wr_data_full;
reg [ADDR_BITS-1:0] wr_data_addr_in;
reg [LEN_BITS-1:0] wr_data_len_in;
reg [SIZE_BITS-1:0] wr_data_size_in;
wire [ADDR_BITS-1:0] wr_data_addr;
wire [LEN_BITS-1:0] wr_data_len;
wire [SIZE_BITS-1:0] wr_data_size;
wire [DATA_BITS/8-1:0] wr_data_strb;
wire [7:0] wr_data_bytes;
wire [ADDR_BITS-1:0] wr_data_addr_prog;
wire [7:0] wr_data_offset;
wire wr_resp_push;
reg wr_resp_pop = 0;
wire wr_resp_empty;
wire wr_resp_full;
wire [1:0] wr_resp_resp_in;
wire [1:0] wr_resp_resp;
reg wr_fifo_push = 0;
wire wr_fifo_pop;
wire wr_fifo_empty;
wire wr_fifo_full;
reg [DATA_BITS-1:0] wr_fifo_data_in;
wire [DATA_BITS-1:0] wr_fifo_data;
wire rd_fifo_push;
reg rd_fifo_pop = 0;
wire rd_fifo_empty;
wire rd_fifo_full;
wire [DATA_BITS-1:0] rd_fifo_data_in;
wire [1:0] rd_fifo_resp_in;
wire [DATA_BITS-1:0] rd_fifo_data;
wire [1:0] rd_fifo_resp;
reg scrbrd_push = 0;
reg scrbrd_pop = 0;
wire scrbrd_empty;
wire scrbrd_full;
reg [ADDR_BITS-1:0] scrbrd_addr_in;
reg [DATA_BITS-1:0] scrbrd_data_in;
reg [DATA_BITS-1:0] scrbrd_mask_in;
wire [ADDR_BITS-1:0] scrbrd_addr;
wire [DATA_BITS-1:0] scrbrd_data;
wire [DATA_BITS-1:0] scrbrd_mask;
integer wr_fullness;
integer rd_fullness;
integer rd_completed;
integer wr_completed;
integer wr_pend_max = MASTER_PEND;
integer rd_pend_max = MASTER_PEND;
wire wr_hold;
wire rd_hold;
 
integer rand_chk_num = 0;
 
 
assign idle = rd_cmd_empty & rd_resp_empty & wr_cmd_empty & wr_data_empty & wr_resp_empty;
always @(rand_chk_num)
if (rand_chk_num > 0)
insert_rand_chk_loop(rand_chk_num);
always @(posedge enable)
begin
@(posedge clk);
wr_enable = 1;
repeat (50) @(posedge clk);
rd_enable = 1;
end
 
//for incremental data
reg [DATA_BITS-1:0] base_data = 0;
integer ww;
initial
begin
ww=0;
while (ww < DATA_BITS/8)
begin
base_data = base_data + ((MASTER_NUM + ww) << (ww*8));
ww = ww + 1;
end
end
assign rd_cmd_pop = ARVALID & ARREADY;
assign rd_resp_pop = RVALID & RREADY & RLAST;
assign rd_fifo_push = RVALID & RREADY;
assign wr_cmd_pop = AWVALID & AWREADY;
assign wr_data_pop = WVALID & WREADY & WLAST;
assign wr_fifo_pop = WVALID & WREADY;
assign wr_resp_push = BVALID & BREADY;
 
assign RREADY_pre = 1;
assign BREADY_pre = 1;
always @(posedge clk or posedge reset)
if (reset)
AWVALID_pre <= #FFD 1'b0;
else if ((wr_cmd_fullness == 1) & wr_cmd_pop)
AWVALID_pre <= #FFD 1'b0;
else if ((!wr_cmd_empty) & wr_enable)
AWVALID_pre <= #FFD 1'b1;
assign AWADDR = wr_cmd_addr;
assign AWLEN = wr_cmd_len;
assign AWSIZE = wr_cmd_size;
assign AWID = MASTER_ID;
assign AWBURST = 2'd1; //INCR only
assign AWCACHE = 4'd0; //not supported
assign AWPROT = 4'd0; //not supported
assign AWLOCK = 2'd0; //not supported
always @(posedge clk or posedge reset)
if (reset)
ARVALID_pre <= #FFD 1'b0;
else if (((rd_cmd_fullness == 1)) & rd_cmd_pop)
ARVALID_pre <= #FFD 1'b0;
else if ((!rd_cmd_empty) & rd_enable)
ARVALID_pre <= #FFD 1'b1;
 
assign ARADDR = rd_cmd_addr;
assign ARLEN = rd_cmd_len;
assign ARSIZE = rd_cmd_size;
assign ARID = MASTER_ID;
assign ARBURST = 2'd1; //INCR only
assign ARCACHE = 4'd0; //not supported
assign ARPROT = 4'd0; //not supported
assign ARLOCK = 2'd0; //not supported
 
assign rd_fifo_data_in = RDATA;
assign rd_fifo_resp_in = BRESP;
assign wr_data_bytes = 1'b1 << wr_data_size;
 
assign wr_data_strb =
wr_data_size == 'd0 ? 1'b1 :
wr_data_size == 'd1 ? 2'b11 :
wr_data_size == 'd2 ? 4'b1111 :
wr_data_size == 'd3 ? {8{1'b1}} :
wr_data_size == 'd4 ? {16{1'b1}} : 'd0;
 
assign wr_data_addr_prog = wr_data_addr + (wvalid_cnt * wr_data_bytes);
 
always @(posedge clk or posedge reset)
if (reset)
WVALID_pre <= #FFD 1'b0;
else if ((wr_data_fullness == 1) & wr_data_pop)
WVALID_pre <= #FFD 1'b0;
else if ((!wr_data_empty) & wr_enable)
WVALID_pre <= #FFD 1'b1;
 
assign wr_data_offset = wr_data_addr_prog[DATA_LOG-1:0];
assign WID = MASTER_ID;
assign WDATA = wr_fifo_empty ? 0 : wr_fifo_data;
assign WSTRB = wr_data_strb << wr_data_offset;
always @(posedge clk or posedge reset)
if (reset)
wvalid_cnt <= #FFD {LEN_BITS{1'b0}};
else if (wr_data_pop)
wvalid_cnt <= #FFD {LEN_BITS{1'b0}};
else if (WVALID & WREADY)
wvalid_cnt <= #FFD wvalid_cnt + 1'b1;
 
assign WLAST = WVALID & (wvalid_cnt == wr_data_len);
 
assign wr_resp_resp_in = BRESP;
always @(posedge clk or posedge reset)
if (reset)
begin
wr_fullness <= #FFD 0;
rd_fullness <= #FFD 0;
rd_completed <= #FFD 0;
wr_completed <= #FFD 0;
end
else
begin
wr_fullness <= #FFD wr_fullness + wr_cmd_pop - wr_resp_push;
rd_fullness <= #FFD rd_fullness + rd_cmd_pop - rd_resp_pop;
rd_completed <= #FFD rd_completed + rd_resp_pop;
wr_completed <= #FFD wr_completed + wr_resp_push;
end
assign wr_hold = wr_fullness >= wr_pend_max;
assign rd_hold = (rd_fullness >= rd_pend_max) | (wait_for_write & (wr_completed <= rd_completed + rd_fullness));
task insert_rd_cmd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
rd_cmd_addr_in = addr;
rd_cmd_len_in = len;
rd_cmd_size_in = size;
rd_resp_addr_in = addr;
rd_resp_size_in = size;
 
if (rd_cmd_full) enable = 1; //start stub not started yet
wait ((!rd_cmd_full) & (!rd_resp_full));
@(negedge clk); #FFD;
rd_cmd_push = 1;
rd_resp_push = 1;
@(posedge clk); #FFD;
rd_cmd_push = 0;
rd_resp_push = 0;
end
endtask
task insert_wr_cmd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
wr_cmd_addr_in = addr;
wr_cmd_len_in = len;
wr_cmd_size_in = size;
wr_data_addr_in = addr;
wr_data_len_in = len;
wr_data_size_in = size;
if (wr_cmd_full) enable = 1; //start stub not started yet
wait ((!wr_cmd_full) & (!wr_data_full));
@(negedge clk); #FFD;
wr_cmd_push = 1;
wr_data_push = 1;
@(posedge clk); #FFD;
wr_cmd_push = 0;
wr_data_push = 0;
end
endtask
 
task insert_wr_data;
input [DATA_BITS-1:0] wdata;
begin
wr_fifo_data_in = wdata;
wait (!wr_fifo_full);
@(negedge clk); #FFD;
wr_fifo_push = 1;
@(posedge clk); #FFD;
wr_fifo_push = 0;
end
endtask
 
task insert_wr_incr_data;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
integer valid_cnt;
integer wdata_cnt;
reg [7:0] data_cnt;
integer bytes;
reg [DATA_BITS-1:0] add_data;
reg [DATA_BITS-1:0] next_data;
begin
//insert data
valid_cnt = 0;
while (valid_cnt <= len)
begin
bytes = 1'b1 << size;
wdata_cnt = valid_cnt+(addr[DATA_LOG-1:0]/bytes);
data_cnt = ((wdata_cnt)/(DATA_BITS/(bytes*8))) * (DATA_BITS/8);
add_data = {DATA_BITS/8{data_cnt}};
next_data = base_data + add_data;
insert_wr_data(next_data);
valid_cnt = valid_cnt+1;
end
//insert command
insert_wr_cmd(addr, len, size);
end
endtask
task insert_scrbrd;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] data;
input [DATA_BITS-1:0] mask;
begin
scrbrd_enable = 1;
scrbrd_addr_in = addr;
scrbrd_data_in = data;
scrbrd_mask_in = mask;
wait (!scrbrd_full);
@(negedge clk); #FFD;
scrbrd_push = 1;
@(posedge clk); #FFD;
scrbrd_push = 0;
end
endtask
task insert_scrbrd_incr_data;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
integer valid_cnt;
integer wdata_cnt;
reg [7:0] data_cnt;
integer bytes;
reg [DATA_BITS-1:0] add_data;
reg [DATA_BITS-1:0] next_data;
reg [DATA_BITS:0] strb;
reg [DATA_BITS-1:0] mask;
reg [ADDR_BITS-1:0] next_addr;
begin
valid_cnt = 0;
while (valid_cnt <= len)
begin
bytes = 1'b1 << size;
wdata_cnt = valid_cnt+(addr[DATA_LOG-1:0]/bytes);
data_cnt = ((wdata_cnt)/(DATA_BITS/(bytes*8))) * (DATA_BITS/8);
add_data = {DATA_BITS/8{data_cnt}};
next_data = base_data + add_data;
next_addr = addr + (bytes * valid_cnt);
strb = (1 << (bytes*8)) - 1;
mask = strb << (next_addr[DATA_LOG-1:0]*8);
insert_scrbrd(next_addr, next_data, mask);
valid_cnt = valid_cnt+1;
end
end
endtask
task insert_rd_scrbrd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
begin
insert_scrbrd_incr_data(addr, len, size);
insert_rd_cmd(addr, len, size);
end
endtask
task insert_wr_rd_scrbrd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
begin
wait_for_write=1;
insert_wr_incr_data(addr, len, size);
insert_rd_scrbrd(addr, len, size);
end
endtask
 
task insert_wr_rd_scrbrd_rand;
reg [ADDR_BITS-1:0] addr;
reg [LEN_BITS-1:0] len;
reg [SIZE_BITS-1:0] size;
begin
len = rand(len_min, len_max);
size = rand(size_min, size_max);
addr = rand_align(addr_min, addr_max, 1 << size);
insert_wr_rd_scrbrd(addr, len, size);
end
endtask
task insert_rand_chk;
input [31:0] num;
 
rand_chk_num = num;
endtask
task insert_rand_chk_loop;
input [31:0] num;
integer i;
begin
i = 0;
while (i < num)
begin
insert_wr_rd_scrbrd_rand;
i = i + 1;
end
end
endtask
task insert_wr_single;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
 
reg [SIZE_BITS-1:0] size;
begin
size = EXPR((DATA_BITS/32)+1);
insert_wr_data(wdata);
insert_wr_cmd(addr, 0, size);
end
endtask
 
task get_rd_resp;
output [DATA_BITS-1:0] rdata;
output [1:0] resp;
reg [DATA_BITS-1:0] rdata;
reg [1:0] resp;
begin
wait (!rd_fifo_empty);
rdata = rd_fifo_data;
resp = rd_fifo_resp;
@(negedge clk); #FFD;
rd_fifo_pop = 1;
@(posedge clk); #FFD;
rd_fifo_pop = 0;
end
endtask
task get_scrbrd;
output [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
output [DATA_BITS-1:0] mask;
reg [ADDR_BITS-1:0] addr;
reg [DATA_BITS-1:0] rdata;
reg [DATA_BITS-1:0] mask;
begin
wait (!scrbrd_empty);
addr = scrbrd_addr;
rdata = scrbrd_data;
mask = scrbrd_mask;
@(negedge clk); #FFD;
scrbrd_pop = 1;
@(posedge clk); #FFD;
scrbrd_pop = 0;
end
endtask
task get_wr_resp;
output [1:0] resp;
 
reg [1:0] resp;
begin
wait (!wr_resp_empty);
resp = wr_resp_resp;
@(negedge clk); #FFD;
wr_resp_pop = 1;
@(posedge clk); #FFD;
wr_resp_pop = 0;
end
endtask
task insert_rd_single;
input [ADDR_BITS-1:0] addr;
 
reg [SIZE_BITS-1:0] size;
begin
size = EXPR((DATA_BITS/32)+1);
insert_rd_cmd(addr, 0, size);
end
endtask
 
task read_single_ack;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
output [1:0] resp;
reg [1:0] resp;
begin
insert_rd_single(addr);
get_rd_resp(rdata, resp);
end
endtask
task write_single_ack;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
output [1:0] resp;
 
reg [1:0] resp;
begin
insert_wr_single(addr, wdata);
get_wr_resp(resp);
end
endtask
task read_single;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
reg [1:0] resp;
begin
read_single_ack(addr, rdata, resp);
end
endtask
task write_single;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
 
reg [1:0] resp;
begin
write_single_ack(addr, wdata, resp);
end
endtask
 
task chk_scrbrd;
reg [ADDR_BITS-1:0] addr;
reg [DATA_BITS-1:0] mask;
reg [DATA_BITS-1:0] expected_data;
reg [DATA_BITS-1:0] rdata;
reg [DATA_BITS-1:0] rdata_masked;
reg [1:0] resp;
begin
if (!wr_resp_empty) get_wr_resp(resp);
get_scrbrd(addr, expected_data, mask);
get_rd_resp(rdata, resp);
expected_data = expected_data & mask; //TBD insert z as dontcare (for print)
rdata_masked = rdata & mask;
if (expected_data !== rdata_masked)
$display("MASTER%0d: SCRBRD_ERROR: Address: 0x%0h, Expected: 0x%0h, Received: 0x%0h.\tTime: %0d ns.", MASTER_NUM, addr, expected_data, rdata, $time);
end
endtask
 
always @(posedge scrbrd_enable)
begin
while (scrbrd_enable)
begin
chk_scrbrd;
end
end
 
CREATE prgen_fifo.v DEFCMD(DEFINE STUB)
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS)
rd_cmd_list(
.clk(clk),
.reset(reset),
.push(rd_cmd_push),
.pop(rd_cmd_pop),
.din({
rd_cmd_size_in,
rd_cmd_len_in,
rd_cmd_addr_in
}),
.dout({
rd_cmd_size,
rd_cmd_len,
rd_cmd_addr
}),
.fullness(rd_cmd_fullness),
.empty(rd_cmd_empty),
.full(rd_cmd_full)
);
 
prgen_fifo_stub #(ADDR_BITS+SIZE_BITS, MAX_CMDS)
rd_resp_list(
.clk(clk),
.reset(reset),
.push(rd_resp_push),
.pop(rd_resp_pop),
.din({
rd_resp_addr_in,
rd_resp_size_in
}),
.dout({
rd_resp_addr,
rd_resp_size
}),
.empty(rd_resp_empty),
.full(rd_resp_full)
);
 
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS)
wr_cmd_list(
.clk(clk),
.reset(reset),
.push(wr_cmd_push),
.pop(wr_cmd_pop),
.din({
wr_cmd_size_in,
wr_cmd_len_in,
wr_cmd_addr_in
}),
.dout({
wr_cmd_size,
wr_cmd_len,
wr_cmd_addr
}),
.fullness(wr_cmd_fullness),
.empty(wr_cmd_empty),
.full(wr_cmd_full)
);
 
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS)
wr_data_list(
.clk(clk),
.reset(reset),
.push(wr_data_push),
.pop(wr_data_pop),
.din({
wr_data_size_in,
wr_data_len_in,
wr_data_addr_in
}),
.dout({
wr_data_size,
wr_data_len,
wr_data_addr
}),
.fullness(wr_data_fullness),
.empty(wr_data_empty),
.full(wr_data_full)
);
 
prgen_fifo_stub #(2, MAX_CMDS)
wr_resp_list(
.clk(clk),
.reset(reset),
.push(wr_resp_push),
.pop(wr_resp_pop),
.din(wr_resp_resp_in),
.dout(wr_resp_resp),
.empty(wr_resp_empty),
.full(wr_resp_full)
);
 
prgen_fifo_stub #(DATA_BITS, MAX_CMDS*EXPR(2^LEN_BITS))
wr_data_fifo(
.clk(clk),
.reset(reset),
.push(wr_fifo_push),
.pop(wr_fifo_pop),
.din(wr_fifo_data_in),
.dout(wr_fifo_data),
.empty(wr_fifo_empty),
.full(wr_fifo_full)
);
 
prgen_fifo_stub #(DATA_BITS+2, MAX_CMDS*EXPR(2^LEN_BITS))
rd_data_fifo(
.clk(clk),
.reset(reset),
.push(rd_fifo_push),
.pop(rd_fifo_pop),
.din({
rd_fifo_data_in,
rd_fifo_resp_in
}),
.dout({
rd_fifo_data,
rd_fifo_resp
}),
.empty(rd_fifo_empty),
.full(rd_fifo_full)
);
 
prgen_fifo_stub #(ADDR_BITS+2*DATA_BITS, MAX_CMDS*EXPR(2^LEN_BITS))
scrbrd_fifo(
.clk(clk),
.reset(reset),
.push(scrbrd_push),
.pop(scrbrd_pop),
.din({
scrbrd_addr_in,
scrbrd_data_in,
scrbrd_mask_in
}),
.dout({
scrbrd_addr,
scrbrd_data,
scrbrd_mask
}),
.empty(scrbrd_empty),
.full(scrbrd_full)
);
 
 
CREATE axi_master_stall.v
PREFIX_stall
PREFIX_stall (
.clk(clk),
.reset(reset),
 
.rd_hold(rd_hold),
.wr_hold(wr_hold),
.ARVALID_pre(ARVALID_pre),
.RREADY_pre(RREADY_pre),
.AWVALID_pre(AWVALID_pre),
.WVALID_pre(WVALID_pre),
.BREADY_pre(BREADY_pre),
.ARREADY(ARREADY),
.AWREADY(AWREADY),
.WREADY(WREADY),
.ARVALID(ARVALID),
.RREADY(RREADY),
.AWVALID(AWVALID),
.WVALID(WVALID),
.BREADY(BREADY)
);
 
 
endmodule
 
 
 
OUTFILE PREFIX_single.v
 
INCLUDE def_axi_master.txt
 
module PREFIX_single(PORTS);
 
parameter MASTER_NUM = 0;
parameter MASTER_ID = 0;
parameter MASTER_PEND = 0;
`include "prgen_rand.v"
parameter MAX_CMDS = 16; //Depth of command FIFO
parameter DATA_LOG = LOG2(EXPR(DATA_BITS/8));
parameter PEND_BITS =
(MAX_CMDS <= 16) ? 4 :
(MAX_CMDS <= 32) ? 5 :
(MAX_CMDS <= 64) ? 6 :
(MAX_CMDS <= 128) ? 7 :
(MAX_CMDS <= 256) ? 8 :
(MAX_CMDS <= 512) ? 9 : 0; //0 is ilegal
input clk;
input reset;
port GROUP_STUB_AXI;
 
output idle;
output scrbrd_empty;
 
//random parameters
integer GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND.DEFAULT;
reg AWVALID_pre;
reg WVALID_pre;
wire BREADY_pre;
reg ARVALID_pre;
wire RREADY_pre;
reg enable = 0;
reg rd_enable = 0;
reg wr_enable = 0;
reg wait_for_write = 0;
reg scrbrd_enable = 0;
reg [LEN_BITS-1:0] wvalid_cnt;
 
reg rd_cmd_push = 0;
wire rd_cmd_pop;
wire [PEND_BITS:0] rd_cmd_fullness;
wire rd_cmd_empty;
wire rd_cmd_full;
reg [ADDR_BITS-1:0] rd_cmd_addr_in;
reg [LEN_BITS-1:0] rd_cmd_len_in;
reg [SIZE_BITS-1:0] rd_cmd_size_in;
wire [ADDR_BITS-1:0] rd_cmd_addr;
wire [LEN_BITS-1:0] rd_cmd_len;
wire [SIZE_BITS-1:0] rd_cmd_size;
reg rd_resp_push = 0;
wire rd_resp_pop;
wire rd_resp_empty;
wire rd_resp_full;
reg [ADDR_BITS-1:0] rd_resp_addr_in;
reg [SIZE_BITS-1:0] rd_resp_size_in;
wire [ADDR_BITS-1:0] rd_resp_addr;
wire [SIZE_BITS-1:0] rd_resp_size;
reg wr_cmd_push = 0;
wire wr_cmd_pop;
wire [PEND_BITS:0] wr_cmd_fullness;
wire wr_cmd_empty;
wire wr_cmd_full;
reg [ADDR_BITS-1:0] wr_cmd_addr_in;
reg [LEN_BITS-1:0] wr_cmd_len_in;
reg [SIZE_BITS-1:0] wr_cmd_size_in;
wire [ADDR_BITS-1:0] wr_cmd_addr;
wire [LEN_BITS-1:0] wr_cmd_len;
wire [SIZE_BITS-1:0] wr_cmd_size;
reg wr_data_push = 0;
wire wr_data_pop;
wire [PEND_BITS:0] wr_data_fullness;
wire wr_data_empty;
wire wr_data_full;
reg [ADDR_BITS-1:0] wr_data_addr_in;
reg [LEN_BITS-1:0] wr_data_len_in;
reg [SIZE_BITS-1:0] wr_data_size_in;
wire [ADDR_BITS-1:0] wr_data_addr;
wire [LEN_BITS-1:0] wr_data_len;
wire [SIZE_BITS-1:0] wr_data_size;
wire [DATA_BITS/8-1:0] wr_data_strb;
wire [7:0] wr_data_bytes;
wire [ADDR_BITS-1:0] wr_data_addr_prog;
wire [7:0] wr_data_offset;
wire wr_resp_push;
reg wr_resp_pop = 0;
wire wr_resp_empty;
wire wr_resp_full;
wire [1:0] wr_resp_resp_in;
wire [1:0] wr_resp_resp;
reg wr_fifo_push = 0;
wire wr_fifo_pop;
wire wr_fifo_empty;
wire wr_fifo_full;
reg [DATA_BITS-1:0] wr_fifo_data_in;
wire [DATA_BITS-1:0] wr_fifo_data;
wire rd_fifo_push;
reg rd_fifo_pop = 0;
wire rd_fifo_empty;
wire rd_fifo_full;
wire [DATA_BITS-1:0] rd_fifo_data_in;
wire [1:0] rd_fifo_resp_in;
wire [DATA_BITS-1:0] rd_fifo_data;
wire [1:0] rd_fifo_resp;
reg scrbrd_push = 0;
reg scrbrd_pop = 0;
wire scrbrd_empty;
wire scrbrd_full;
reg [ADDR_BITS-1:0] scrbrd_addr_in;
reg [DATA_BITS-1:0] scrbrd_data_in;
reg [DATA_BITS-1:0] scrbrd_mask_in;
wire [ADDR_BITS-1:0] scrbrd_addr;
wire [DATA_BITS-1:0] scrbrd_data;
wire [DATA_BITS-1:0] scrbrd_mask;
integer wr_fullness;
integer rd_fullness;
integer rd_completed;
integer wr_completed;
integer wr_pend_max = MASTER_PEND;
integer rd_pend_max = MASTER_PEND;
wire wr_hold;
wire rd_hold;
 
integer rand_chk_num = 0;
 
 
assign idle = rd_cmd_empty & rd_resp_empty & wr_cmd_empty & wr_data_empty & wr_resp_empty;
always @(rand_chk_num)
if (rand_chk_num > 0)
insert_rand_chk_loop(rand_chk_num);
always @(posedge enable)
begin
@(posedge clk);
wr_enable = 1;
repeat (50) @(posedge clk);
rd_enable = 1;
end
 
//for incremental data
reg [DATA_BITS-1:0] base_data = 0;
integer ww;
initial
begin
ww=0;
while (ww < DATA_BITS/8)
begin
base_data = base_data + ((MASTER_NUM + ww) << (ww*8));
ww = ww + 1;
end
end
assign rd_cmd_pop = ARVALID & ARREADY;
assign rd_resp_pop = RVALID & RREADY & RLAST;
assign rd_fifo_push = RVALID & RREADY;
assign wr_cmd_pop = AWVALID & AWREADY;
assign wr_data_pop = WVALID & WREADY & WLAST;
assign wr_fifo_pop = WVALID & WREADY;
assign wr_resp_push = BVALID & BREADY;
 
assign RREADY_pre = 1;
assign BREADY_pre = 1;
always @(posedge clk or posedge reset)
if (reset)
AWVALID_pre <= #FFD 1'b0;
else if ((wr_cmd_fullness == 1) & wr_cmd_pop)
AWVALID_pre <= #FFD 1'b0;
else if ((!wr_cmd_empty) & wr_enable)
AWVALID_pre <= #FFD 1'b1;
assign AWADDR = wr_cmd_addr;
assign AWLEN = wr_cmd_len;
assign AWSIZE = wr_cmd_size;
assign AWID = MASTER_ID;
assign AWBURST = 2'd1; //INCR only
assign AWCACHE = 4'd0; //not supported
assign AWPROT = 4'd0; //not supported
assign AWLOCK = 2'd0; //not supported
always @(posedge clk or posedge reset)
if (reset)
ARVALID_pre <= #FFD 1'b0;
else if (((rd_cmd_fullness == 1)) & rd_cmd_pop)
ARVALID_pre <= #FFD 1'b0;
else if ((!rd_cmd_empty) & rd_enable)
ARVALID_pre <= #FFD 1'b1;
 
assign ARADDR = rd_cmd_addr;
assign ARLEN = rd_cmd_len;
assign ARSIZE = rd_cmd_size;
assign ARID = MASTER_ID;
assign ARBURST = 2'd1; //INCR only
assign ARCACHE = 4'd0; //not supported
assign ARPROT = 4'd0; //not supported
assign ARLOCK = 2'd0; //not supported
 
assign rd_fifo_data_in = RDATA;
assign rd_fifo_resp_in = BRESP;
assign wr_data_bytes = 1'b1 << wr_data_size;
 
assign wr_data_strb =
wr_data_size == 'd0 ? 1'b1 :
wr_data_size == 'd1 ? 2'b11 :
wr_data_size == 'd2 ? 4'b1111 :
wr_data_size == 'd3 ? {8{1'b1}} :
wr_data_size == 'd4 ? {16{1'b1}} : 'd0;
 
assign wr_data_addr_prog = wr_data_addr + (wvalid_cnt * wr_data_bytes);
 
always @(posedge clk or posedge reset)
if (reset)
WVALID_pre <= #FFD 1'b0;
else if ((wr_data_fullness == 1) & wr_data_pop)
WVALID_pre <= #FFD 1'b0;
else if ((!wr_data_empty) & wr_enable)
WVALID_pre <= #FFD 1'b1;
 
assign wr_data_offset = wr_data_addr_prog[DATA_LOG-1:0];
assign WID = MASTER_ID;
assign WDATA = wr_fifo_empty ? 0 : wr_fifo_data;
assign WSTRB = wr_data_strb << wr_data_offset;
always @(posedge clk or posedge reset)
if (reset)
wvalid_cnt <= #FFD {LEN_BITS{1'b0}};
else if (wr_data_pop)
wvalid_cnt <= #FFD {LEN_BITS{1'b0}};
else if (WVALID & WREADY)
wvalid_cnt <= #FFD wvalid_cnt + 1'b1;
 
assign WLAST = WVALID & (wvalid_cnt == wr_data_len);
 
assign wr_resp_resp_in = BRESP;
always @(posedge clk or posedge reset)
if (reset)
begin
wr_fullness <= #FFD 0;
rd_fullness <= #FFD 0;
rd_completed <= #FFD 0;
wr_completed <= #FFD 0;
end
else
begin
wr_fullness <= #FFD wr_fullness + wr_cmd_pop - wr_resp_push;
rd_fullness <= #FFD rd_fullness + rd_cmd_pop - rd_resp_pop;
rd_completed <= #FFD rd_completed + rd_resp_pop;
wr_completed <= #FFD wr_completed + wr_resp_push;
end
assign wr_hold = wr_fullness >= wr_pend_max;
assign rd_hold = (rd_fullness >= rd_pend_max) | (wait_for_write & (wr_completed <= rd_completed + rd_fullness));
task insert_rd_cmd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
rd_cmd_addr_in = addr;
rd_cmd_len_in = len;
rd_cmd_size_in = size;
rd_resp_addr_in = addr;
rd_resp_size_in = size;
 
if (rd_cmd_full) enable = 1; //start stub not started yet
wait ((!rd_cmd_full) & (!rd_resp_full));
@(negedge clk); #FFD;
rd_cmd_push = 1;
rd_resp_push = 1;
@(posedge clk); #FFD;
rd_cmd_push = 0;
rd_resp_push = 0;
end
endtask
task insert_wr_cmd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
begin
wr_cmd_addr_in = addr;
wr_cmd_len_in = len;
wr_cmd_size_in = size;
wr_data_addr_in = addr;
wr_data_len_in = len;
wr_data_size_in = size;
if (wr_cmd_full) enable = 1; //start stub not started yet
wait ((!wr_cmd_full) & (!wr_data_full));
@(negedge clk); #FFD;
wr_cmd_push = 1;
wr_data_push = 1;
@(posedge clk); #FFD;
wr_cmd_push = 0;
wr_data_push = 0;
end
endtask
 
task insert_wr_data;
input [DATA_BITS-1:0] wdata;
begin
wr_fifo_data_in = wdata;
wait (!wr_fifo_full);
@(negedge clk); #FFD;
wr_fifo_push = 1;
@(posedge clk); #FFD;
wr_fifo_push = 0;
end
endtask
 
task insert_wr_incr_data;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
integer valid_cnt;
integer wdata_cnt;
reg [7:0] data_cnt;
integer bytes;
reg [DATA_BITS-1:0] add_data;
reg [DATA_BITS-1:0] next_data;
begin
//insert data
valid_cnt = 0;
while (valid_cnt <= len)
begin
bytes = 1'b1 << size;
wdata_cnt = valid_cnt+(addr[DATA_LOG-1:0]/bytes);
data_cnt = ((wdata_cnt)/(DATA_BITS/(bytes*8))) * (DATA_BITS/8);
add_data = {DATA_BITS/8{data_cnt}};
next_data = (use_addr_base ? addr : base_data) + add_data;
insert_wr_data(next_data);
valid_cnt = valid_cnt+1;
end
//insert command
insert_wr_cmd(addr, len, size);
end
endtask
task insert_scrbrd;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] data;
input [DATA_BITS-1:0] mask;
begin
scrbrd_enable = 1;
scrbrd_addr_in = addr;
scrbrd_data_in = data;
scrbrd_mask_in = mask;
wait (!scrbrd_full);
@(negedge clk); #FFD;
scrbrd_push = 1;
@(posedge clk); #FFD;
scrbrd_push = 0;
end
endtask
task insert_scrbrd_incr_data;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
integer valid_cnt;
integer wdata_cnt;
reg [7:0] data_cnt;
integer bytes;
reg [DATA_BITS-1:0] add_data;
reg [DATA_BITS-1:0] next_data;
reg [DATA_BITS:0] strb;
reg [DATA_BITS-1:0] mask;
reg [ADDR_BITS-1:0] next_addr;
begin
valid_cnt = 0;
while (valid_cnt <= len)
begin
bytes = 1'b1 << size;
wdata_cnt = valid_cnt+(addr[DATA_LOG-1:0]/bytes);
data_cnt = ((wdata_cnt)/(DATA_BITS/(bytes*8))) * (DATA_BITS/8);
add_data = {DATA_BITS/8{data_cnt}};
next_data = (use_addr_base ? addr : base_data) + add_data;
next_addr = addr + (bytes * valid_cnt);
strb = (1 << (bytes*8)) - 1;
mask = strb << (next_addr[DATA_LOG-1:0]*8);
insert_scrbrd(next_addr, next_data, mask);
valid_cnt = valid_cnt+1;
end
end
endtask
task insert_rd_scrbrd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
begin
insert_scrbrd_incr_data(addr, len, size);
insert_rd_cmd(addr, len, size);
end
endtask
task insert_wr_rd_scrbrd;
input [ADDR_BITS-1:0] addr;
input [LEN_BITS-1:0] len;
input [SIZE_BITS-1:0] size;
 
begin
wait_for_write=1;
insert_wr_incr_data(addr, len, size);
insert_rd_scrbrd(addr, len, size);
end
endtask
 
task insert_wr_rd_scrbrd_rand;
reg [ADDR_BITS-1:0] addr;
reg [LEN_BITS-1:0] len;
reg [SIZE_BITS-1:0] size;
begin
len = rand(len_min, len_max);
size = rand(size_min, size_max);
addr = rand_align(addr_min, addr_max, 1 << size);
insert_wr_rd_scrbrd(addr, len, size);
end
endtask
task insert_rand_chk;
input [31:0] num;
 
rand_chk_num = num;
endtask
task insert_rand_chk_loop;
input [31:0] num;
integer i;
begin
i = 0;
while (i < num)
begin
insert_wr_rd_scrbrd_rand;
i = i + 1;
end
end
endtask
task insert_wr_single;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
 
reg [SIZE_BITS-1:0] size;
begin
size = EXPR((DATA_BITS/32)+1);
insert_wr_data(wdata);
insert_wr_cmd(addr, 0, size);
end
endtask
 
task get_rd_resp;
output [DATA_BITS-1:0] rdata;
output [1:0] resp;
reg [DATA_BITS-1:0] rdata;
reg [1:0] resp;
begin
wait (!rd_fifo_empty);
rdata = rd_fifo_data;
resp = rd_fifo_resp;
@(negedge clk); #FFD;
rd_fifo_pop = 1;
@(posedge clk); #FFD;
rd_fifo_pop = 0;
end
endtask
task get_scrbrd;
output [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
output [DATA_BITS-1:0] mask;
reg [ADDR_BITS-1:0] addr;
reg [DATA_BITS-1:0] rdata;
reg [DATA_BITS-1:0] mask;
begin
wait (!scrbrd_empty);
addr = scrbrd_addr;
rdata = scrbrd_data;
mask = scrbrd_mask;
@(negedge clk); #FFD;
scrbrd_pop = 1;
@(posedge clk); #FFD;
scrbrd_pop = 0;
end
endtask
task get_wr_resp;
output [1:0] resp;
 
reg [1:0] resp;
begin
wait (!wr_resp_empty);
resp = wr_resp_resp;
@(negedge clk); #FFD;
wr_resp_pop = 1;
@(posedge clk); #FFD;
wr_resp_pop = 0;
end
endtask
task insert_rd_single;
input [ADDR_BITS-1:0] addr;
 
reg [SIZE_BITS-1:0] size;
begin
size = EXPR((DATA_BITS/32)+1);
insert_rd_cmd(addr, 0, size);
end
endtask
 
task read_single_ack;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
output [1:0] resp;
reg [1:0] resp;
begin
insert_rd_single(addr);
get_rd_resp(rdata, resp);
end
endtask
task write_single_ack;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
output [1:0] resp;
 
reg [1:0] resp;
begin
insert_wr_single(addr, wdata);
get_wr_resp(resp);
end
endtask
task read_single;
input [ADDR_BITS-1:0] addr;
output [DATA_BITS-1:0] rdata;
reg [1:0] resp;
begin
read_single_ack(addr, rdata, resp);
end
endtask
task check_single;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] expected;
reg [1:0] resp;
reg [DATA_BITS-1:0] rdata;
begin
read_single_ack(addr, rdata, resp);
if (rdata !== expected)
$display("MASTER%0d: CHK_SINGLE_ERROR: Address: 0x%0h, Expected: 0x%0h, Received: 0x%0h.\tTime: %0d ns.", MASTER_NUM, addr, expected, rdata, $time);
end
endtask
task write_and_check_single;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] data;
begin
write_single(addr, data);
check_single(addr, data);
end
endtask
task write_single;
input [ADDR_BITS-1:0] addr;
input [DATA_BITS-1:0] wdata;
 
reg [1:0] resp;
begin
write_single_ack(addr, wdata, resp);
end
endtask
 
task chk_scrbrd;
reg [ADDR_BITS-1:0] addr;
reg [DATA_BITS-1:0] mask;
reg [DATA_BITS-1:0] expected_data;
reg [DATA_BITS-1:0] rdata;
reg [DATA_BITS-1:0] rdata_masked;
reg [1:0] resp;
begin
if (!wr_resp_empty) get_wr_resp(resp);
get_scrbrd(addr, expected_data, mask);
get_rd_resp(rdata, resp);
expected_data = expected_data & mask; //TBD insert z as dontcare (for print)
rdata_masked = rdata & mask;
if (expected_data !== rdata_masked)
$display("MASTER%0d: SCRBRD_ERROR: Address: 0x%0h, Expected: 0x%0h, Received: 0x%0h.\tTime: %0d ns.", MASTER_NUM, addr, expected_data, rdata, $time);
end
endtask
 
always @(posedge scrbrd_enable)
begin
while (scrbrd_enable)
begin
chk_scrbrd;
end
end
 
CREATE prgen_fifo.v DEFCMD(DEFINE STUB)
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS)
rd_cmd_list(
.clk(clk),
.reset(reset),
.push(rd_cmd_push),
.pop(rd_cmd_pop),
.din({
rd_cmd_size_in,
rd_cmd_len_in,
rd_cmd_addr_in
}),
.dout({
rd_cmd_size,
rd_cmd_len,
rd_cmd_addr
}),
.fullness(rd_cmd_fullness),
.empty(rd_cmd_empty),
.full(rd_cmd_full)
);
 
prgen_fifo_stub #(ADDR_BITS+SIZE_BITS, MAX_CMDS)
rd_resp_list(
.clk(clk),
.reset(reset),
.push(rd_resp_push),
.pop(rd_resp_pop),
.din({
rd_resp_addr_in,
rd_resp_size_in
}),
.dout({
rd_resp_addr,
rd_resp_size
}),
.empty(rd_resp_empty),
.full(rd_resp_full)
);
 
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS)
wr_cmd_list(
.clk(clk),
.reset(reset),
.push(wr_cmd_push),
.pop(wr_cmd_pop),
.din({
wr_cmd_size_in,
wr_cmd_len_in,
wr_cmd_addr_in
}),
.dout({
wr_cmd_size,
wr_cmd_len,
wr_cmd_addr
}),
.fullness(wr_cmd_fullness),
.empty(wr_cmd_empty),
.full(wr_cmd_full)
);
 
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS)
wr_data_list(
.clk(clk),
.reset(reset),
.push(wr_data_push),
.pop(wr_data_pop),
.din({
wr_data_size_in,
wr_data_len_in,
wr_data_addr_in
}),
.dout({
wr_data_size,
wr_data_len,
wr_data_addr
}),
.fullness(wr_data_fullness),
.empty(wr_data_empty),
.full(wr_data_full)
);
 
prgen_fifo_stub #(2, MAX_CMDS)
wr_resp_list(
.clk(clk),
.reset(reset),
.push(wr_resp_push),
.pop(wr_resp_pop),
.din(wr_resp_resp_in),
.dout(wr_resp_resp),
.empty(wr_resp_empty),
.full(wr_resp_full)
);
 
prgen_fifo_stub #(DATA_BITS, MAX_CMDS*EXPR(2^LEN_BITS))
wr_data_fifo(
.clk(clk),
.reset(reset),
.push(wr_fifo_push),
.pop(wr_fifo_pop),
.din(wr_fifo_data_in),
.dout(wr_fifo_data),
.empty(wr_fifo_empty),
.full(wr_fifo_full)
);
 
prgen_fifo_stub #(DATA_BITS+2, MAX_CMDS*EXPR(2^LEN_BITS))
rd_data_fifo(
.clk(clk),
.reset(reset),
.push(rd_fifo_push),
.pop(rd_fifo_pop),
.din({
rd_fifo_data_in,
rd_fifo_resp_in
}),
.dout({
rd_fifo_data,
rd_fifo_resp
}),
.empty(rd_fifo_empty),
.full(rd_fifo_full)
);
 
prgen_fifo_stub #(ADDR_BITS+2*DATA_BITS, MAX_CMDS*EXPR(2^LEN_BITS))
scrbrd_fifo(
.clk(clk),
.reset(reset),
.push(scrbrd_push),
.pop(scrbrd_pop),
.din({
scrbrd_addr_in,
scrbrd_data_in,
scrbrd_mask_in
}),
.dout({
scrbrd_addr,
scrbrd_data,
scrbrd_mask
}),
.empty(scrbrd_empty),
.full(scrbrd_full)
);
 
 
CREATE axi_master_stall.v
PREFIX_stall
PREFIX_stall (
.clk(clk),
.reset(reset),
 
.rd_hold(rd_hold),
.wr_hold(wr_hold),
.ARVALID_pre(ARVALID_pre),
.RREADY_pre(RREADY_pre),
.AWVALID_pre(AWVALID_pre),
.WVALID_pre(WVALID_pre),
.BREADY_pre(BREADY_pre),
.ARREADY(ARREADY),
.AWREADY(AWREADY),
.WREADY(WREADY),
.ARVALID(ARVALID),
.RREADY(RREADY),
.AWVALID(AWVALID),
.WVALID(WVALID),
.BREADY(BREADY)
);
 
 
endmodule
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.