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

Subversion Repositories wb2axip

[/] [wb2axip/] [trunk/] [bench/] [formal/] [faxi_slave.v] - Rev 12

Go to most recent revision | Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
// Filename: 	faxi_slave.v (Formal properties of an AXI slave)
//
// Project:	Pipelined Wishbone to AXI converter
//
// Purpose:
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program.  (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.
//
// License:	GPL, v3, as defined and found on www.gnu.org,
//		http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
`default_nettype	none
//
module faxi_slave #(
	parameter C_AXI_ID_WIDTH	= 3, // The AXI id width used for R&W
                                             // This is an int between 1-16
	parameter C_AXI_DATA_WIDTH	= 128,// Width of the AXI R&W data
	parameter C_AXI_ADDR_WIDTH	= 28,	// AXI Address width (log wordsize)
	localparam DW			= C_AXI_DATA_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_CHECK_IDS	= 1'b1	// Check ID's upon issue&return
	) (
	input				i_clk,	// System clock
	input				i_axi_reset_n,
 
// AXI write address channel signals
	input				i_axi_awready, // Slave is ready to accept
	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	[7:0]		i_axi_awlen,	// Write Burst Length
	input	wire	[2:0]		i_axi_awsize,	// Write Burst size
	input	wire	[1:0]		i_axi_awburst,	// Write Burst type
	input	wire	[0:0]		i_axi_awlock,	// Write lock type
	input	wire	[3:0]		i_axi_awcache,	// Write Cache type
	input	wire	[2:0]		i_axi_awprot,	// Write Protection type
	input	wire	[3:0]		i_axi_awqos,	// Write Quality of Svc
	input	wire			i_axi_awvalid,	// Write address valid
 
// AXI write data channel signals
	input	wire			i_axi_wready,  // Write data ready
	input	wire	[DW-1:0]	i_axi_wdata,	// Write data
	input	wire	[DW/8-1:0]	i_axi_wstrb,	// Write strobes
	input	wire			i_axi_wlast,	// Last write transaction
	input	wire			i_axi_wvalid,	// Write valid
 
// AXI write response channel signals
	input	wire [C_AXI_ID_WIDTH-1:0] i_axi_bid,	// Response ID
	input	wire [1:0]		i_axi_bresp,	// Write response
	input	wire			i_axi_bvalid,  // Write reponse valid
	input	wire			i_axi_bready,  // Response ready
 
// AXI read address channel signals
	input	wire			i_axi_arready,	// Read address ready
	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	[7:0]		i_axi_arlen,	// Read Burst Length
	input	wire	[2:0]		i_axi_arsize,	// Read Burst size
	input	wire	[1:0]		i_axi_arburst,	// Read Burst type
	input	wire	[0:0]		i_axi_arlock,	// Read lock type
	input	wire	[3:0]		i_axi_arcache,	// Read Cache type
	input	wire	[2:0]		i_axi_arprot,	// Read Protection type
	input	wire	[3:0]		i_axi_arqos,	// Read Protection type
	input	wire			i_axi_arvalid,	// Read address valid
 
// AXI read data channel signals
	input	wire [C_AXI_ID_WIDTH-1:0] i_axi_rid,     // Response ID
	input	wire [1:0]		i_axi_rresp,   // Read response
	input	wire			i_axi_rvalid,  // Read reponse valid
	input	wire [DW-1:0]		i_axi_rdata,    // Read data
	input	wire			i_axi_rlast,    // Read last
	input	wire			i_axi_rready,  // Read Response ready
	//
	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_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_awr_id_outstanding,
	output	reg [((1<<C_AXI_ID_WIDTH)-1):0]	f_axi_wr_id_outstanding
 
);
	reg [((1<<C_AXI_ID_WIDTH)-1):0]	f_axi_wr_id_complete;
 
//*****************************************************************************
// Parameter declarations
//*****************************************************************************
 
	localparam	LG_AXI_DW	= ( C_AXI_DATA_WIDTH ==   8) ? 3
					: ((C_AXI_DATA_WIDTH ==  16) ? 4
					: ((C_AXI_DATA_WIDTH ==  32) ? 5
					: ((C_AXI_DATA_WIDTH ==  64) ? 6
					: ((C_AXI_DATA_WIDTH == 128) ? 7
					: 8))));
 
	localparam	LG_WB_DW	= ( DW ==   8) ? 3
					: ((DW ==  16) ? 4
					: ((DW ==  32) ? 5
					: ((DW ==  64) ? 6
					: ((DW == 128) ? 7
					: 8))));
	localparam	LGFIFOLN = C_AXI_ID_WIDTH;
	localparam	FIFOLN = (1<<LGFIFOLN);
 
 
//*****************************************************************************
// 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	axi_rd_ack, axi_wr_ack, axi_ard_req, axi_awr_req, axi_wr_req,
		axi_rd_err, axi_wr_err;
	//
	assign	axi_ard_req = (i_axi_arvalid)&&(i_axi_arready);
	assign	axi_awr_req = (i_axi_awvalid)&&(i_axi_awready);
	assign	axi_wr_req  = (i_axi_wvalid )&&(i_axi_wready);
	//
	assign	axi_rd_ack = (i_axi_rvalid)&&(i_axi_rready);
	assign	axi_wr_ack = (i_axi_bvalid)&&(i_axi_bready);
	assign	axi_rd_err = (axi_rd_ack)&&(i_axi_rresp[1]);
	assign	axi_wr_err = (axi_wr_ack)&&(i_axi_bresp[1]);
 
	//
	// Setup
	//
	reg	f_past_valid;
	integer	k;
 
	initial	f_past_valid = 1'b0;
	always @(posedge i_clk)
		f_past_valid <= 1'b1;
	always @(*)
		if (!f_past_valid)
			assume(!i_axi_reset_n);
 
	//
	// 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
	//
	//
	////////////////////////////////////////////////////
 
	always @(posedge i_clk)
	if ((f_past_valid)&&(!$past(i_axi_reset_n)))
	begin
		assume(!i_axi_arvalid);
		assume(!i_axi_awvalid);
		assume(!i_axi_wvalid);
		assert(!i_axi_bvalid);
		assert(!i_axi_rvalid);
	end
 
	////////////////////////////////////////////////////
	//
	//
	// Stability assumptions, AXI inputs/responses
	//
	//
	////////////////////////////////////////////////////
 
	// Assume any response from the bus will not change prior to that
	// response being accepted
	always @(posedge i_clk)
	if (f_past_valid)
	begin
		if ((f_past_valid)&&($past(i_axi_rvalid))&&(!$past(i_axi_rready)))
		begin
			assert(i_axi_rid    == $past(i_axi_rid));
			assert(i_axi_rresp  == $past(i_axi_rresp));
			assert(i_axi_rdata  == $past(i_axi_rdata));
			assert(i_axi_rlast  == $past(i_axi_rlast));
		end
 
		if ((f_past_valid)&&($past(i_axi_bvalid))&&(!$past(i_axi_bready)))
		begin
			assert(i_axi_bid    == $past(i_axi_bid));
			assert(i_axi_bresp  == $past(i_axi_bresp));
		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
	always @(posedge i_clk)
	if ((f_past_valid)&&($past(i_axi_arvalid))&&(!$past(i_axi_arready)))
	begin
		assume(i_axi_arvalid);
		assume($stable(i_axi_arid));
		assume($stable(i_axi_araddr));
		assume($stable(i_axi_arlen));
		assume($stable(i_axi_arsize));
		assume($stable(i_axi_arburst));
		assume($stable(i_axi_arlock));
		assume($stable(i_axi_arcache));
		assume($stable(i_axi_arprot));
		assume($stable(i_axi_arqos));
		assume($stable(i_axi_arvalid));
	end
 
	// If valid, but not ready, on any channel is true, nothing changes
	// until valid && ready
	always @(posedge i_clk)
	if ((f_past_valid)&&($past(i_axi_awvalid))&&(!$past(i_axi_awready)))
	begin
		assume($stable(i_axi_awid));
		assume($stable(i_axi_awaddr));
		assume($stable(i_axi_awlen));
		assume($stable(i_axi_awsize));
		assume($stable(i_axi_awburst));
		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
 
	always @(posedge i_clk)
	if ((f_past_valid)&&($past(i_axi_wvalid))&&(!$past(i_axi_wready)))
	begin
		// AXI write data channel signals
		assume($stable(i_axi_wdata));
		assume($stable(i_axi_wstrb));
		assume($stable(i_axi_wlast));
		assume($stable(i_axi_wvalid));
	end
 
	//
	//
 
	///////////////////////////////////////////////////////////////////
	//
	//
	// Insist upon a maximum delay before a request is accepted
	//
	//
	///////////////////////////////////////////////////////////////////
 
	//
	// AXI write address channel
	//
	//
	reg	[(C_AXI_ID_WIDTH):0]	f_axi_awstall;
	initial	f_axi_awstall = 0;
	always @(posedge i_clk)
		if ((!i_axi_reset_n)||(!i_axi_awvalid)||(i_axi_awready))
			f_axi_awstall <= 0;
		else
			f_axi_awstall <= f_axi_awstall + 1'b1;
	always @(*)
		assert((F_AXI_MAXSTALL==0)||(f_axi_awstall < F_AXI_MAXSTALL));
 
	//
	// 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) assume(|i_axi_wstrb);
 
	reg	[(C_AXI_ID_WIDTH):0]	f_axi_wstall;
	initial	f_axi_wstall = 0;
	always @(posedge i_clk)
		if ((!i_axi_reset_n)||(!i_axi_wvalid)||(i_axi_wready))
			f_axi_wstall <= 0;
		else
			f_axi_wstall <= f_axi_wstall + 1'b1;
	always @(*)
		assert((F_AXI_MAXSTALL==0)||(f_axi_wstall < F_AXI_MAXSTALL));
 
 
	//
	// AXI read address channel
	//
	//
	reg	[(C_AXI_ID_WIDTH):0]	f_axi_arstall;
	initial	f_axi_arstall = 0;
	always @(posedge i_clk)
		if ((!i_axi_reset_n)||(!i_axi_arvalid)||(i_axi_arready))
			f_axi_arstall <= 0;
		else
			f_axi_arstall <= f_axi_arstall + 1'b1;
	always @(*)
		assert((F_AXI_MAXSTALL==0)||(f_axi_arstall < F_AXI_MAXSTALL));
 
 
	////////////////////////////////////////////////////////////////////////
	//
	//
	// Count outstanding transactions.  With these measures, we count
	// once per any burst.
	//
	//
	////////////////////////////////////////////////////////////////////////
	initial	f_axi_awr_outstanding = 0;
	always @(posedge i_clk)
		if (!i_axi_reset_n)
			f_axi_awr_outstanding <= 0;
		else case({ (axi_awr_req), (axi_wr_ack) })
			2'b10: f_axi_awr_outstanding <= f_axi_awr_outstanding + 1'b1;
			2'b01: f_axi_awr_outstanding <= f_axi_awr_outstanding - 1'b1;
			default: begin end
		endcase
 
	initial	f_axi_wr_outstanding = 0;
	always @(posedge i_clk)
		if (!i_axi_reset_n)
			f_axi_wr_outstanding <= 0;
		else case({ (axi_wr_req)&&(i_axi_wlast), (axi_wr_ack) })
		2'b01: f_axi_wr_outstanding <= f_axi_wr_outstanding - 1'b1;
		2'b10: f_axi_wr_outstanding <= f_axi_wr_outstanding + 1'b1;
		endcase
 
	initial	f_axi_rd_outstanding = 0;
	always @(posedge i_clk)
		if (!i_axi_reset_n)
			f_axi_rd_outstanding <= 0;
		else case({ (axi_ard_req), (axi_rd_ack)&&(i_axi_rlast) })
		2'b01: f_axi_rd_outstanding <= f_axi_rd_outstanding - 1'b1;
		2'b10: f_axi_rd_outstanding <= f_axi_rd_outstanding + 1'b1;
		endcase
 
	// Do not let the number of outstanding requests overflow
	always @(posedge i_clk)
		assume(f_axi_wr_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
	always @(posedge i_clk)
		assume(f_axi_awr_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
	always @(posedge i_clk)
		assume(f_axi_rd_outstanding < {(C_AXI_ID_WIDTH){1'b1}});
 
	////////////////////////////////////////////////////////////////////////
	//
	//
	// Insist that all responses are returned in less than a maximum delay
	// In this case, we count responses within a burst, rather than entire
	// bursts.
	//
	//
	////////////////////////////////////////////////////////////////////////
 
	reg	[(C_AXI_ID_WIDTH):0]	f_axi_wr_ack_delay,
					f_axi_awr_ack_delay,
					f_axi_rd_ack_delay;
 
	initial	f_axi_rd_ack_delay = 0;
	always @(posedge i_clk)
		if ((!i_axi_reset_n)||(axi_rd_ack))
			f_axi_rd_ack_delay <= 0;
		else if (f_axi_rd_outstanding > 0)
			f_axi_rd_ack_delay <= f_axi_rd_ack_delay + 1'b1;
 
	initial	f_axi_wr_ack_delay = 0;
	always @(posedge i_clk)
		if ((!i_axi_reset_n)||(axi_wr_ack))
			f_axi_wr_ack_delay <= 0;
		else if (f_axi_wr_outstanding > 0)
			f_axi_wr_ack_delay <= f_axi_wr_ack_delay + 1'b1;
 
	initial	f_axi_awr_ack_delay = 0;
	always @(posedge i_clk)
		if ((!i_axi_reset_n)||(axi_wr_ack))
			f_axi_awr_ack_delay <= 0;
		else if (f_axi_awr_outstanding > 0)
			f_axi_awr_ack_delay <= f_axi_awr_ack_delay + 1'b1;
 
	always @(posedge i_clk)
		assert((F_AXI_MAXDELAY==0)||(f_axi_rd_ack_delay < F_AXI_MAXDELAY));
 
	always @(posedge i_clk)
		assert((F_AXI_MAXDELAY==0)||(f_axi_wr_ack_delay < F_AXI_MAXDELAY));
 
	always @(posedge i_clk)
		assert((F_AXI_MAXDELAY==0)||(f_axi_awr_ack_delay < F_AXI_MAXDELAY));
 
	////////////////////////////////////////////////////////////////////////
	//
	//
	// Assume all acknowledgements must follow requests
	//
	// The outstanding count is a count of bursts, but the acknowledgements
	// we are looking for are individual.  Hence, there should be no
	// individual acknowledgements coming back if there's no outstanding
	// burst.
	//
	//
	////////////////////////////////////////////////////////////////////////
 
	//
	// AXI write response channel
	//
	always @(posedge i_clk)
		if ((!axi_awr_req)&&(axi_wr_ack))
			assert(f_axi_awr_outstanding > 0);
	always @(posedge i_clk)
		if ((!axi_wr_req)&&(axi_wr_ack))
			assert(f_axi_wr_outstanding > 0);
 
	//
	// AXI read data channel signals
	//
	initial	f_axi_rd_outstanding = 0;
	always @(posedge i_clk)
		if ((!axi_ard_req)&&(axi_rd_ack))
			assert(f_axi_rd_outstanding > 0);
 
	///////////////////////////////////////////////////////////////////
	//
	//
	// 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
		if (axi_ard_req)
		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
		if (axi_wr_ack)
		begin
			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
		if (axi_rd_ack)
		begin
			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)
				f_axi_rd_id_outstanding[i_axi_rid] <= 1'b0;
		end
	end
 
 
	reg	[LGFIFOLN:0]	f_axi_rd_id_outstanding_count,
				f_axi_awr_id_outstanding_count,
				f_axi_wr_id_outstanding_count;
 
	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;
		for(k=0; k< FIFOLN; k=k+1)
			if (f_axi_rd_id_outstanding[k])
				f_axi_rd_id_outstanding_count
					= f_axi_rd_id_outstanding_count +1;
		//
		f_axi_wr_id_outstanding_count = 0;
		for(k=0; k< FIFOLN; k=k+1)
			if (f_axi_wr_id_outstanding[k])
				f_axi_wr_id_outstanding_count = f_axi_wr_id_outstanding_count +1;
		f_axi_awr_id_outstanding_count = 0;
		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
 
	always @(*)
		assume((!F_CHECK_IDS)||(f_axi_awr_outstanding== f_axi_awr_id_outstanding_count));
 
	always @(*)
		assume((!F_CHECK_IDS)||(f_axi_wr_outstanding == f_axi_wr_id_outstanding_count));
 
	always @(*)
		assume((!F_CHECK_IDS)||(f_axi_rd_outstanding == f_axi_rd_id_outstanding_count));
 
	always @(*)
		assume( ((f_axi_wr_id_complete)&(~f_axi_awr_id_outstanding)) == 0);
 
	generate if (F_OPT_BURSTS)
	begin
		reg	[(8-1):0]	f_rd_pending	[0:(FIFOLN-1)];
		reg	[(8-1):0]	f_wr_pending,
					f_rd_count, f_wr_count;
 
		reg	r_last_rd_id_valid,
			r_last_wr_id_valid;
 
		reg	[(C_AXI_ID_WIDTH-1):0]	r_last_wr_id, r_last_rd_id;
 
		initial	r_last_wr_id_valid = 1'b0;
		initial	r_last_rd_id_valid = 1'b0;
		always @(posedge i_clk)
		if (!i_axi_reset_n)
		begin
			r_last_wr_id_valid <= 1'b0;
			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
				if (i_axi_rlast)
					r_last_rd_id_valid <= 1'b0;
				else
					r_last_rd_id_valid <= 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 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));
			assume((!i_axi_awvalid)||(i_axi_awlen==0));
		end
 
		always @(posedge i_clk)
			if (i_axi_awvalid)
				assume(i_axi_awlen == 0);
		always @(posedge i_clk)
			if (i_axi_arvalid)
				assume(i_axi_arlen == 0);
		always @(posedge i_clk)
			if (i_axi_wvalid)
				assume(i_axi_wlast);
		always @(posedge i_clk)
			if (i_axi_rvalid)
				assert(i_axi_rlast);
	end endgenerate
 
`endif
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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