blob: c6102230552efb420bd595e2d51d4624e81a7223 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Filename: xlnxfull.v
//
// Project: WB2AXIPSP: bus bridges and other odds and ends
//
// Purpose: To test the formal tools on an AXI4 (full) core that is "known"
// to work. (Only this one doesn't, but at least that was my
// initial purpose.) Most of this code comes directly from Vivado's core
// generator--starting at the end of this comment block and going down
// directly to the initial statements before the `ifdef FORMAL block at
// the bottom. I have made superficial adjustments to Xilinx's code: I
// swapped spaces for tabs, I removed any white space at the ends of
// lines, I fixed any spelling errors that I noticed in the comments, added
// the default_nettype, added initial statements (just before the ifdef
// FORMAL) for things that should've had them in the first place, etc.
// I may have even swapped an always @(somevalue) for an always @(*), but
// that's as far as I've gone.
//
// I was surprised to learn that this core passed, and would always pass,
// a Xilinx VIP check as is. It does not pass a formal verification check.
//
// Creator: Vivado, 2018.3
//
////////////////////////////////////////////////////////////////////////////////
//
//
`default_nettype none // Added to the raw demo
`timescale 1 ns / 1 ps
//
module xlnxfull_2018_3 #(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// Width of ID for for write address, write data, read address and read data
parameter integer C_S_AXI_ID_WIDTH = 1,
// Width of S_AXI data bus
parameter integer C_S_AXI_DATA_WIDTH = 32,
// Width of S_AXI address bus
parameter integer C_S_AXI_ADDR_WIDTH = 6,
// Width of optional user defined signal in write address channel
parameter integer C_S_AXI_AWUSER_WIDTH = 0,
// Width of optional user defined signal in read address channel
parameter integer C_S_AXI_ARUSER_WIDTH = 0,
// Width of optional user defined signal in write data channel
parameter integer C_S_AXI_WUSER_WIDTH = 0,
// Width of optional user defined signal in read data channel
parameter integer C_S_AXI_RUSER_WIDTH = 0,
// Width of optional user defined signal in write response channel
parameter integer C_S_AXI_BUSER_WIDTH = 0
) (
// Users to add ports here
// User ports ends
// Do not modify the ports beyond this line
// Global Clock Signal
input wire S_AXI_ACLK,
// Global Reset Signal. This Signal is Active LOW
input wire S_AXI_ARESETN,
// Write Address ID
input wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_AWID,
// Write address
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
// Burst length. The burst length gives the exact number of transfers in a burst
input wire [7 : 0] S_AXI_AWLEN,
// Burst size. This signal indicates the size of each transfer in the burst
input wire [2 : 0] S_AXI_AWSIZE,
// Burst type. The burst type and the size information,
// determine how the address for each transfer within the burst is calculated.
input wire [1 : 0] S_AXI_AWBURST,
// Lock type. Provides additional information about the
// atomic characteristics of the transfer.
input wire S_AXI_AWLOCK,
// Memory type. This signal indicates how transactions
// are required to progress through a system.
input wire [3 : 0] S_AXI_AWCACHE,
// Protection type. This signal indicates the privilege
// and security level of the transaction, and whether
// the transaction is a data access or an instruction access.
input wire [2 : 0] S_AXI_AWPROT,
// Quality of Service, QoS identifier sent for each
// write transaction.
input wire [3 : 0] S_AXI_AWQOS,
// Region identifier. Permits a single physical interface
// on a slave to be used for multiple logical interfaces.
input wire [3 : 0] S_AXI_AWREGION,
// Optional User-defined signal in the write address channel.
// input wire [C_S_AXI_AWUSER_WIDTH-1 : 0] S_AXI_AWUSER,
// Write address valid. This signal indicates that
// the channel is signaling valid write address and
// control information.
input wire S_AXI_AWVALID,
// Write address ready. This signal indicates that
// the slave is ready to accept an address and associated
// control signals.
output wire S_AXI_AWREADY,
// Write Data
input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
// Write strobes. This signal indicates which byte
// lanes hold valid data. There is one write strobe
// bit for each eight bits of the write data bus.
input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
// Write last. This signal indicates the last transfer
// in a write burst.
input wire S_AXI_WLAST,
// Optional User-defined signal in the write data channel.
// input wire [C_S_AXI_WUSER_WIDTH-1 : 0] S_AXI_WUSER,
// Write valid. This signal indicates that valid write
// data and strobes are available.
input wire S_AXI_WVALID,
// Write ready. This signal indicates that the slave
// can accept the write data.
output wire S_AXI_WREADY,
// Response ID tag. This signal is the ID tag of the
// write response.
output wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_BID,
// Write response. This signal indicates the status
// of the write transaction.
output wire [1 : 0] S_AXI_BRESP,
// Optional User-defined signal in the write response channel.
// output wire [C_S_AXI_BUSER_WIDTH-1 : 0] S_AXI_BUSER,
// Write response valid. This signal indicates that the
// channel is signaling a valid write response.
output wire S_AXI_BVALID,
// Response ready. This signal indicates that the master
// can accept a write response.
input wire S_AXI_BREADY,
// Read address ID. This signal is the identification
// tag for the read address group of signals.
input wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_ARID,
// Read address. This signal indicates the initial
// address of a read burst transaction.
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
// Burst length. The burst length gives the exact number of transfers in a burst
input wire [7 : 0] S_AXI_ARLEN,
// Burst size. This signal indicates the size of each transfer in the burst
input wire [2 : 0] S_AXI_ARSIZE,
// Burst type. The burst type and the size information,
// determine how the address for each transfer within the burst is calculated.
input wire [1 : 0] S_AXI_ARBURST,
// Lock type. Provides additional information about the
// atomic characteristics of the transfer.
input wire S_AXI_ARLOCK,
// Memory type. This signal indicates how transactions
// are required to progress through a system.
input wire [3 : 0] S_AXI_ARCACHE,
// Protection type. This signal indicates the privilege
// and security level of the transaction, and whether
// the transaction is a data access or an instruction access.
input wire [2 : 0] S_AXI_ARPROT,
// Quality of Service, QoS identifier sent for each
// read transaction.
input wire [3 : 0] S_AXI_ARQOS,
// Region identifier. Permits a single physical interface
// on a slave to be used for multiple logical interfaces.
// input wire [3 : 0] S_AXI_ARREGION,
// Optional User-defined signal in the read address channel.
// input wire [C_S_AXI_ARUSER_WIDTH-1 : 0] S_AXI_ARUSER,
// Write address valid. This signal indicates that
// the channel is signaling valid read address and
// control information.
input wire S_AXI_ARVALID,
// Read address ready. This signal indicates that
// the slave is ready to accept an address and associated
// control signals.
output wire S_AXI_ARREADY,
// Read ID tag. This signal is the identification tag
// for the read data group of signals generated by the slave.
output wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_RID,
// Read Data
output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
// Read response. This signal indicates the status of
// the read transfer.
output wire [1 : 0] S_AXI_RRESP,
// Read last. This signal indicates the last transfer
// in a read burst.
output wire S_AXI_RLAST,
// Optional User-defined signal in the read address channel.
// output wire [C_S_AXI_RUSER_WIDTH-1 : 0] S_AXI_RUSER,
// Read valid. This signal indicates that the channel
// is signaling the required read data.
output wire S_AXI_RVALID,
// Read ready. This signal indicates that the master can
// accept the read data and response information.
input wire S_AXI_RREADY
);
// AXI4FULL signals
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
reg axi_awready;
reg axi_wready;
reg [1 : 0] axi_bresp;
// reg [C_S_AXI_BUSER_WIDTH-1 : 0] axi_buser;
reg axi_bvalid;
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
reg axi_arready;
reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;
reg [1 : 0] axi_rresp;
reg axi_rlast;
// reg [C_S_AXI_RUSER_WIDTH-1 : 0] axi_ruser;
reg axi_rvalid;
// aw_wrap_en determines wrap boundary and enables wrapping
wire aw_wrap_en;
// ar_wrap_en determines wrap boundary and enables wrapping
wire ar_wrap_en;
// aw_wrap_size is the size of the write transfer, the
// write address wraps to a lower address if upper address
// limit is reached
wire [31:0] aw_wrap_size ;
// ar_wrap_size is the size of the read transfer, the
// read address wraps to a lower address if upper address
// limit is reached
wire [31:0] ar_wrap_size ;
// The axi_awv_awr_flag flag marks the presence of write address valid
reg axi_awv_awr_flag;
//The axi_arv_arr_flag flag marks the presence of read address valid
reg axi_arv_arr_flag;
// The axi_awlen_cntr internal write address counter to keep track of beats in a burst transaction
reg [7:0] axi_awlen_cntr;
//The axi_arlen_cntr internal read address counter to keep track of beats in a burst transaction
reg [7:0] axi_arlen_cntr;
reg [1:0] axi_arburst;
reg [1:0] axi_awburst;
reg [7:0] axi_arlen;
reg [7:0] axi_awlen;
//local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
//ADDR_LSB is used for addressing 32/64 bit registers/memories
//ADDR_LSB = 2 for 32 bits (n downto 2)
//ADDR_LSB = 3 for 42 bits (n downto 3)
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32)+ 1;
localparam integer OPT_MEM_ADDR_BITS = 3;
localparam integer USER_NUM_MEM = 1;
//----------------------------------------------
//-- Signals for user logic memory space example
//------------------------------------------------
wire [OPT_MEM_ADDR_BITS:0] mem_address;
// wire [USER_NUM_MEM-1:0] mem_select;
reg [C_S_AXI_DATA_WIDTH-1:0] mem_data_out[0 : USER_NUM_MEM-1];
genvar i;
genvar j;
genvar mem_byte_index;
// I/O Connections assignments
assign S_AXI_AWREADY = axi_awready;
assign S_AXI_WREADY = axi_wready;
assign S_AXI_BRESP = axi_bresp;
// assign S_AXI_BUSER = axi_buser;
assign S_AXI_BVALID = axi_bvalid;
assign S_AXI_ARREADY = axi_arready;
assign S_AXI_RDATA = axi_rdata;
assign S_AXI_RRESP = axi_rresp;
assign S_AXI_RLAST = axi_rlast;
// assign S_AXI_RUSER = axi_ruser;
assign S_AXI_RVALID = axi_rvalid;
assign S_AXI_BID = S_AXI_AWID;
assign S_AXI_RID = S_AXI_ARID;
assign aw_wrap_size = (C_S_AXI_DATA_WIDTH/8 * (axi_awlen));
assign ar_wrap_size = (C_S_AXI_DATA_WIDTH/8 * (axi_arlen));
assign aw_wrap_en = ((axi_awaddr & aw_wrap_size) == aw_wrap_size)? 1'b1: 1'b0;
assign ar_wrap_en = ((axi_araddr & ar_wrap_size) == ar_wrap_size)? 1'b1: 1'b0;
// Implement axi_awready generation
// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
// de-asserted when reset is low.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awready <= 1'b0;
axi_awv_awr_flag <= 1'b0;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && ~axi_awv_awr_flag && ~axi_arv_arr_flag)
begin
// slave is ready to accept an address and
// associated control signals
axi_awready <= 1'b1;
axi_awv_awr_flag <= 1'b1;
// used for generation of bresp() and bvalid
end
else if (S_AXI_WLAST && axi_wready)
// preparing to accept next address after current write burst tx completion
begin
axi_awv_awr_flag <= 1'b0;
end
else
begin
axi_awready <= 1'b0;
end
end
end
// Implement axi_awaddr latching
// This process is used to latch the address when both
// S_AXI_AWVALID and S_AXI_WVALID are valid.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awaddr <= 0;
axi_awlen_cntr <= 0;
axi_awburst <= 0;
axi_awlen <= 0;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && ~axi_awv_awr_flag)
begin
// address latching
axi_awaddr <= S_AXI_AWADDR[C_S_AXI_ADDR_WIDTH - 1:0];
axi_awburst <= S_AXI_AWBURST;
axi_awlen <= S_AXI_AWLEN;
// start address of transfer
axi_awlen_cntr <= 0;
end
else if((axi_awlen_cntr <= axi_awlen) && axi_wready && S_AXI_WVALID)
begin
axi_awlen_cntr <= axi_awlen_cntr + 1;
case (axi_awburst)
2'b00: // fixed burst
// The write address for all the beats in the transaction are fixed
begin
axi_awaddr <= axi_awaddr;
//for awsize = 4 bytes (010)
end
2'b01: //incremental burst
// The write address for all the beats in the transaction are increments by awsize
begin
axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
//awaddr aligned to 4 byte boundary
axi_awaddr[ADDR_LSB-1:0] <= {ADDR_LSB{1'b0}};
//for awsize = 4 bytes (010)
end
2'b10: //Wrapping burst
// The write address wraps when the address reaches wrap boundary
if (aw_wrap_en)
begin
axi_awaddr <= (axi_awaddr - aw_wrap_size);
end
else
begin
axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
axi_awaddr[ADDR_LSB-1:0] <= {ADDR_LSB{1'b0}};
end
default: //reserved (incremental burst for example)
begin
axi_awaddr <= axi_awaddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
//for awsize = 4 bytes (010)
end
endcase
end
end
end
// Implement axi_wready generation
// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
// de-asserted when reset is low.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_wready <= 1'b0;
end
else
begin
if (~axi_wready && S_AXI_WVALID && axi_awv_awr_flag)
begin
// slave can accept the write data
axi_wready <= 1'b1;
end
//else if (~axi_awv_awr_flag)
else if (S_AXI_WLAST && axi_wready)
begin
axi_wready <= 1'b0;
end
end
end
// Implement write response logic generation
// The write response and response valid signals are asserted by the slave
// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
// This marks the acceptance of address and indicates the status of
// write transaction.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_bvalid <= 0;
axi_bresp <= 2'b0;
// axi_buser <= 0;
end
else
begin
if (axi_awv_awr_flag && axi_wready && S_AXI_WVALID && ~axi_bvalid && S_AXI_WLAST )
begin
axi_bvalid <= 1'b1;
axi_bresp <= 2'b0;
// 'OKAY' response
end
else
begin
if (S_AXI_BREADY && axi_bvalid)
//check if bready is asserted while bvalid is high)
//(there is a possibility that bready is always asserted high)
begin
axi_bvalid <= 1'b0;
end
end
end
end
// Implement axi_arready generation
// axi_arready is asserted for one S_AXI_ACLK clock cycle when
// S_AXI_ARVALID is asserted. axi_awready is
// de-asserted when reset (active low) is asserted.
// The read address is also latched when S_AXI_ARVALID is
// asserted. axi_araddr is reset to zero on reset assertion.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_arready <= 1'b0;
axi_arv_arr_flag <= 1'b0;
end
else
begin
if (~axi_arready && S_AXI_ARVALID && ~axi_awv_awr_flag && ~axi_arv_arr_flag)
begin
axi_arready <= 1'b1;
axi_arv_arr_flag <= 1'b1;
end
else if (axi_rvalid && S_AXI_RREADY && axi_arlen_cntr == axi_arlen)
// preparing to accept next address after current read completion
begin
axi_arv_arr_flag <= 1'b0;
end
else
begin
axi_arready <= 1'b0;
end
end
end
// Implement axi_araddr latching
//This process is used to latch the address when both
//S_AXI_ARVALID and S_AXI_RVALID are valid.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_araddr <= 0;
axi_arlen_cntr <= 0;
axi_arburst <= 0;
axi_arlen <= 0;
axi_rlast <= 1'b0;
// axi_ruser <= 0;
end
else
begin
if (~axi_arready && S_AXI_ARVALID && ~axi_arv_arr_flag)
begin
// address latching
axi_araddr <= S_AXI_ARADDR[C_S_AXI_ADDR_WIDTH - 1:0];
axi_arburst <= S_AXI_ARBURST;
axi_arlen <= S_AXI_ARLEN;
// start address of transfer
axi_arlen_cntr <= 0;
axi_rlast <= 1'b0;
end
else if((axi_arlen_cntr <= axi_arlen) && axi_rvalid && S_AXI_RREADY)
begin
axi_arlen_cntr <= axi_arlen_cntr + 1;
axi_rlast <= 1'b0;
case (axi_arburst)
2'b00: // fixed burst
// The read address for all the beats in the transaction are fixed
begin
axi_araddr <= axi_araddr;
//for arsize = 4 bytes (010)
end
2'b01: //incremental burst
// The read address for all the beats in the transaction are increments by awsize
begin
axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
//araddr aligned to 4 byte boundary
axi_araddr[ADDR_LSB-1:0] <= {ADDR_LSB{1'b0}};
//for awsize = 4 bytes (010)
end
2'b10: //Wrapping burst
// The read address wraps when the address reaches wrap boundary
if (ar_wrap_en)
begin
axi_araddr <= (axi_araddr - ar_wrap_size);
end
else
begin
axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
//araddr aligned to 4 byte boundary
axi_araddr[ADDR_LSB-1:0] <= {ADDR_LSB{1'b0}};
end
default: //reserved (incremental burst for example)
begin
axi_araddr <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB]+1;
//for arsize = 4 bytes (010)
end
endcase
end
else if((axi_arlen_cntr == axi_arlen) && ~axi_rlast && axi_arv_arr_flag )
begin
axi_rlast <= 1'b1;
end
else if (S_AXI_RREADY)
begin
axi_rlast <= 1'b0;
end
end
end
// Implement axi_arvalid generation
// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_ARVALID and axi_arready are asserted. The slave registers
// data are available on the axi_rdata bus at this instance. The
// assertion of axi_rvalid marks the validity of read data on the
// bus and axi_rresp indicates the status of read transaction.axi_rvalid
// is deasserted on reset (active low). axi_rresp and axi_rdata are
// cleared to zero on reset (active low).
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rvalid <= 0;
axi_rresp <= 0;
end
else
begin
if (axi_arv_arr_flag && ~axi_rvalid)
begin
axi_rvalid <= 1'b1;
axi_rresp <= 2'b0;
// 'OKAY' response
end
else if (axi_rvalid && S_AXI_RREADY)
begin
axi_rvalid <= 1'b0;
end
end
end
// ------------------------------------------
// -- Example code to access user logic memory region
// ------------------------------------------
generate
if (USER_NUM_MEM >= 1)
begin
// assign mem_select = 1;
assign mem_address = (axi_arv_arr_flag? axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]:(axi_awv_awr_flag? axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]:0));
end
endgenerate
// implement Block RAM(s)
generate
for(i=0; i<= USER_NUM_MEM-1; i=i+1)
begin:BRAM_GEN
wire mem_rden;
wire mem_wren;
assign mem_wren = axi_wready && S_AXI_WVALID ;
assign mem_rden = axi_arv_arr_flag ; //& ~axi_rvalid
for(mem_byte_index=0; mem_byte_index<= (C_S_AXI_DATA_WIDTH/8-1); mem_byte_index=mem_byte_index+1)
begin:BYTE_BRAM_GEN
wire [8-1:0] data_in ;
wire [8-1:0] data_out;
reg [8-1:0] byte_ram [0 : 15];
// integer j;
//assigning 8 bit data
assign data_in = S_AXI_WDATA[(mem_byte_index*8+7) -: 8];
assign data_out = byte_ram[mem_address];
always @( posedge S_AXI_ACLK )
begin
if (mem_wren && S_AXI_WSTRB[mem_byte_index])
begin
byte_ram[mem_address] <= data_in;
end
end
always @( posedge S_AXI_ACLK )
begin
if (mem_rden)
begin
mem_data_out[i][(mem_byte_index*8+7) -: 8] <= data_out;
end
end
end
end
endgenerate
//Output register or memory read data
always @(*) // @( mem_data_out, axi_rvalid)
begin
if (axi_rvalid)
begin
// Read address mux
axi_rdata = mem_data_out[0];
end
else
begin
axi_rdata = 32'h00000000;
end
end
// Verification logic starts here:
initial axi_awready = 1'b0;
initial axi_awv_awr_flag = 1'b0;
initial axi_awaddr = 0;
initial axi_awlen_cntr = 0;
initial axi_awburst = 0;
initial axi_awlen = 0;
initial axi_wready = 1'b0;
initial axi_bvalid = 1'b0;
initial axi_bresp = 1'b0;
// initial axi_buser = 1'b0;
initial axi_arready = 1'b0;
initial axi_arv_arr_flag = 1'b0;
initial axi_araddr = 0;
initial axi_arlen_cntr = 0;
initial axi_arburst = 0;
initial axi_arlen = 0;
initial axi_rlast = 0;
// initial axi_ruser = 0;
initial axi_rvalid = 1'b0;
initial axi_rresp = 1'b0;
`ifdef FORMAL
//
// ...
//
faxi_slave #(
.F_AXI_MAXSTALL(6),
.C_AXI_ID_WIDTH(C_S_AXI_ID_WIDTH),
.C_AXI_DATA_WIDTH(C_S_AXI_DATA_WIDTH),
.C_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH),
.OPT_NARROW_BURST(0),
.OPT_EXCLUSIVE(0),
.F_LGDEPTH(F_LGDEPTH))
f_slave(
// {{{
.i_clk(S_AXI_ACLK),
.i_axi_reset_n(S_AXI_ARESETN),
//
// Address write channel
//
// Write Address ID
.i_axi_awid(S_AXI_AWID),
// Write address
.i_axi_awaddr(S_AXI_AWADDR),
// Burst length. The burst length gives the exact number of transfers in a burst
.i_axi_awlen(S_AXI_AWLEN),
// Burst size. This signal indicates the size of each transfer in the burst
.i_axi_awsize(S_AXI_AWSIZE),
// Burst type. The burst type and the size information,
// determine how the address for each transfer within the burst is calculated.
.i_axi_awburst(S_AXI_AWBURST),
// Lock type. Provides additional information about the
// atomic characteristics of the transfer.
.i_axi_awlock(S_AXI_AWLOCK),
// Memory type. This signal indicates how transactions
// are required to progress through a system.
.i_axi_awcache(S_AXI_AWCACHE),
// Protection type. This signal indicates the privilege
// and security level of the transaction, and whether
// the transaction is a data access or an instruction access.
.i_axi_awprot(S_AXI_AWPROT),
// Quality of Service, QoS identifier sent for each
// write transaction.
.i_axi_awqos(S_AXI_AWQOS),
// Write address valid. This signal indicates that
// the channel is signaling valid write address and
// control information.
.i_axi_awvalid(S_AXI_AWVALID),
// Write address ready. This signal indicates that
// the slave is ready to accept an address and associated
// control signals.
.i_axi_awready(S_AXI_AWREADY),
//
//
//
// Write Data Channel
//
// Write Data
.i_axi_wdata(S_AXI_WDATA),
// Write strobes. This signal indicates which byte
// lanes hold valid data. There is one write strobe
// bit for each eight bits of the write data bus.
.i_axi_wstrb(S_AXI_WSTRB),
// Write last. This signal indicates the last transfer
// in a write burst.
.i_axi_wlast(S_AXI_WLAST),
// Write valid. This signal indicates that valid write
// data and strobes are available.
.i_axi_wvalid(S_AXI_WVALID),
// Write ready. This signal indicates that the slave
// can accept the write data.
.i_axi_wready(S_AXI_WREADY),
//
//
// Response ID tag. This signal is the ID tag of the
// write response.
.i_axi_bid(S_AXI_BID),
// Write response. This signal indicates the status
// of the write transaction.
.i_axi_bresp(S_AXI_BRESP),
// Write response valid. This signal indicates that the
// channel is signaling a valid write response.
.i_axi_bvalid(S_AXI_BVALID),
// Response ready. This signal indicates that the master
// can accept a write response.
.i_axi_bready(S_AXI_BREADY),
//
//
//
// Read address channel
//
// Read address ID. This signal is the identification
// tag for the read address group of signals.
.i_axi_arid(S_AXI_ARID),
// Read address. This signal indicates the initial
// address of a read burst transaction.
.i_axi_araddr(S_AXI_ARADDR),
// Burst length. The burst length gives the exact number of transfers in a burst
.i_axi_arlen(S_AXI_ARLEN),
// Burst size. This signal indicates the size of each transfer in the burst
.i_axi_arsize(S_AXI_ARSIZE),
// Burst type. The burst type and the size information,
// determine how the address for each transfer within the burst is calculated.
.i_axi_arburst(S_AXI_ARBURST),
// Lock type. Provides additional information about the
// atomic characteristics of the transfer.
.i_axi_arlock(S_AXI_ARLOCK),
// Memory type. This signal indicates how transactions
// are required to progress through a system.
.i_axi_arcache(S_AXI_ARCACHE),
// Protection type. This signal indicates the privilege
// and security level of the transaction, and whether
// the transaction is a data access or an instruction access.
.i_axi_arprot(S_AXI_ARPROT),
// Quality of Service, QoS identifier sent for each
// read transaction.
.i_axi_arqos(S_AXI_ARQOS),
// Write address valid. This signal indicates that
// the channel is signaling valid read address and
// control information.
.i_axi_arvalid(S_AXI_ARVALID),
// Read address ready. This signal indicates that
// the slave is ready to accept an address and associated
// control signals.
.i_axi_arready(S_AXI_ARREADY),
//
//
//
// Read data return channel
//
// Read ID tag. This signal is the identification tag
// for the read data group of signals generated by the slave.
.i_axi_rid(S_AXI_RID),
// Read Data
.i_axi_rdata(S_AXI_RDATA),
// Read response. This signal indicates the status of
// the read transfer.
.i_axi_rresp(S_AXI_RRESP),
// Read last. This signal indicates the last transfer
// in a read burst.
.i_axi_rlast(S_AXI_RLAST),
// Read valid. This signal indicates that the channel
// is signaling the required read data.
.i_axi_rvalid(S_AXI_RVALID),
// Read ready. This signal indicates that the master can
// accept the read data and response information.
.i_axi_rready(S_AXI_RREADY)
//
// ...
//
// }}}
);
//
// ...
//
////////////////////////////////////////////////////////////////////////
//
// Write induction properties
//
////////////////////////////////////////////////////////////////////////
//
//
//
// ...
//
////////////////////////////////////////////////////////////////////////
//
// Read induction properties
//
////////////////////////////////////////////////////////////////////////
//
//
//
// ...
//
////////////////////////////////////////////////////////////////////////
//
// Cover properties
//
////////////////////////////////////////////////////////////////////////
//
//
//
// ...
//
////////////////////////////////////////////////////////////////////////
//
// Assumptions necessary to pass a formal check
//
////////////////////////////////////////////////////////////////////////
//
//
// BUG #1: The ID inputs, both ARID and AWID, are not registered.
// As a result, if the master changes these values mid burst,
// the slave will return the wrong ID values
//
// ...
//
//
// BUG #2: This core using the S_AXI_WLAST signal, without first
// checking that S_AXI_WVALID is also true. Hence, if there's any
// time between WVALIDs, the core might act on the last one
// without receiving the data
//
// ...
//
//
// BUG #3: Like Xilinx's AXI-lite core, this core can't handle back
// pressure. Should S_AXI_BREADY not be accepted before the next
// S_AXI_AWVALID & S_AXI_AWREADY, a burst would be dropped
//
//
// ...
//
//
// BAD PRACTICE: This particular core can't handle both reads and
// writes at the same time. To avoid failing a stall timeout,
// we'll insist that no new transactions start while a
// transaction on the other side is in process
//
// Comments:
//
// - ID's are broken. The ID should be registered and recorded within the
// core, allowing the interconnect to change them after the transaction
// has been accepted
//
// - This core does not support narrow burst mode, but rather only
// supports an AxSIZE of 2'b10 (32'bit bus). It cannot handle busses
// of other sizes, or transactions from smaller sources.
//
// This might be considered a "feature"
//
// - This core can only handle read or write transactions, but never both
// at the same time
//
// This might also be considered a "feature"
//
// - The wrap logic depends upon a multiply
//
// A good synthesis tool might simplify this
//
// - Read transactions take place at one word every other clock at best
//
// This is just plain crippled.
//
// - Any back pressure could easily cause the core to lose a transaction,
// as the newer transaction's response will overwrite the waiting
// response from the previous transaction
//
`endif
// User logic ends
endmodule