Line 11... |
Line 11... |
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2017, Gisselquist Technology, LLC
|
// Copyright (C) 2017, Gisselquist Technology, LLC
|
//
|
//
|
// This program is free software (firmware): you can redistribute it and/or
|
// This file is part of the pipelined Wishbone to AXI converter project, a
|
// modify it under the terms of the GNU General Public License as published
|
// project that contains multiple bus bridging designs and formal bus property
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// sets.
|
// your option) any later version.
|
//
|
//
|
// The bus bridge designs and property sets are free RTL designs: you can
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// redistribute them and/or modify any of them under the terms of the GNU
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// Lesser General Public License as published by the Free Software Foundation,
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// either version 3 of the License, or (at your option) any later version.
|
// for more details.
|
//
|
//
|
// The bus bridge designs and property sets are distributed in the hope that
|
// You should have received a copy of the GNU General Public License along
|
// they will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
// with this program. (It's in the $(ROOT)/doc directory, run make with no
|
// warranty of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// target there if the PDF file isn't present.) If not, see
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with these designs. (It's in the $(ROOT)/doc directory. Run make
|
|
// with no target there if the PDF file isn't present.) If not, see
|
// <http://www.gnu.org/licenses/> for a copy.
|
// <http://www.gnu.org/licenses/> for a copy.
|
//
|
//
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// License: LGPL, v3, as defined and found on www.gnu.org,
|
// http://www.gnu.org/licenses/gpl.html
|
// http://www.gnu.org/licenses/lgpl.html
|
//
|
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
`default_nettype none
|
`default_nettype none
|
Line 42... |
Line 45... |
// This is an int between 1-16
|
// This is an int between 1-16
|
parameter C_AXI_DATA_WIDTH = 128,// Width of the AXI R&W data
|
parameter C_AXI_DATA_WIDTH = 128,// Width of the AXI R&W data
|
parameter C_AXI_ADDR_WIDTH = 28, // AXI Address width (log wordsize)
|
parameter C_AXI_ADDR_WIDTH = 28, // AXI Address width (log wordsize)
|
localparam DW = C_AXI_DATA_WIDTH,
|
localparam DW = C_AXI_DATA_WIDTH,
|
localparam AW = C_AXI_ADDR_WIDTH,
|
localparam AW = C_AXI_ADDR_WIDTH,
|
parameter [(C_AXI_ID_WIDTH-1):0] F_AXI_MAXSTALL = 3,
|
|
parameter [(C_AXI_ID_WIDTH-1):0] F_AXI_MAXDELAY = 3,
|
|
parameter [0:0] F_STRICT_ORDER = 0, // Reorder, or not? 0 -> Reorder
|
parameter [0:0] F_STRICT_ORDER = 0, // Reorder, or not? 0 -> Reorder
|
parameter [0:0] F_CONSECUTIVE_IDS= 0, // 0=ID's must be consecutive
|
parameter [0:0] F_CONSECUTIVE_IDS= 0, // 0=ID's must be consecutive
|
parameter [0:0] F_OPT_BURSTS = 1'b1, // Check burst lengths
|
parameter [0:0] F_OPT_BURSTS = 1'b1, // Check burst lengths
|
parameter [0:0] F_CHECK_IDS = 1'b1 // Check ID's upon issue&return
|
parameter [0:0] F_CHECK_IDS = 1'b1, // Check ID's upon issue&return
|
|
parameter [7:0] F_AXI_MAXBURST = 8'hff,// Maximum burst length, minus 1
|
|
parameter [0:0] F_OPT_CLK2FFLOGIC= 1'b0, // Multiple clock testing?
|
|
parameter [(C_AXI_ID_WIDTH-1):0] F_AXI_MAXSTALL = 3,
|
|
parameter [(C_AXI_ID_WIDTH-1):0] F_AXI_MAXDELAY = 3
|
) (
|
) (
|
input i_clk, // System clock
|
input wire i_clk, // System clock
|
input i_axi_reset_n,
|
input wire i_axi_reset_n,
|
|
|
// AXI write address channel signals
|
// AXI write address channel signals
|
input i_axi_awready, // Slave is ready to accept
|
input wire i_axi_awready,//Slave is ready to accept
|
input wire [C_AXI_ID_WIDTH-1:0] i_axi_awid, // Write ID
|
input wire [C_AXI_ID_WIDTH-1:0] i_axi_awid, // Write ID
|
input wire [AW-1:0] i_axi_awaddr, // Write address
|
input wire [AW-1:0] i_axi_awaddr, // Write address
|
input wire [7:0] i_axi_awlen, // Write Burst Length
|
input wire [7:0] i_axi_awlen, // Write Burst Length
|
input wire [2:0] i_axi_awsize, // Write Burst size
|
input wire [2:0] i_axi_awsize, // Write Burst size
|
input wire [1:0] i_axi_awburst, // Write Burst type
|
input wire [1:0] i_axi_awburst, // Write Burst type
|
Line 104... |
Line 109... |
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_rd_outstanding,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_rd_outstanding,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_wr_outstanding,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_wr_outstanding,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_awr_outstanding,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_awr_outstanding,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_rd_id_outstanding,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_rd_id_outstanding,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_awr_id_outstanding,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_awr_id_outstanding,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_wr_id_outstanding
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_wr_id_outstanding,
|
|
// output reg [(9-1):0] f_axi_wr_pending,
|
|
// output reg [(9-1):0] f_axi_rd_count,
|
|
output reg [(9-1):0] f_axi_wr_count
|
);
|
);
|
reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_wr_id_complete;
|
reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_wr_id_complete;
|
|
|
//*****************************************************************************
|
//*****************************************************************************
|
// Parameter declarations
|
// Parameter declarations
|
Line 128... |
Line 135... |
: ((DW == 64) ? 6
|
: ((DW == 64) ? 6
|
: ((DW == 128) ? 7
|
: ((DW == 128) ? 7
|
: 8))));
|
: 8))));
|
localparam LGFIFOLN = C_AXI_ID_WIDTH;
|
localparam LGFIFOLN = C_AXI_ID_WIDTH;
|
localparam FIFOLN = (1<<LGFIFOLN);
|
localparam FIFOLN = (1<<LGFIFOLN);
|
|
localparam F_LGDEPTH = C_AXI_ID_WIDTH;
|
|
localparam F_AXI_MAXWAIT = F_AXI_MAXSTALL;
|
|
|
|
|
//*****************************************************************************
|
//*****************************************************************************
|
// Internal register and wire declarations
|
// Internal register and wire declarations
|
//*****************************************************************************
|
//*****************************************************************************
|
|
|
// Things we're not changing ...
|
|
always @(*)
|
|
begin
|
|
assert(i_axi_awlen == 8'h0); // Burst length is one
|
|
assert(i_axi_awsize == 3'b101); // maximum bytes per burst is 32
|
|
assert(i_axi_awburst == 2'b01); // Incrementing address (ignored)
|
|
assert(i_axi_arburst == 2'b01); // Incrementing address (ignored)
|
|
assert(i_axi_awlock == 1'b0); // Normal signaling
|
|
assert(i_axi_arlock == 1'b0); // Normal signaling
|
|
assert(i_axi_awcache == 4'h2); // Normal: no cache, no buffer
|
|
assert(i_axi_arcache == 4'h2); // Normal: no cache, no buffer
|
|
assert(i_axi_awprot == 3'b010);// Unpriviledged, unsecure, data access
|
|
assert(i_axi_arprot == 3'b010);// Unpriviledged, unsecure, data access
|
|
assert(i_axi_awqos == 4'h0); // Lowest quality of service (unused)
|
|
assert(i_axi_arqos == 4'h0); // Lowest quality of service (unused)
|
|
end
|
|
|
|
// wire w_fifo_full;
|
// wire w_fifo_full;
|
wire axi_rd_ack, axi_wr_ack, axi_ard_req, axi_awr_req, axi_wr_req,
|
wire axi_rd_ack, axi_wr_ack, axi_ard_req, axi_awr_req, axi_wr_req,
|
axi_rd_err, axi_wr_err;
|
axi_rd_err, axi_wr_err;
|
//
|
//
|
Line 164... |
Line 157... |
assign axi_rd_ack = (i_axi_rvalid)&&(i_axi_rready);
|
assign axi_rd_ack = (i_axi_rvalid)&&(i_axi_rready);
|
assign axi_wr_ack = (i_axi_bvalid)&&(i_axi_bready);
|
assign axi_wr_ack = (i_axi_bvalid)&&(i_axi_bready);
|
assign axi_rd_err = (axi_rd_ack)&&(i_axi_rresp[1]);
|
assign axi_rd_err = (axi_rd_ack)&&(i_axi_rresp[1]);
|
assign axi_wr_err = (axi_wr_ack)&&(i_axi_bresp[1]);
|
assign axi_wr_err = (axi_wr_ack)&&(i_axi_bresp[1]);
|
|
|
|
`define SLAVE_ASSUME assert
|
|
`define SLAVE_ASSERT assume
|
|
|
//
|
//
|
// Setup
|
// Setup
|
//
|
//
|
reg f_past_valid;
|
reg f_past_valid;
|
integer k;
|
integer k;
|
Line 180... |
Line 176... |
assert(!i_axi_reset_n);
|
assert(!i_axi_reset_n);
|
|
|
//
|
//
|
// All signals must be synchronous with the clock
|
// All signals must be synchronous with the clock
|
//
|
//
|
|
generate if (F_OPT_CLK2FFLOGIC)
|
|
begin
|
|
|
always @($global_clock)
|
always @($global_clock)
|
if (f_past_valid) begin
|
if (f_past_valid) begin
|
// Assume our inputs will only change on the positive edge
|
// Assume our inputs will only change on the positive
|
// of the clock
|
// edge of the clock
|
if (!$rose(i_clk))
|
if (!$rose(i_clk))
|
begin
|
begin
|
// AXI inputs
|
// AXI inputs
|
assume($stable(i_axi_awready));
|
assume($stable(i_axi_awready));
|
assume($stable(i_axi_wready));
|
assume($stable(i_axi_wready));
|
Line 237... |
Line 236... |
assert($stable(f_axi_rd_outstanding));
|
assert($stable(f_axi_rd_outstanding));
|
assert($stable(f_axi_wr_outstanding));
|
assert($stable(f_axi_wr_outstanding));
|
assert($stable(f_axi_awr_outstanding));
|
assert($stable(f_axi_awr_outstanding));
|
end
|
end
|
end
|
end
|
|
end endgenerate
|
|
|
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Reset properties
|
// Reset properties
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// If asserted, the reset must be asserted for a minimum of 16 clocks
|
|
reg [3:0] f_reset_length;
|
|
initial f_reset_length = 0;
|
|
always @(posedge i_clk)
|
|
if (i_axi_reset_n)
|
|
f_reset_length <= 0;
|
|
else if (!(&f_reset_length))
|
|
f_reset_length <= f_reset_length + 1'b1;
|
|
|
|
always @(posedge i_clk)
|
|
if ((f_past_valid)&&(!$past(i_axi_reset_n))&&(!$past(&f_reset_length)))
|
|
`SLAVE_ASSUME(!i_axi_reset_n);
|
|
|
|
always @(*)
|
|
if ((f_reset_length > 0)&&(f_reset_length < 4'hf))
|
|
`SLAVE_ASSUME(!i_axi_reset_n);
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((f_past_valid)&&(!$past(i_axi_reset_n)))
|
if ((!f_past_valid)||(!$past(i_axi_reset_n)))
|
begin
|
begin
|
assert(!i_axi_arvalid);
|
`SLAVE_ASSUME(!i_axi_arvalid);
|
assert(!i_axi_awvalid);
|
`SLAVE_ASSUME(!i_axi_awvalid);
|
assert(!i_axi_wvalid);
|
`SLAVE_ASSUME(!i_axi_wvalid);
|
assume(!i_axi_bvalid);
|
//
|
assume(!i_axi_rvalid);
|
`SLAVE_ASSERT(!i_axi_bvalid);
|
|
`SLAVE_ASSERT(!i_axi_rvalid);
|
end
|
end
|
|
|
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Stability assumptions, AXI inputs/responses
|
// Stability properties--what happens if valid and not ready
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
|
|
// Assume any response from the bus will not change prior to that
|
// Assume any response from the bus will not change prior to that
|
// response being accepted
|
// response being accepted
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (f_past_valid)
|
if ((f_past_valid)&&($past(i_axi_reset_n)))
|
begin
|
begin
|
if ((f_past_valid)&&($past(i_axi_rvalid))&&(!$past(i_axi_rready)))
|
// Write address channel
|
|
if ((f_past_valid)&&($past(i_axi_awvalid))&&(!$past(i_axi_awready)))
|
begin
|
begin
|
assume(i_axi_rid == $past(i_axi_rid));
|
`SLAVE_ASSUME(i_axi_awvalid);
|
assume(i_axi_rresp == $past(i_axi_rresp));
|
`SLAVE_ASSUME(i_axi_awaddr == $past(i_axi_awaddr));
|
assume(i_axi_rdata == $past(i_axi_rdata));
|
`SLAVE_ASSUME($stable(i_axi_awid));
|
assume(i_axi_rlast == $past(i_axi_rlast));
|
`SLAVE_ASSUME($stable(i_axi_awlen));
|
|
`SLAVE_ASSUME($stable(i_axi_awsize));
|
|
`SLAVE_ASSUME($stable(i_axi_awburst));
|
|
`SLAVE_ASSUME($stable(i_axi_awlock));
|
|
`SLAVE_ASSUME($stable(i_axi_awcache));
|
|
`SLAVE_ASSUME($stable(i_axi_awprot));
|
|
`SLAVE_ASSUME($stable(i_axi_awqos));
|
end
|
end
|
|
|
if ((f_past_valid)&&($past(i_axi_bvalid))&&(!$past(i_axi_bready)))
|
// Write data channel
|
|
if ((f_past_valid)&&($past(i_axi_wvalid))&&(!$past(i_axi_wready)))
|
begin
|
begin
|
assume(i_axi_bid == $past(i_axi_bid));
|
`SLAVE_ASSUME(i_axi_wvalid);
|
assume(i_axi_bresp == $past(i_axi_bresp));
|
`SLAVE_ASSUME(i_axi_wstrb == $past(i_axi_wstrb));
|
|
`SLAVE_ASSUME(i_axi_wdata == $past(i_axi_wdata));
|
|
`SLAVE_ASSUME(i_axi_wlast);
|
end
|
end
|
end
|
|
|
|
// Nothing should be returning a result on the first clock
|
|
initial assume(!i_axi_bvalid);
|
|
initial assume(!i_axi_rvalid);
|
|
//
|
|
initial assert(!i_axi_arvalid);
|
|
initial assert(!i_axi_awvalid);
|
|
initial assert(!i_axi_wvalid);
|
|
|
|
//////////////////////////////////////////////
|
// Incoming Read address channel
|
//
|
|
//
|
|
// Stability assumptions, AXI outputs/requests
|
|
//
|
|
//
|
|
//////////////////////////////////////////////
|
|
|
|
// Read address chanel
|
|
always @(posedge i_clk)
|
|
if ((f_past_valid)&&($past(i_axi_arvalid))&&(!$past(i_axi_arready)))
|
if ((f_past_valid)&&($past(i_axi_arvalid))&&(!$past(i_axi_arready)))
|
begin
|
begin
|
assert(i_axi_arvalid);
|
`SLAVE_ASSUME(i_axi_arvalid);
|
assert($stable(i_axi_arid));
|
`SLAVE_ASSUME(i_axi_arid == $past(i_axi_arid));
|
assert($stable(i_axi_araddr));
|
`SLAVE_ASSUME(i_axi_araddr == $past(i_axi_araddr));
|
assert($stable(i_axi_arlen));
|
`SLAVE_ASSUME(i_axi_arlen == $past(i_axi_arlen));
|
assert($stable(i_axi_arsize));
|
`SLAVE_ASSUME(i_axi_arsize == $past(i_axi_arsize));
|
assert($stable(i_axi_arburst));
|
`SLAVE_ASSUME(i_axi_arburst == $past(i_axi_arburst));
|
assert($stable(i_axi_arlock));
|
`SLAVE_ASSUME(i_axi_arlock == $past(i_axi_arlock));
|
assert($stable(i_axi_arcache));
|
`SLAVE_ASSUME(i_axi_arcache == $past(i_axi_arcache));
|
assert($stable(i_axi_arprot));
|
`SLAVE_ASSUME(i_axi_arprot == $past(i_axi_arprot));
|
assert($stable(i_axi_arqos));
|
`SLAVE_ASSUME(i_axi_arqos == $past(i_axi_arqos));
|
assert($stable(i_axi_arvalid));
|
|
end
|
end
|
|
|
// If valid, but not ready, on any channel is true, nothing changes
|
// Assume any response from the bus will not change prior to that
|
// until valid && ready
|
// response being accepted
|
always @(posedge i_clk)
|
if ((f_past_valid)&&($past(i_axi_rvalid))&&(!$past(i_axi_rready)))
|
if ((f_past_valid)&&($past(i_axi_awvalid))&&(!$past(i_axi_awready)))
|
|
begin
|
begin
|
assert($stable(i_axi_awid));
|
`SLAVE_ASSERT(i_axi_rvalid);
|
assert($stable(i_axi_awaddr));
|
`SLAVE_ASSERT(i_axi_rid == $past(i_axi_rid));
|
assert($stable(i_axi_awlen));
|
`SLAVE_ASSERT(i_axi_rresp == $past(i_axi_rresp));
|
assert($stable(i_axi_awsize));
|
`SLAVE_ASSERT(i_axi_rdata == $past(i_axi_rdata));
|
assert($stable(i_axi_awburst));
|
`SLAVE_ASSERT(i_axi_rlast == $past(i_axi_rlast));
|
assert($stable(i_axi_awlock));
|
|
assert($stable(i_axi_awcache));
|
|
assert($stable(i_axi_awprot));
|
|
assert($stable(i_axi_awqos));
|
|
assert($stable(i_axi_awvalid));
|
|
end
|
end
|
|
|
always @(posedge i_clk)
|
if ((f_past_valid)&&($past(i_axi_bvalid))&&(!$past(i_axi_bready)))
|
if ((f_past_valid)&&($past(i_axi_wvalid))&&(!$past(i_axi_wready)))
|
|
begin
|
begin
|
// AXI write data channel signals
|
`SLAVE_ASSERT(i_axi_bvalid);
|
assert($stable(i_axi_wdata));
|
`SLAVE_ASSERT(i_axi_bid == $past(i_axi_bid));
|
assert($stable(i_axi_wstrb));
|
`SLAVE_ASSERT(i_axi_bresp == $past(i_axi_bresp));
|
assert($stable(i_axi_wlast));
|
end
|
assert($stable(i_axi_wvalid));
|
|
end
|
end
|
|
|
|
// Nothing should be returned or requested on the first clock
|
|
initial `SLAVE_ASSUME(!i_axi_arvalid);
|
|
initial `SLAVE_ASSUME(!i_axi_awvalid);
|
|
initial `SLAVE_ASSUME(!i_axi_wvalid);
|
//
|
//
|
//
|
initial `SLAVE_ASSERT(!i_axi_bvalid);
|
|
initial `SLAVE_ASSERT(!i_axi_rvalid);
|
|
|
///////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Insist upon a maximum delay before a request is accepted
|
// Insist upon a maximum delay before a request is accepted
|
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
generate if (F_AXI_MAXWAIT > 0)
|
|
begin : CHECK_STALL_COUNT
|
//
|
//
|
// AXI write address channel
|
// AXI write address channel
|
//
|
//
|
//
|
//
|
reg [(C_AXI_ID_WIDTH):0] f_axi_awstall;
|
reg [(F_LGDEPTH-1):0] f_axi_awstall,
|
|
f_axi_wstall,
|
|
f_axi_arstall,
|
|
f_axi_bstall,
|
|
f_axi_rstall;
|
|
|
initial f_axi_awstall = 0;
|
initial f_axi_awstall = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!i_axi_reset_n)||(!i_axi_awvalid)||(i_axi_awready))
|
if ((!i_axi_reset_n)||(!i_axi_awvalid)||(i_axi_awready))
|
f_axi_awstall <= 0;
|
f_axi_awstall <= 0;
|
else
|
else if ((!i_axi_bvalid)||(i_axi_bready))
|
f_axi_awstall <= f_axi_awstall + 1'b1;
|
f_axi_awstall <= f_axi_awstall + 1'b1;
|
|
|
always @(*)
|
always @(*)
|
assume((F_AXI_MAXSTALL==0)||(f_axi_awstall < F_AXI_MAXSTALL));
|
`SLAVE_ASSERT(f_axi_awstall < F_AXI_MAXWAIT);
|
|
|
//
|
//
|
// AXI write data channel
|
// AXI write data channel
|
//
|
//
|
//
|
//
|
// AXI explicitly allows write bursts with zero strobes. This is part
|
|
// of how a transaction is aborted (if at all).
|
|
//always @(*) if (i_axi_wvalid) assert(|i_axi_wstrb);
|
|
|
|
reg [(C_AXI_ID_WIDTH):0] f_axi_wstall;
|
|
initial f_axi_wstall = 0;
|
initial f_axi_wstall = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!i_axi_reset_n)||(!i_axi_wvalid)||(i_axi_wready))
|
if ((!i_axi_reset_n)||(!i_axi_wvalid)||(i_axi_wready))
|
f_axi_wstall <= 0;
|
f_axi_wstall <= 0;
|
else
|
else if ((!i_axi_bvalid)||(i_axi_bready))
|
f_axi_wstall <= f_axi_wstall + 1'b1;
|
f_axi_wstall <= f_axi_wstall + 1'b1;
|
always @(*)
|
|
assume((F_AXI_MAXSTALL==0)||(f_axi_wstall < F_AXI_MAXSTALL));
|
|
|
|
|
always @(*)
|
|
`SLAVE_ASSERT(f_axi_wstall < F_AXI_MAXWAIT);
|
|
|
//
|
//
|
// AXI read address channel
|
// AXI read address channel
|
//
|
//
|
//
|
//
|
reg [(C_AXI_ID_WIDTH):0] f_axi_arstall;
|
|
initial f_axi_arstall = 0;
|
initial f_axi_arstall = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!i_axi_reset_n)||(!i_axi_arvalid)||(i_axi_arready))
|
if ((!i_axi_reset_n)||(!i_axi_arvalid)||(i_axi_arready))
|
f_axi_arstall <= 0;
|
f_axi_arstall <= 0;
|
else
|
else if ((!i_axi_rvalid)||(i_axi_rready))
|
f_axi_arstall <= f_axi_arstall + 1'b1;
|
f_axi_arstall <= f_axi_arstall + 1'b1;
|
|
|
|
always @(*)
|
|
`SLAVE_ASSERT(f_axi_arstall < F_AXI_MAXWAIT);
|
|
|
|
// AXI write response channel
|
|
initial f_axi_bstall = 0;
|
|
always @(posedge i_clk)
|
|
if ((!i_axi_reset_n)||(!i_axi_bvalid)||(i_axi_bready))
|
|
f_axi_bstall <= 0;
|
|
else
|
|
f_axi_bstall <= f_axi_bstall + 1'b1;
|
|
|
|
always @(*)
|
|
`SLAVE_ASSUME(f_axi_bstall < F_AXI_MAXWAIT);
|
|
|
|
// AXI read response channel
|
|
initial f_axi_rstall = 0;
|
|
always @(posedge i_clk)
|
|
if ((!i_axi_reset_n)||(!i_axi_rvalid)||(i_axi_rready))
|
|
f_axi_rstall <= 0;
|
|
else
|
|
f_axi_rstall <= f_axi_rstall + 1'b1;
|
|
|
always @(*)
|
always @(*)
|
assume((F_AXI_MAXSTALL==0)||(f_axi_arstall < F_AXI_MAXSTALL));
|
`SLAVE_ASSUME(f_axi_rstall < F_AXI_MAXWAIT);
|
|
|
|
end endgenerate
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Count outstanding transactions
|
// Count outstanding transactions. With these measures, we count
|
|
// once per any burst.
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
initial f_axi_awr_outstanding = 0;
|
initial f_axi_awr_outstanding = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
Line 440... |
Line 475... |
2'b10: f_axi_rd_outstanding <= f_axi_rd_outstanding + 1'b1;
|
2'b10: f_axi_rd_outstanding <= f_axi_rd_outstanding + 1'b1;
|
endcase
|
endcase
|
|
|
// Do not let the number of outstanding requests overflow
|
// Do not let the number of outstanding requests overflow
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
assert(f_axi_wr_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
|
`SLAVE_ASSERT(f_axi_wr_outstanding < {(F_LGDEPTH){1'b1}});
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
assert(f_axi_awr_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
|
`SLAVE_ASSERT(f_axi_awr_outstanding < {(F_LGDEPTH){1'b1}});
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
assert(f_axi_rd_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
|
`SLAVE_ASSERT(f_axi_rd_outstanding < {(F_LGDEPTH){1'b1}});
|
|
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Insist that all responses are returned in less than a maximum delay
|
// Insist that all responses are returned in less than a maximum delay
|
Line 456... |
Line 491... |
// bursts.
|
// bursts.
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
generate if (F_AXI_MAXDELAY > 0)
|
|
begin : CHECK_MAX_DELAY
|
|
|
reg [(C_AXI_ID_WIDTH):0] f_axi_wr_ack_delay,
|
reg [(C_AXI_ID_WIDTH):0] f_axi_wr_ack_delay,
|
f_axi_awr_ack_delay,
|
f_axi_awr_ack_delay,
|
f_axi_rd_ack_delay;
|
f_axi_rd_ack_delay;
|
|
|
initial f_axi_rd_ack_delay = 0;
|
initial f_axi_rd_ack_delay = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!i_axi_reset_n)||(axi_rd_ack))
|
if ((!i_axi_reset_n)||(i_axi_rvalid)||(f_axi_rd_outstanding==0))
|
f_axi_rd_ack_delay <= 0;
|
f_axi_rd_ack_delay <= 0;
|
else if (f_axi_rd_outstanding > 0)
|
else
|
f_axi_rd_ack_delay <= f_axi_rd_ack_delay + 1'b1;
|
f_axi_rd_ack_delay <= f_axi_rd_ack_delay + 1'b1;
|
|
|
initial f_axi_wr_ack_delay = 0;
|
initial f_axi_wr_ack_delay = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!i_axi_reset_n)||(axi_wr_ack))
|
if ((!i_axi_reset_n)||(i_axi_bvalid)||(f_axi_wr_outstanding==0))
|
f_axi_wr_ack_delay <= 0;
|
f_axi_wr_ack_delay <= 0;
|
else if (f_axi_wr_outstanding > 0)
|
else if (f_axi_wr_outstanding > 0)
|
f_axi_wr_ack_delay <= f_axi_wr_ack_delay + 1'b1;
|
f_axi_wr_ack_delay <= f_axi_wr_ack_delay + 1'b1;
|
|
|
initial f_axi_awr_ack_delay = 0;
|
initial f_axi_awr_ack_delay = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!i_axi_reset_n)||(axi_wr_ack))
|
if ((!i_axi_reset_n)||(i_axi_bvalid)||(f_axi_awr_outstanding == 0))
|
f_axi_awr_ack_delay <= 0;
|
f_axi_awr_ack_delay <= 0;
|
else if (f_axi_awr_outstanding > 0)
|
else
|
f_axi_awr_ack_delay <= f_axi_awr_ack_delay + 1'b1;
|
f_axi_awr_ack_delay <= f_axi_awr_ack_delay + 1'b1;
|
|
|
always @(posedge i_clk)
|
always @(*)
|
assume((F_AXI_MAXDELAY==0)||(f_axi_rd_ack_delay < F_AXI_MAXDELAY));
|
`SLAVE_ASSERT(f_axi_rd_ack_delay < F_AXI_MAXDELAY);
|
|
|
always @(posedge i_clk)
|
always @(*)
|
assume((F_AXI_MAXDELAY==0)||(f_axi_wr_ack_delay < F_AXI_MAXDELAY));
|
`SLAVE_ASSERT(f_axi_wr_ack_delay < F_AXI_MAXDELAY);
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
assume((F_AXI_MAXDELAY==0)||(f_axi_awr_ack_delay < F_AXI_MAXDELAY));
|
`SLAVE_ASSERT(f_axi_awr_ack_delay < F_AXI_MAXDELAY);
|
|
end endgenerate
|
|
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Assume all acknowledgements must follow requests
|
// Assume acknowledgements must follow requests
|
//
|
//
|
// The outstanding count is a count of bursts, but the acknowledgements
|
// The outstanding count is a count of bursts, but the acknowledgements
|
// we are looking for are individual. Hence, there should be no
|
// we are looking for are individual. Hence, there should be no
|
// individual acknowledgements coming back if there's no outstanding
|
// individual acknowledgements coming back if there's no outstanding
|
// burst.
|
// burst.
|
Line 507... |
Line 546... |
|
|
//
|
//
|
// AXI write response channel
|
// AXI write response channel
|
//
|
//
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!axi_awr_req)&&(axi_wr_ack))
|
if ((!axi_awr_req)&&(i_axi_bvalid))
|
assume(f_axi_awr_outstanding > 0);
|
`SLAVE_ASSERT(f_axi_awr_outstanding > 0);
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!axi_wr_req)&&(axi_wr_ack))
|
if ((!axi_wr_req)&&(i_axi_bvalid))
|
assume(f_axi_wr_outstanding > 0);
|
`SLAVE_ASSERT(f_axi_wr_outstanding > 0);
|
|
|
//
|
//
|
// AXI read data channel signals
|
// AXI read data channel signals
|
//
|
//
|
initial f_axi_rd_outstanding = 0;
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!axi_ard_req)&&(axi_rd_ack))
|
if ((!axi_ard_req)&&(i_axi_rvalid))
|
assume(f_axi_rd_outstanding > 0);
|
`SLAVE_ASSERT(f_axi_rd_outstanding > 0);
|
|
|
///////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// Manage the ID buffer. Basic rules apply such as you can't
|
// Manage the ID buffer. Basic rules apply such as you can't
|
// make a request of an already requested ID # before that ID
|
// make a request of an already requested ID # before that ID
|
// is returned, etc.
|
// is returned, etc.
|
//
|
//
|
// Elements in this buffer reference transactions--possibly burst
|
// Elements in this buffer reference transactions--possibly burst
|
// transactions and not necessarily the individual values.
|
// transactions and not necessarily the individual values.
|
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
// Now, let's look into that FIFO. Without it, we know nothing about
|
// Now, let's look into that FIFO. Without it, we know nothing about
|
// the ID's
|
// the ID's
|
|
|
initial f_axi_rd_id_outstanding = 0;
|
initial f_axi_rd_id_outstanding = 0;
|
initial f_axi_wr_id_outstanding = 0;
|
initial f_axi_wr_id_outstanding = 0;
|
Line 646... |
Line 685... |
if (f_axi_awr_id_outstanding[k])
|
if (f_axi_awr_id_outstanding[k])
|
f_axi_awr_id_outstanding_count = f_axi_awr_id_outstanding_count +1;
|
f_axi_awr_id_outstanding_count = f_axi_awr_id_outstanding_count +1;
|
end
|
end
|
|
|
always @(*)
|
always @(*)
|
assert((!F_CHECK_IDS)||(f_axi_awr_outstanding== f_axi_awr_id_outstanding_count));
|
`SLAVE_ASSUME((!F_CHECK_IDS)||(f_axi_awr_outstanding== f_axi_awr_id_outstanding_count));
|
|
|
always @(*)
|
always @(*)
|
assert((!F_CHECK_IDS)||(f_axi_wr_outstanding == f_axi_wr_id_outstanding_count));
|
`SLAVE_ASSUME((!F_CHECK_IDS)||(f_axi_wr_outstanding == f_axi_wr_id_outstanding_count));
|
|
|
always @(*)
|
always @(*)
|
assert((!F_CHECK_IDS)||(f_axi_rd_outstanding == f_axi_rd_id_outstanding_count));
|
`SLAVE_ASSUME((!F_CHECK_IDS)||(f_axi_rd_outstanding == f_axi_rd_id_outstanding_count));
|
|
|
always @(*)
|
always @(*)
|
assume( ((f_axi_wr_id_complete)&(~f_axi_awr_id_outstanding)) == 0);
|
assume( ((f_axi_wr_id_complete)&(~f_axi_awr_id_outstanding)) == 0);
|
|
|
generate if (F_OPT_BURSTS)
|
generate if (F_OPT_BURSTS)
|
Line 683... |
Line 722... |
if (axi_awr_req)
|
if (axi_awr_req)
|
begin
|
begin
|
f_wr_pending <= i_axi_awlen+9'h1;
|
f_wr_pending <= i_axi_awlen+9'h1;
|
assert(f_wr_pending == 0);
|
assert(f_wr_pending == 0);
|
r_last_wr_id_valid <= 1'b1;
|
r_last_wr_id_valid <= 1'b1;
|
|
`SLAVE_ASSUME(i_axi_awlen <= F_AXI_MAXBURST);
|
end
|
end
|
|
|
if (axi_ard_req)
|
if (axi_ard_req)
|
f_rd_pending[i_axi_arid] <= i_axi_arlen+9'h1;
|
f_rd_pending[i_axi_arid] <= i_axi_arlen+9'h1;
|
|
|
Line 714... |
Line 754... |
else
|
else
|
r_last_rd_id_valid <= 1'b1;
|
r_last_rd_id_valid <= 1'b1;
|
|
|
r_last_rd_id <= i_axi_rid;
|
r_last_rd_id <= i_axi_rid;
|
if ((axi_rd_ack)&&(r_last_rd_id_valid))
|
if ((axi_rd_ack)&&(r_last_rd_id_valid))
|
assume(i_axi_rid == r_last_rd_id);
|
`SLAVE_ASSERT(i_axi_rid == r_last_rd_id);
|
end
|
end
|
|
|
if ((axi_rd_ack)&&(i_axi_rlast))
|
if ((axi_rd_ack)&&(i_axi_rlast))
|
assert(f_rd_count == f_rd_pending[i_axi_rid]-9'h1);
|
assert(f_rd_count == f_rd_pending[i_axi_rid]-9'h1);
|
if ((axi_rd_ack)&&(i_axi_rlast))
|
if ((axi_rd_ack)&&(i_axi_rlast))
|
Line 729... |
Line 769... |
end else begin
|
end else begin
|
always @(*) begin
|
always @(*) begin
|
// Since we aren't allowing bursts, *every*
|
// Since we aren't allowing bursts, *every*
|
// write data and read data must always be the last
|
// write data and read data must always be the last
|
// value
|
// value
|
assert((i_axi_wlast)||(!i_axi_wvalid));
|
`SLAVE_ASSUME((i_axi_wlast)||(!i_axi_wvalid));
|
assume((i_axi_rlast)||(!i_axi_rvalid));
|
`SLAVE_ASSERT((i_axi_rlast)||(!i_axi_rvalid));
|
|
|
assert((!i_axi_arvalid)||(i_axi_arlen==0));
|
assert((!i_axi_arvalid)||(i_axi_arlen==0));
|
assert((!i_axi_awvalid)||(i_axi_awlen==0));
|
assert((!i_axi_awvalid)||(i_axi_awlen==0));
|
end
|
end
|
|
|