Line 2... |
Line 2... |
//
|
//
|
// Filename: faxi_slave.v (Formal properties of an AXI slave)
|
// Filename: faxi_slave.v (Formal properties of an AXI slave)
|
//
|
//
|
// Project: Pipelined Wishbone to AXI converter
|
// Project: Pipelined Wishbone to AXI converter
|
//
|
//
|
// Purpose:
|
// Purpose: This file contains a set of formal properties which can be
|
|
// used to formally verify that a core truly follows the full
|
|
// AXI4 specification.
|
//
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Technology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2017, Gisselquist Technology, LLC
|
// Copyright (C) 2017-2019, 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 47... |
// 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_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 [7:0] F_AXI_MAXBURST = 8'hff,// Maximum burst length, minus 1
|
|
parameter F_LGDEPTH = 10,
|
|
parameter F_LGFIFO = 3,
|
|
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
|
input wire [0:0] i_axi_awlock, // Write lock type
|
input wire [0:0] i_axi_awlock, // Write lock type
|
Line 73... |
Line 78... |
input wire [DW/8-1:0] i_axi_wstrb, // Write strobes
|
input wire [DW/8-1:0] i_axi_wstrb, // Write strobes
|
input wire i_axi_wlast, // Last write transaction
|
input wire i_axi_wlast, // Last write transaction
|
input wire i_axi_wvalid, // Write valid
|
input wire i_axi_wvalid, // Write valid
|
|
|
// AXI write response channel signals
|
// AXI write response channel signals
|
input wire [C_AXI_ID_WIDTH-1:0] i_axi_bid, // Response ID
|
// input wire [C_AXI_ID_WIDTH-1:0] i_axi_bid, // Response ID
|
input wire [1:0] i_axi_bresp, // Write response
|
input wire [1:0] i_axi_bresp, // Write response
|
input wire i_axi_bvalid, // Write reponse valid
|
input wire i_axi_bvalid, // Write reponse valid
|
input wire i_axi_bready, // Response ready
|
input wire i_axi_bready, // Response ready
|
|
|
// AXI read address channel signals
|
// AXI read address channel signals
|
input wire i_axi_arready, // Read address ready
|
input wire i_axi_arready, // Read address ready
|
input wire [C_AXI_ID_WIDTH-1:0] i_axi_arid, // Read ID
|
// input wire [C_AXI_ID_WIDTH-1:0] i_axi_arid, // Read ID
|
input wire [AW-1:0] i_axi_araddr, // Read address
|
input wire [AW-1:0] i_axi_araddr, // Read address
|
input wire [7:0] i_axi_arlen, // Read Burst Length
|
input wire [7:0] i_axi_arlen, // Read Burst Length
|
input wire [2:0] i_axi_arsize, // Read Burst size
|
input wire [2:0] i_axi_arsize, // Read Burst size
|
input wire [1:0] i_axi_arburst, // Read Burst type
|
input wire [1:0] i_axi_arburst, // Read Burst type
|
input wire [0:0] i_axi_arlock, // Read lock type
|
input wire [0:0] i_axi_arlock, // Read lock type
|
Line 92... |
Line 97... |
input wire [2:0] i_axi_arprot, // Read Protection type
|
input wire [2:0] i_axi_arprot, // Read Protection type
|
input wire [3:0] i_axi_arqos, // Read Protection type
|
input wire [3:0] i_axi_arqos, // Read Protection type
|
input wire i_axi_arvalid, // Read address valid
|
input wire i_axi_arvalid, // Read address valid
|
|
|
// AXI read data channel signals
|
// AXI read data channel signals
|
input wire [C_AXI_ID_WIDTH-1:0] i_axi_rid, // Response ID
|
// input wire [C_AXI_ID_WIDTH-1:0] i_axi_rid, // Response ID
|
input wire [1:0] i_axi_rresp, // Read response
|
input wire [1:0] i_axi_rresp, // Read response
|
input wire i_axi_rvalid, // Read reponse valid
|
input wire i_axi_rvalid, // Read reponse valid
|
input wire [DW-1:0] i_axi_rdata, // Read data
|
input wire [DW-1:0] i_axi_rdata, // Read data
|
input wire i_axi_rlast, // Read last
|
input wire i_axi_rlast, // Read last
|
input wire i_axi_rready, // Read Response ready
|
input wire i_axi_rready, // Read Response ready
|
//
|
//
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_rd_outstanding,
|
output reg [F_LGDEPTH-1:0] f_axi_rd_nbursts,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_wr_outstanding,
|
output reg [F_LGDEPTH-1:0] f_axi_rd_outstanding,
|
output reg [(C_AXI_ID_WIDTH-1):0] f_axi_awr_outstanding,
|
output reg [F_LGDEPTH-1:0] f_axi_wr_nbursts,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_rd_id_outstanding,
|
output reg [F_LGDEPTH-1:0] f_axi_awr_outstanding,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_awr_id_outstanding,
|
output reg [F_LGDEPTH-1:0] f_axi_awr_nbursts,
|
output reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_wr_id_outstanding
|
// Address writes without write valids
|
|
//
|
|
// output reg [(9-1):0] f_axi_wr_pending,
|
|
//
|
|
// RD_COUNT: increment on read w/o last, cleared on read w/ last
|
|
output reg [(9-1):0] f_axi_rd_count,
|
|
output reg [(72-1):0] f_axi_rdfifo
|
);
|
);
|
reg [((1<<C_AXI_ID_WIDTH)-1):0] f_axi_wr_id_complete;
|
reg [(9-1):0] f_axi_wr_count;
|
|
|
//*****************************************************************************
|
//*****************************************************************************
|
// Parameter declarations
|
// Parameter declarations
|
//*****************************************************************************
|
//*****************************************************************************
|
|
|
Line 128... |
Line 138... |
: ((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_AXI_MAXWAIT = F_AXI_MAXSTALL;
|
|
|
|
|
//*****************************************************************************
|
//*****************************************************************************
|
// Internal register and wire declarations
|
// Internal register and wire declarations
|
//*****************************************************************************
|
//*****************************************************************************
|
|
|
// Things we're not changing ...
|
|
always @(*)
|
|
begin
|
|
assume(i_axi_awlen == 8'h0); // Burst length is one
|
|
assume(i_axi_awsize == 3'b101); // maximum bytes per burst is 32
|
|
assume(i_axi_awburst == 2'b01); // Incrementing address (ignored)
|
|
assume(i_axi_arburst == 2'b01); // Incrementing address (ignored)
|
|
assume(i_axi_awlock == 1'b0); // Normal signaling
|
|
assume(i_axi_arlock == 1'b0); // Normal signaling
|
|
assume(i_axi_awcache == 4'h2); // Normal: no cache, no buffer
|
|
assume(i_axi_arcache == 4'h2); // Normal: no cache, no buffer
|
|
assume(i_axi_awprot == 3'b010);// Unpriviledged, unsecure, data access
|
|
assume(i_axi_arprot == 3'b010);// Unpriviledged, unsecure, data access
|
|
assume(i_axi_awqos == 4'h0); // Lowest quality of service (unused)
|
|
assume(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 159... |
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 assume
|
|
`define SLAVE_ASSERT assert
|
|
|
//
|
//
|
// Setup
|
// Setup
|
//
|
//
|
reg f_past_valid;
|
reg f_past_valid;
|
integer k;
|
integer k;
|
Line 176... |
Line 174... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
f_past_valid <= 1'b1;
|
f_past_valid <= 1'b1;
|
always @(*)
|
always @(*)
|
if (!f_past_valid)
|
if (!f_past_valid)
|
assume(!i_axi_reset_n);
|
assume(!i_axi_reset_n);
|
|
// WAS AN ASSERT
|
|
|
//
|
////////////////////////////////////////////////////////////////////////
|
// All signals must be synchronous with the clock
|
|
//
|
|
always @($global_clock)
|
|
if (f_past_valid) begin
|
|
// Assume our inputs will only change on the positive edge
|
|
// of the clock
|
|
if (!$rose(i_clk))
|
|
begin
|
|
// AXI inputs
|
|
assert($stable(i_axi_awready));
|
|
assert($stable(i_axi_wready));
|
|
//
|
|
assert($stable(i_axi_bid));
|
|
assert($stable(i_axi_bresp));
|
|
assert($stable(i_axi_bvalid));
|
|
assert($stable(i_axi_arready));
|
|
//
|
|
assert($stable(i_axi_rid));
|
|
assert($stable(i_axi_rresp));
|
|
assert($stable(i_axi_rvalid));
|
|
assert($stable(i_axi_rdata));
|
|
assert($stable(i_axi_rlast));
|
|
//
|
|
// AXI outputs
|
|
//
|
|
assume($stable(i_axi_awvalid));
|
|
assume($stable(i_axi_awid));
|
|
assume($stable(i_axi_awlen));
|
|
assume($stable(i_axi_awsize));
|
|
assume($stable(i_axi_awlock));
|
|
assume($stable(i_axi_awcache));
|
|
assume($stable(i_axi_awprot));
|
|
assume($stable(i_axi_awqos));
|
|
//
|
|
assume($stable(i_axi_wvalid));
|
|
assume($stable(i_axi_wdata));
|
|
assume($stable(i_axi_wstrb));
|
|
assume($stable(i_axi_wlast));
|
|
//
|
|
assume($stable(i_axi_arvalid));
|
|
assume($stable(i_axi_arid));
|
|
assume($stable(i_axi_arlen));
|
|
assume($stable(i_axi_arsize));
|
|
assume($stable(i_axi_arburst));
|
|
assume($stable(i_axi_arlock));
|
|
assume($stable(i_axi_arprot));
|
|
assume($stable(i_axi_arqos));
|
|
//
|
|
assume($stable(i_axi_bready));
|
|
//
|
|
assume($stable(i_axi_rready));
|
|
//
|
|
// Formal outputs
|
|
//
|
|
assume($stable(f_axi_rd_outstanding));
|
|
assume($stable(f_axi_wr_outstanding));
|
|
assume($stable(f_axi_awr_outstanding));
|
|
end
|
|
end
|
|
|
|
////////////////////////////////////////////////////
|
|
//
|
//
|
//
|
//
|
// Reset properties
|
// Reset properties
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
|
localparam [0:0] F_OPT_ASSUME_RESET = 1'b1;
|
|
generate if (F_OPT_ASSUME_RESET)
|
|
begin : ASSUME_INITIAL_RESET
|
|
always @(*)
|
|
if (!f_past_valid)
|
|
assume(!i_axi_reset_n);
|
|
end else begin : ASSERT_INITIAL_RESET
|
|
always @(*)
|
|
if (!f_past_valid)
|
|
assert(!i_axi_reset_n);
|
|
end endgenerate
|
|
//
|
|
// 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)
|
always @(posedge i_clk)
|
if ((f_past_valid)&&(!$past(i_axi_reset_n)))
|
if ((f_past_valid)&&(!$past(i_axi_reset_n))&&(!$past(&f_reset_length)))
|
|
`SLAVE_ASSUME(!i_axi_reset_n);
|
|
|
|
generate if (F_OPT_ASSUME_RESET)
|
|
begin : ASSUME_RESET
|
|
always @(posedge i_clk)
|
|
if ((f_past_valid)&&(!$past(i_axi_reset_n))&&(!$past(&f_reset_length)))
|
|
assume(!i_axi_reset_n);
|
|
|
|
always @(*)
|
|
if ((f_reset_length > 0)&&(f_reset_length < 4'hf))
|
|
assume(!i_axi_reset_n);
|
|
|
|
end else begin : ASSERT_RESET
|
|
|
|
always @(posedge i_clk)
|
|
if ((f_past_valid)&&(!$past(i_axi_reset_n))&&(!$past(&f_reset_length)))
|
|
assert(!i_axi_reset_n);
|
|
|
|
always @(*)
|
|
if ((f_reset_length > 0)&&(f_reset_length < 4'hf))
|
|
assert(!i_axi_reset_n);
|
|
|
|
end endgenerate
|
|
|
|
always @(posedge i_clk)
|
|
if ((!f_past_valid)||(!$past(i_axi_reset_n)))
|
begin
|
begin
|
assume(!i_axi_arvalid);
|
`SLAVE_ASSUME(!i_axi_arvalid);
|
assume(!i_axi_awvalid);
|
`SLAVE_ASSUME(!i_axi_awvalid);
|
assume(!i_axi_wvalid);
|
`SLAVE_ASSUME(!i_axi_wvalid);
|
assert(!i_axi_bvalid);
|
//
|
assert(!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
|
assert(i_axi_rid == $past(i_axi_rid));
|
`SLAVE_ASSUME(i_axi_awvalid);
|
assert(i_axi_rresp == $past(i_axi_rresp));
|
`SLAVE_ASSUME(i_axi_awaddr == $past(i_axi_awaddr));
|
assert(i_axi_rdata == $past(i_axi_rdata));
|
// `SLAVE_ASSUME($stable(i_axi_awid));
|
assert(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
|
assert(i_axi_bid == $past(i_axi_bid));
|
`SLAVE_ASSUME(i_axi_wvalid);
|
assert(i_axi_bresp == $past(i_axi_bresp));
|
`SLAVE_ASSUME($stable(i_axi_wstrb));
|
|
`SLAVE_ASSUME($stable(i_axi_wdata));
|
|
`SLAVE_ASSUME($stable(i_axi_wlast));
|
end
|
end
|
end
|
|
|
|
// Nothing should be returning a result on the first clock
|
|
initial assert(!i_axi_bvalid);
|
|
initial assert(!i_axi_rvalid);
|
|
//
|
|
initial assume(!i_axi_arvalid);
|
|
initial assume(!i_axi_awvalid);
|
|
initial assume(!i_axi_wvalid);
|
|
|
|
//////////////////////////////////////////////
|
|
//
|
|
//
|
|
// Stability assumptions, AXI outputs/requests
|
|
//
|
|
//
|
|
//////////////////////////////////////////////
|
|
|
|
// Read address chanel
|
// Incoming Read address channel
|
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
|
assume(i_axi_arvalid);
|
`SLAVE_ASSUME(i_axi_arvalid);
|
assume($stable(i_axi_arid));
|
// `SLAVE_ASSUME($stable(i_axi_arid));
|
assume($stable(i_axi_araddr));
|
`SLAVE_ASSUME($stable(i_axi_araddr));
|
assume($stable(i_axi_arlen));
|
`SLAVE_ASSUME($stable(i_axi_arlen));
|
assume($stable(i_axi_arsize));
|
`SLAVE_ASSUME($stable(i_axi_arsize));
|
assume($stable(i_axi_arburst));
|
`SLAVE_ASSUME($stable(i_axi_arburst));
|
assume($stable(i_axi_arlock));
|
`SLAVE_ASSUME($stable(i_axi_arlock));
|
assume($stable(i_axi_arcache));
|
`SLAVE_ASSUME($stable(i_axi_arcache));
|
assume($stable(i_axi_arprot));
|
`SLAVE_ASSUME($stable(i_axi_arprot));
|
assume($stable(i_axi_arqos));
|
`SLAVE_ASSUME($stable(i_axi_arqos));
|
assume($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
|
assume($stable(i_axi_awid));
|
`SLAVE_ASSERT(i_axi_rvalid);
|
assume($stable(i_axi_awaddr));
|
// `SLAVE_ASSERT($stable(i_axi_rid));
|
assume($stable(i_axi_awlen));
|
`SLAVE_ASSERT($stable(i_axi_rresp));
|
assume($stable(i_axi_awsize));
|
`SLAVE_ASSERT($stable(i_axi_rdata));
|
assume($stable(i_axi_awburst));
|
`SLAVE_ASSERT($stable(i_axi_rlast));
|
assume($stable(i_axi_awlock));
|
|
assume($stable(i_axi_awcache));
|
|
assume($stable(i_axi_awprot));
|
|
assume($stable(i_axi_awqos));
|
|
assume($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);
|
assume($stable(i_axi_wdata));
|
/// `SLAVE_ASSERT($stable(i_axi_bid));
|
assume($stable(i_axi_wstrb));
|
`SLAVE_ASSERT($stable(i_axi_bresp));
|
assume($stable(i_axi_wlast));
|
end
|
assume($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 @(*)
|
assert((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
|
// AXI explicitly allows write bursts with zero strobes. This is part
|
// of how a transaction is aborted (if at all).
|
// of how a transaction is aborted (if at all).
|
//always @(*) if (i_axi_wvalid) assume(|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 @(*)
|
|
assert((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 @(*)
|
always @(*)
|
assert((F_AXI_MAXSTALL==0)||(f_axi_arstall < F_AXI_MAXSTALL));
|
`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 @(*)
|
|
`SLAVE_ASSUME(f_axi_rstall < F_AXI_MAXWAIT);
|
|
|
|
end endgenerate
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
Line 415... |
Line 418... |
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
initial f_axi_awr_outstanding = 0;
|
initial f_axi_awr_outstanding = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (!i_axi_reset_n)
|
if (!i_axi_reset_n)
|
f_axi_awr_outstanding <= 0;
|
f_axi_awr_outstanding <= 0;
|
else case({ (axi_awr_req), (axi_wr_ack) })
|
else case({ (axi_awr_req), (axi_wr_req) })
|
2'b10: f_axi_awr_outstanding <= f_axi_awr_outstanding + 1'b1;
|
2'b10: f_axi_awr_outstanding <= f_axi_awr_outstanding + i_axi_awlen-1;
|
2'b01: f_axi_awr_outstanding <= f_axi_awr_outstanding - 1'b1;
|
2'b01: f_axi_awr_outstanding <= f_axi_awr_outstanding - 1'b1;
|
|
2'b11: f_axi_awr_outstanding <= f_axi_awr_outstanding + i_axi_awlen; // +1 -1
|
default: begin end
|
default: begin end
|
endcase
|
endcase
|
|
|
initial f_axi_wr_outstanding = 0;
|
initial f_axi_awr_nbursts = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (!i_axi_reset_n)
|
if (!i_axi_reset_n)
|
f_axi_wr_outstanding <= 0;
|
f_axi_awr_nbursts <= 0;
|
|
else case({ (axi_awr_req), (axi_wr_ack) })
|
|
2'b10: f_axi_awr_nbursts <= f_axi_awr_nbursts + 1'b1;
|
|
2'b01: f_axi_awr_nbursts <= f_axi_awr_nbursts - 1'b1;
|
|
default: begin end
|
|
endcase
|
|
|
|
initial f_axi_wr_nbursts = 0;
|
|
always @(posedge i_clk)
|
|
if (!i_axi_reset_n)
|
|
f_axi_wr_nbursts <= 0;
|
else case({ (axi_wr_req)&&(i_axi_wlast), (axi_wr_ack) })
|
else case({ (axi_wr_req)&&(i_axi_wlast), (axi_wr_ack) })
|
2'b01: f_axi_wr_outstanding <= f_axi_wr_outstanding - 1'b1;
|
2'b01: f_axi_wr_nbursts <= f_axi_wr_nbursts - 1'b1;
|
2'b10: f_axi_wr_outstanding <= f_axi_wr_outstanding + 1'b1;
|
2'b10: f_axi_wr_nbursts <= f_axi_wr_nbursts + 1'b1;
|
|
default: begin end
|
|
endcase
|
|
|
|
initial f_axi_rd_nbursts = 0;
|
|
always @(posedge i_clk)
|
|
if (!i_axi_reset_n)
|
|
f_axi_rd_nbursts <= 0;
|
|
else case({ (axi_ard_req), (axi_rd_ack)&&(i_axi_rlast) })
|
|
2'b01: f_axi_rd_nbursts <= f_axi_rd_nbursts - 1'b1;
|
|
2'b10: f_axi_rd_nbursts <= f_axi_rd_nbursts + 1'b1;
|
endcase
|
endcase
|
|
|
initial f_axi_rd_outstanding = 0;
|
initial f_axi_rd_outstanding = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (!i_axi_reset_n)
|
if (!i_axi_reset_n)
|
f_axi_rd_outstanding <= 0;
|
f_axi_rd_outstanding <= 0;
|
else case({ (axi_ard_req), (axi_rd_ack)&&(i_axi_rlast) })
|
else case({ (axi_ard_req), (axi_rd_ack) })
|
2'b01: f_axi_rd_outstanding <= f_axi_rd_outstanding - 1'b1;
|
2'b01: f_axi_rd_outstanding <= f_axi_rd_outstanding - 1'b1;
|
2'b10: f_axi_rd_outstanding <= f_axi_rd_outstanding + 1'b1;
|
2'b10: f_axi_rd_outstanding <= f_axi_rd_outstanding + i_axi_arlen+1;
|
|
2'b11: f_axi_rd_outstanding <= f_axi_rd_outstanding + i_axi_arlen;
|
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)
|
assume(f_axi_wr_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)
|
assume(f_axi_awr_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
|
`SLAVE_ASSERT(f_axi_rd_outstanding < {(F_LGDEPTH){1'b1}});
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
assume(f_axi_rd_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
|
`SLAVE_ASSERT(f_axi_awr_nbursts < {(F_LGDEPTH){1'b1}});
|
|
always @(posedge i_clk)
|
|
`SLAVE_ASSERT(f_axi_wr_nbursts < {(F_LGDEPTH){1'b1}});
|
|
always @(posedge i_clk)
|
|
`SLAVE_ASSERT(f_axi_rd_nbursts < {(F_LGDEPTH){1'b1}});
|
|
|
|
// Cannot have outstanding values if there aren't any outstanding
|
|
// bursts
|
|
always @(posedge i_clk)
|
|
if (f_axi_awr_outstanding > 0)
|
|
`SLAVE_ASSERT(f_axi_awr_nbursts > 0);
|
|
// else if (f_axi_awr_outstanding == 0)
|
|
// Doesn't apply. Might have awr_outstanding == 0 and
|
|
// awr_nbursts>0
|
|
always @(posedge i_clk)
|
|
if (f_axi_rd_outstanding > 0)
|
|
`SLAVE_ASSERT(f_axi_rd_nbursts > 0);
|
|
else
|
|
`SLAVE_ASSERT(f_axi_rd_nbursts == 0);
|
|
always @(posedge i_clk)
|
|
`SLAVE_ASSERT(f_axi_rd_nbursts <= f_axi_rd_outstanding);
|
|
|
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// 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 457... |
Line 502... |
// 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_wvalid)&&(!i_axi_wlast))
|
|
||(i_axi_bvalid)||(f_axi_awr_outstanding==0))
|
f_axi_wr_ack_delay <= 0;
|
f_axi_wr_ack_delay <= 0;
|
else if (f_axi_wr_outstanding > 0)
|
else
|
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)||(i_axi_wvalid)
|
|
||(f_axi_awr_nbursts == 0)
|
|
||(f_axi_wr_nbursts == 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 @(*)
|
assert((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 @(*)
|
assert((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)
|
assert((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 508... |
Line 560... |
|
|
//
|
//
|
// AXI write response channel
|
// AXI write response channel
|
//
|
//
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((!axi_awr_req)&&(axi_wr_ack))
|
if (i_axi_bvalid)
|
assert(f_axi_awr_outstanding > 0);
|
begin
|
always @(posedge i_clk)
|
`SLAVE_ASSERT(f_axi_awr_nbursts > 0);
|
if ((!axi_wr_req)&&(axi_wr_ack))
|
`SLAVE_ASSERT(f_axi_wr_nbursts > 0);
|
assert(f_axi_wr_outstanding > 0);
|
end
|
|
|
//
|
//
|
// 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 (i_axi_rvalid)
|
assert(f_axi_rd_outstanding > 0);
|
begin
|
|
`SLAVE_ASSERT(f_axi_rd_outstanding > 0);
|
|
`SLAVE_ASSERT(f_axi_rd_nbursts > 0);
|
|
if (!i_axi_rlast)
|
|
`SLAVE_ASSERT(f_axi_rd_outstanding > 1);
|
|
end
|
|
|
///////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
//
|
|
//
|
|
// Manage the ID buffer. Basic rules apply such as you can't
|
|
// make a request of an already requested ID # before that ID
|
|
// is returned, etc.
|
|
//
|
//
|
// Elements in this buffer reference transactions--possibly burst
|
|
// transactions and not necessarily the individual values.
|
|
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
// Now, let's look into that FIFO. Without it, we know nothing about
|
|
// the ID's
|
|
|
|
initial f_axi_rd_id_outstanding = 0;
|
|
initial f_axi_wr_id_outstanding = 0;
|
|
initial f_axi_awr_id_outstanding = 0;
|
|
initial f_axi_wr_id_complete = 0;
|
|
always @(posedge i_clk)
|
|
if (!i_axi_reset_n)
|
|
begin
|
|
f_axi_rd_id_outstanding <= 0;
|
|
f_axi_wr_id_outstanding <= 0;
|
|
f_axi_wr_id_complete <= 0;
|
|
f_axi_awr_id_outstanding <= 0;
|
|
end else begin
|
|
// When issuing a write
|
|
if (axi_awr_req)
|
|
begin
|
|
if ((F_CONSECUTIVE_IDS)&&(F_CHECK_IDS))
|
|
assume(f_axi_awr_id_outstanding[i_axi_awid+1'b1] == 1'b0);
|
|
assume((!F_CHECK_IDS)
|
|
||(f_axi_awr_id_outstanding[i_axi_awid] == 1'b0));
|
|
assume((!F_CHECK_IDS)
|
|
||(f_axi_wr_id_complete[i_axi_awid] == 1'b0));
|
|
f_axi_awr_id_outstanding[i_axi_awid] <= 1'b1;
|
|
f_axi_wr_id_complete[i_axi_awid] <= 1'b0;
|
|
end
|
|
|
|
if (axi_wr_req)
|
|
begin
|
|
if ((F_CONSECUTIVE_IDS)&&(F_CHECK_IDS))
|
|
assume(f_axi_wr_id_outstanding[i_axi_awid+1'b1] == 1'b0);
|
|
assume((!F_CHECK_IDS)
|
|
||(f_axi_wr_id_outstanding[i_axi_awid] == 1'b0));
|
|
f_axi_wr_id_outstanding[i_axi_awid] <= 1'b1;
|
|
if (i_axi_wlast)
|
|
begin
|
|
assert(f_axi_wr_id_complete[i_axi_awid] == 1'b0);
|
|
f_axi_wr_id_complete[i_axi_awid] <= 1'b1;
|
|
end
|
|
end
|
|
|
|
// When issuing a read
|
generate if (!F_OPT_BURSTS)
|
if (axi_ard_req)
|
|
begin
|
begin
|
if ((F_CONSECUTIVE_IDS)&&(F_CHECK_IDS))
|
|
assume(f_axi_rd_id_outstanding[i_axi_arid+1'b1] == 1'b0);
|
|
assume((!F_CHECK_IDS)
|
|
||(f_axi_rd_id_outstanding[i_axi_arid] == 1'b0));
|
|
f_axi_rd_id_outstanding[i_axi_arid] <= 1'b1;
|
|
end
|
|
|
|
// When a write is acknowledged
|
always @(posedge i_clk)
|
if (axi_wr_ack)
|
if (i_axi_awvalid)
|
begin
|
`SLAVE_ASSUME(i_axi_awlen == 0);
|
if (F_CHECK_IDS)
|
|
begin
|
|
assert(f_axi_awr_id_outstanding[i_axi_bid]);
|
|
assert(f_axi_wr_id_outstanding[i_axi_bid]);
|
|
assert((!F_STRICT_ORDER)||(!F_CONSECUTIVE_IDS)
|
|
||(!f_axi_wr_id_outstanding[i_axi_bid-1'b1]));
|
|
assert((!F_STRICT_ORDER)||(!F_CONSECUTIVE_IDS)
|
|
||(!f_axi_awr_id_outstanding[i_axi_bid-1'b1]));
|
|
assert(f_axi_wr_id_complete[i_axi_bid]);
|
|
end
|
|
f_axi_awr_id_outstanding[i_axi_bid] <= 1'b0;
|
|
f_axi_wr_id_outstanding[i_axi_bid] <= 1'b0;
|
|
f_axi_wr_id_complete[i_axi_bid] <= 1'b0;
|
|
end
|
|
|
|
// When a read is acknowledged
|
always @(posedge i_clk)
|
if (axi_rd_ack)
|
if (i_axi_wvalid)
|
begin
|
`SLAVE_ASSUME(i_axi_wlast);
|
if (F_CHECK_IDS)
|
|
begin
|
|
assert(f_axi_rd_id_outstanding[i_axi_rid]);
|
|
assert((!F_STRICT_ORDER)||(!F_CONSECUTIVE_IDS)
|
|
||(!f_axi_rd_id_outstanding[i_axi_rid-1'b1]));
|
|
end
|
|
|
|
if (i_axi_rlast)
|
always @(posedge i_clk)
|
f_axi_rd_id_outstanding[i_axi_rid] <= 1'b0;
|
if (i_axi_arvalid)
|
end
|
`SLAVE_ASSUME(i_axi_arlen == 0);
|
end
|
|
|
|
|
always @(*)
|
|
`SLAVE_ASSERT(f_axi_rd_nbursts == f_axi_rd_outstanding);
|
|
end endgenerate
|
|
|
reg [LGFIFOLN:0] f_axi_rd_id_outstanding_count,
|
reg [7:0] wrfifo [0:((1<<F_LGDEPTH)-1)];
|
f_axi_awr_id_outstanding_count,
|
reg [7:0] rdfifo [0:((1<<F_LGDEPTH)-1)];
|
f_axi_wr_id_outstanding_count;
|
reg [F_LGDEPTH-1:0] rd_rdaddr, wr_rdaddr, rd_wraddr, wr_wraddr;
|
|
reg [7:0] rdfifo_data, wrfifo_data;
|
|
reg [F_LGDEPTH-1:0] rdfifo_outstanding;
|
|
wire [7:0] this_wlen;
|
|
wire [F_LGDEPTH-1:0] wrfifo_fill, rdfifo_fill;
|
|
|
|
/*
|
|
always @(posedge i_clk)
|
|
if (!i_axi_reset_n)
|
|
begin
|
|
f_axi_wburst_fifo <= 0;
|
|
end else case({ axi_awr_req , axi_wr_req, i_axi_wrlast })
|
|
3'b010:
|
|
f_axi_wburst_fifo[7:0] <= f_axi_wburst_fifo[7:0]-1;
|
|
3'b011: begin
|
|
`SLAVE_ASSUME(f_axi_wburst_fifo[7:0] == 0);
|
|
f_axi_wburst_fifo <= { 8'h0, f_axi_wburst_fifo[63:8] };
|
|
end
|
|
3'b100:
|
|
`SLAVE_ASSUME(f_axi_awr_nbursts < 8);
|
|
f_axi_wburst_fifo <= f_axi_wburst_fifo
|
|
| ((i_axi_awlen)<<(f_axi_awr_nbursts * 8));
|
|
3'b11:
|
|
f_axi_wburst_fifo <= { 8'h0, f_axi_wburst_fifo[63:8] }
|
|
| ((i_axi_awlen)<<((f_axi_awr_nbursts-1) * 8));
|
|
default:
|
|
endcase
|
|
*/
|
|
|
initial f_axi_rd_id_outstanding_count = 0;
|
|
initial f_axi_awr_id_outstanding_count = 0;
|
|
initial f_axi_wr_id_outstanding_count = 0;
|
|
always @(*)
|
|
begin
|
|
//
|
//
|
f_axi_rd_id_outstanding_count = 0;
|
// Count the number of write elements received since the last wlast
|
for(k=0; k< FIFOLN; k=k+1)
|
initial f_axi_wr_count = 0;
|
if (f_axi_rd_id_outstanding[k])
|
always @(posedge i_clk)
|
f_axi_rd_id_outstanding_count
|
if (!i_axi_reset_n)
|
= f_axi_rd_id_outstanding_count +1;
|
f_axi_wr_count <= 0;
|
//
|
else if (axi_wr_req)
|
f_axi_wr_id_outstanding_count = 0;
|
begin
|
for(k=0; k< FIFOLN; k=k+1)
|
if (i_axi_wlast)
|
if (f_axi_wr_id_outstanding[k])
|
f_axi_wr_count <= 1'b0;
|
f_axi_wr_id_outstanding_count = f_axi_wr_id_outstanding_count +1;
|
else
|
f_axi_awr_id_outstanding_count = 0;
|
f_axi_wr_count <= f_axi_wr_count + 1'b1;
|
for(k=0; k< FIFOLN; k=k+1)
|
|
if (f_axi_awr_id_outstanding[k])
|
|
f_axi_awr_id_outstanding_count = f_axi_awr_id_outstanding_count +1;
|
|
end
|
end
|
|
|
always @(*)
|
//
|
assume((!F_CHECK_IDS)||(f_axi_awr_outstanding== f_axi_awr_id_outstanding_count));
|
// Write information to the write FIFO
|
|
initial wr_wraddr = 0;
|
|
always @(posedge i_clk)
|
|
if (!i_axi_reset_n)
|
|
wr_wraddr <= 0;
|
|
else if (axi_awr_req)
|
|
wr_wraddr <= wr_wraddr + 1'b1;
|
|
|
always @(*)
|
always @(posedge i_clk)
|
assume((!F_CHECK_IDS)||(f_axi_wr_outstanding == f_axi_wr_id_outstanding_count));
|
if (axi_awr_req)
|
|
wrfifo[wr_wraddr] <= { i_axi_awlen };
|
|
|
|
//
|
|
// Read information from the write queue
|
always @(*)
|
always @(*)
|
assume((!F_CHECK_IDS)||(f_axi_rd_outstanding == f_axi_rd_id_outstanding_count));
|
wrfifo_data = wrfifo[wr_rdaddr];
|
|
|
|
assign this_wlen = wrfifo_data;
|
|
|
always @(*)
|
always @(*)
|
assume( ((f_axi_wr_id_complete)&(~f_axi_awr_id_outstanding)) == 0);
|
if ((i_axi_wvalid)&&(i_axi_wlast)&&(f_axi_awr_nbursts>0))
|
|
`SLAVE_ASSUME(i_axi_wlast == (this_wlen == f_axi_wr_count));
|
|
|
generate if (F_OPT_BURSTS)
|
// Advance the read pointer for the write FIFO
|
begin
|
initial wr_rdaddr = 0;
|
reg [(8-1):0] f_rd_pending [0:(FIFOLN-1)];
|
always @(posedge i_clk)
|
reg [(8-1):0] f_wr_pending,
|
if (!i_axi_reset_n)
|
f_rd_count, f_wr_count;
|
wr_rdaddr <= 0;
|
|
else if ((axi_wr_req)&&(i_axi_wlast))
|
|
wr_rdaddr <= wr_rdaddr + 1'b1;
|
|
|
reg r_last_rd_id_valid,
|
assign wrfifo_fill = wr_wraddr - wr_rdaddr;
|
r_last_wr_id_valid;
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Read FIFO
|
|
//
|
|
parameter NRDFIFO = 8;
|
|
parameter WRDFIFO = 9;
|
|
|
reg [(C_AXI_ID_WIDTH-1):0] r_last_wr_id, r_last_rd_id;
|
|
|
|
initial r_last_wr_id_valid = 1'b0;
|
initial f_axi_rd_count = 0;
|
initial r_last_rd_id_valid = 1'b0;
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (!i_axi_reset_n)
|
if (!i_axi_reset_n)
|
begin
|
f_axi_rd_count <= 0;
|
r_last_wr_id_valid <= 1'b0;
|
else if (axi_rd_ack)
|
r_last_rd_id_valid <= 1'b0;
|
|
f_wr_count <= 0;
|
|
f_rd_count <= 0;
|
|
end else begin
|
|
if (axi_awr_req)
|
|
begin
|
|
f_wr_pending <= i_axi_awlen+9'h1;
|
|
assume(f_wr_pending == 0);
|
|
r_last_wr_id_valid <= 1'b1;
|
|
end
|
|
|
|
if (axi_ard_req)
|
|
f_rd_pending[i_axi_arid] <= i_axi_arlen+9'h1;
|
|
|
|
|
|
if ((axi_wr_req)&&(i_axi_wlast))
|
|
begin
|
|
f_wr_count <= 0;
|
|
r_last_wr_id_valid <= 1'b0;
|
|
assume(
|
|
// Either this is the last
|
|
// of a series of requests we've
|
|
// been waiting for,
|
|
(f_wr_pending == f_wr_count - 9'h1)
|
|
// *or* the only value
|
|
// associated with an as yet
|
|
// to be counted request
|
|
||((axi_awr_req)&&(i_axi_awlen == 0)));
|
|
end else if (axi_wr_req)
|
|
f_wr_count <= f_wr_count + 1'b1;
|
|
|
|
if (axi_rd_ack)
|
|
begin
|
begin
|
if (i_axi_rlast)
|
if (i_axi_rlast)
|
r_last_rd_id_valid <= 1'b0;
|
f_axi_rd_count <= 1'b0;
|
else
|
else
|
r_last_rd_id_valid <= 1'b1;
|
f_axi_rd_count <= f_axi_rd_count + 1'b1;
|
|
|
r_last_rd_id <= i_axi_rid;
|
|
if ((axi_rd_ack)&&(r_last_rd_id_valid))
|
|
assert(i_axi_rid == r_last_rd_id);
|
|
end
|
|
|
|
if ((axi_rd_ack)&&(i_axi_rlast))
|
|
assume(f_rd_count == f_rd_pending[i_axi_rid]-9'h1);
|
|
if ((axi_rd_ack)&&(i_axi_rlast))
|
|
f_rd_count <= 0;
|
|
else if (axi_rd_ack)
|
|
f_rd_count <= f_rd_count + 1'b1;
|
|
end
|
end
|
end else begin
|
|
always @(*) begin
|
|
// Since we aren't allowing bursts, *every*
|
|
// write data and read data must always be the last
|
|
// value
|
|
assume((i_axi_wlast)||(!i_axi_wvalid));
|
|
assert((i_axi_rlast)||(!i_axi_rvalid));
|
|
|
|
assume((!i_axi_arvalid)||(i_axi_arlen==0));
|
always @(*)
|
assume((!i_axi_awvalid)||(i_axi_awlen==0));
|
`SLAVE_ASSUME(f_axi_rd_nbursts <= NRDFIFO);
|
end
|
|
|
|
always @(posedge i_clk)
|
/*
|
if (i_axi_awvalid)
|
always @(*)
|
assume(i_axi_awlen == 0);
|
if (i_axi_rvalid)
|
always @(posedge i_clk)
|
begin
|
if (i_axi_arvalid)
|
if (i_axi_rlast)
|
assume(i_axi_arlen == 0);
|
`SLAVE_ASSERT(f_axi_rdfifo[WRDFIFO-1:0] == f_axi_rd_count);
|
always @(posedge i_clk)
|
else
|
if (i_axi_wvalid)
|
`SLAVE_ASSERT(f_axi_rdfifo[WRDFIFO-1:0] < f_axi_rd_count);
|
assume(i_axi_wlast);
|
end
|
always @(posedge i_clk)
|
|
if (i_axi_rvalid)
|
always @(posedge i_clk)
|
assert(i_axi_rlast);
|
if (!i_axi_reset_n)
|
end endgenerate
|
f_axi_rdfifo <= 0;
|
|
else casez({ axi_ard_req, axi_rd_ack, i_axi_rlast })
|
|
3'b10?: f_axi_rdfifo[ f_axi_rd_nbursts*WRDFIFO +: WRDFIFO]
|
|
<= { 1'b0, i_axi_arlen };
|
|
// 3'b010: f_axi_rdfifo[ 8:0] <= f_axi_rdfifo[8:0] - 1'b1;
|
|
3'b011: f_axi_rdfifo <= { {(WRDFIFO){1'b0}},
|
|
f_axi_rdfifo[NRDFIFO*WRDFIFO-1:WRDFIFO] };
|
|
3'b111: begin
|
|
f_axi_rdfifo <= { {(WRDFIFO){1'b0}},
|
|
f_axi_rdfifo[NRDFIFO*WRDFIFO-1:WRDFIFO] };
|
|
f_axi_rdfifo[ (f_axi_rd_nbursts-1)*WRDFIFO +: WRDFIFO]
|
|
<= { 1'b0, i_axi_arlen };
|
|
end
|
|
default: begin end
|
|
endcase
|
|
|
|
always @(*)
|
|
if (f_axi_rd_nbursts < NRDFIFO)
|
|
assert(f_axi_rdfifo[NRDFIFO * WRDFIFO-1: f_axi_rd_nbursts*WRDFIFO] == 0);
|
|
|
|
always @(*)
|
|
begin
|
|
rdfifo_outstanding = 0;
|
|
for(k = 0; k < NRDFIFO; k=k+1)
|
|
begin
|
|
if (k < f_axi_rd_nbursts)
|
|
begin
|
|
rdfifo_outstanding = rdfifo_outstanding
|
|
+ f_axi_rdfifo[k * WRDFIFO +: WRDFIFO] + 1;
|
|
end
|
|
assert(f_axi_rdfifo[k*WRDFIFO+(WRDFIFO-1)] == 1'b0);
|
|
end
|
|
end
|
|
|
|
always @(posedge i_clk)
|
|
assert(rdfifo_outstanding - f_axi_rd_count
|
|
== f_axi_rd_outstanding);
|
|
*/
|
|
|
`endif
|
always @(*)
|
|
f_axi_rdfifo = 0;
|
endmodule
|
endmodule
|
|
|
No newline at end of file
|
No newline at end of file
|