summaryrefslogtreecommitdiff
path: root/rtl/wb2axip/axilsafety.v
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/wb2axip/axilsafety.v')
-rw-r--r--rtl/wb2axip/axilsafety.v1449
1 files changed, 1449 insertions, 0 deletions
diff --git a/rtl/wb2axip/axilsafety.v b/rtl/wb2axip/axilsafety.v
new file mode 100644
index 0000000..ff8b391
--- /dev/null
+++ b/rtl/wb2axip/axilsafety.v
@@ -0,0 +1,1449 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Filename: axilsafety.v
+// {{{
+// Project: WB2AXIPSP: bus bridges and other odds and ends
+//
+// Purpose: A AXI-Lite bus fault isolator. This core will isolate any
+// downstream AXI-liite slave faults from the upstream channel.
+// It sits as a bump in the wire between upstream and downstream channels,
+// and so it will consume two clocks--slowing down the slave, but
+// potentially allowing developer to recover in case of a fault.
+//
+// This core is configured by a couple parameters, which are key to its
+// functionality.
+//
+// OPT_TIMEOUT Set this to a number to be roughly the longest time
+// period you expect the slave to stall the bus, or likewise
+// the longest time period you expect it to wait for a response.
+// If the slave takes longer for either task, a fault will be
+// detected and reported.
+//
+// OPT_SELF_RESET If set, this will send a reset signal to the downstream
+// core so that you can attempt to restart it without reloading
+// the FPGA. If set, the o_reset signal will be used to reset
+// the downstream core.
+//
+// A second key feature of this core are the outgoing fault indicators,
+// o_write_fault and o_read_fault. If either signal is ever raised, the
+// slave has (somehow) violated protocol on either the write or the
+// read channels respectively. Such a violation may (or may not) return an
+// error upstream. For example, if the slave returns a response
+// following no requests from the master, then no error will be returned
+// up stream (doing so would be a protocol violation), but a fault will
+// still be detected. Use this line to trigger any internal logic
+// analyzers.
+//
+// Creator: Dan Gisselquist, Ph.D.
+// Gisselquist Technology, LLC
+//
+////////////////////////////////////////////////////////////////////////////////
+// }}}
+// Copyright (C) 2020-2024, Gisselquist Technology, LLC
+// {{{
+// This file is part of the WB2AXIP project.
+//
+// The WB2AXIP project contains free software and gateware, licensed under the
+// Apache License, Version 2.0 (the "License"). You may not use this project,
+// or this file, except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+//
+`default_nettype none
+// }}}
+module axilsafety #(
+ // {{{
+ parameter C_AXI_ADDR_WIDTH = 28,
+ parameter C_AXI_DATA_WIDTH = 32,
+ parameter OPT_TIMEOUT = 12,
+ parameter MAX_DEPTH = (OPT_TIMEOUT),
+ localparam AW = C_AXI_ADDR_WIDTH,
+ localparam DW = C_AXI_DATA_WIDTH,
+ localparam LGTIMEOUT = $clog2(OPT_TIMEOUT+1),
+ localparam LGDEPTH = $clog2(MAX_DEPTH+1),
+ parameter [0:0] OPT_SELF_RESET = 1'b1,
+ parameter OPT_MIN_RESET = 16
+`ifdef FORMAL
+ , parameter [0:0] F_OPT_WRITES = 1'b1,
+ parameter [0:0] F_OPT_READS = 1'b1,
+ parameter [0:0] F_OPT_FAULTLESS = 1'b1
+`endif
+ // }}}
+ ) (
+ // {{{
+ output reg o_write_fault,
+ output reg o_read_fault,
+ //
+ input wire S_AXI_ACLK,
+ input wire S_AXI_ARESETN,
+ output reg M_AXI_ARESETN,
+ //
+ input wire S_AXI_AWVALID,
+ output reg S_AXI_AWREADY,
+ input wire [AW-1:0] S_AXI_AWADDR,
+ input wire [2:0] S_AXI_AWPROT,
+ //
+ input wire S_AXI_WVALID,
+ output reg S_AXI_WREADY,
+ input wire [DW-1:0] S_AXI_WDATA,
+ input wire [DW/8-1:0] S_AXI_WSTRB,
+ //
+ output reg S_AXI_BVALID,
+ input wire S_AXI_BREADY,
+ output reg [1:0] S_AXI_BRESP,
+ //
+ input wire S_AXI_ARVALID,
+ output reg S_AXI_ARREADY,
+ input wire [AW-1:0] S_AXI_ARADDR,
+ input wire [2:0] S_AXI_ARPROT,
+ //
+ output reg S_AXI_RVALID,
+ input wire S_AXI_RREADY,
+ output reg [DW-1:0] S_AXI_RDATA,
+ output reg [1:0] S_AXI_RRESP,
+ //
+ //
+ //
+ output reg M_AXI_AWVALID,
+ input wire M_AXI_AWREADY,
+ output reg [AW-1:0] M_AXI_AWADDR,
+ output reg [2:0] M_AXI_AWPROT,
+ //
+ output reg M_AXI_WVALID,
+ input wire M_AXI_WREADY,
+ output reg [DW-1:0] M_AXI_WDATA,
+ output reg [DW/8-1:0] M_AXI_WSTRB,
+ //
+ input wire M_AXI_BVALID,
+ output wire M_AXI_BREADY,
+ input wire [1:0] M_AXI_BRESP,
+ //
+ output reg M_AXI_ARVALID,
+ input wire M_AXI_ARREADY,
+ output reg [AW-1:0] M_AXI_ARADDR,
+ output reg [2:0] M_AXI_ARPROT,
+ //
+ input wire M_AXI_RVALID,
+ output wire M_AXI_RREADY,
+ input wire [DW-1:0] M_AXI_RDATA,
+ input wire [1:0] M_AXI_RRESP
+ // }}}
+ );
+
+ // localparam, wire, and register declarations
+ // {{{
+ localparam OPT_LOWPOWER = 1'b0;
+ localparam OKAY = 2'b00,
+ EXOKAY = 2'b01,
+ SLVERR = 2'b10;
+
+ reg [LGDEPTH-1:0] aw_count, w_count, r_count;
+ reg aw_zero, w_zero, r_zero,
+ aw_full, w_full, r_full,
+ aw_w_greater, w_aw_greater;
+ reg [LGDEPTH-1:0] downstream_aw_count, downstream_w_count, downstream_r_count;
+ reg downstream_aw_zero, downstream_w_zero, downstream_r_zero;
+ // downstream_aw_w_greater, downstream_w_aw_greater;
+
+ wire awskd_valid;
+ wire [2:0] awskd_prot;
+ wire [AW-1:0] awskd_addr;
+ reg awskd_ready;
+
+ wire wskd_valid;
+ wire [DW-1:0] wskd_data;
+ wire [DW/8-1:0] wskd_strb;
+ reg wskd_ready;
+
+ wire bskd_valid;
+ wire [1:0] bskd_resp;
+ reg bskd_ready;
+
+ reg last_bvalid;
+ reg [1:0] last_bdata;
+ reg last_bchanged;
+
+ wire arskd_valid;
+ wire [2:0] arskd_prot;
+ wire [AW-1:0] arskd_addr;
+ reg arskd_ready;
+
+ reg last_rvalid;
+ reg [DW+1:0] last_rdata;
+ reg last_rchanged;
+
+ wire rskd_valid;
+ wire [1:0] rskd_resp;
+ wire [DW-1:0] rskd_data;
+ reg rskd_ready;
+
+ reg [LGTIMEOUT-1:0] aw_stall_counter, w_stall_counter,
+ r_stall_counter, w_ack_timer, r_ack_timer;
+ reg aw_stall_limit, w_stall_limit, r_stall_limit,
+ w_ack_limit, r_ack_limit;
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Write signaling
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ //
+ // Write address channel
+ // {{{
+
+ skidbuffer #(.DW(AW+3)
+ // {{{
+`ifdef FORMAL
+ , .OPT_PASSTHROUGH(1'b1)
+`endif
+ // }}}
+ ) awskd(S_AXI_ACLK, !S_AXI_ARESETN,
+ // {{{
+ S_AXI_AWVALID, S_AXI_AWREADY, { S_AXI_AWPROT, S_AXI_AWADDR },
+ awskd_valid, awskd_ready, { awskd_prot, awskd_addr});
+ // }}}
+
+ // awskd_ready
+ // {{{
+ // awskd_ready is the critical piece here, since it determines when
+ // we accept a packet from the skid buffer.
+ //
+ always @(*)
+ if (!M_AXI_ARESETN || o_write_fault)
+ // On any fault, we'll always accept a request (and return an
+ // error). We always accept a value if there are already
+ // more writes than write addresses accepted.
+ awskd_ready = (w_aw_greater)
+ ||((aw_zero)&&(!S_AXI_BVALID || S_AXI_BREADY));
+ else
+ // Otherwise, we accept if ever our counters aren't about to
+ // overflow, and there's a place downstream to accept it
+ awskd_ready = (!M_AXI_AWVALID || M_AXI_AWREADY)&& (!aw_full);
+ // }}}
+
+ // M_AXI_AWVALID
+ // {{{
+ initial M_AXI_AWVALID = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN)
+ M_AXI_AWVALID <= 1'b0;
+ else if (!M_AXI_AWVALID || M_AXI_AWREADY)
+ M_AXI_AWVALID <= awskd_valid && awskd_ready && !o_write_fault;
+ // }}}
+
+ // M_AXI_AWADDR, M_AXI_AWPROT
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (OPT_LOWPOWER && (!M_AXI_ARESETN || o_write_fault))
+ begin
+ M_AXI_AWADDR <= 0;
+ M_AXI_AWPROT <= 0;
+ end else if (!M_AXI_AWVALID || M_AXI_AWREADY)
+ begin
+ M_AXI_AWADDR <= awskd_addr;
+ M_AXI_AWPROT <= awskd_prot;
+ end
+ // }}}
+ // }}}
+
+ //
+ // Write data channel
+ // {{{
+
+ skidbuffer #(.DW(DW+DW/8)
+ // {{{
+`ifdef FORMAL
+ , .OPT_PASSTHROUGH(1'b1)
+`endif
+ // }}}
+ ) wskd(S_AXI_ACLK, !S_AXI_ARESETN,
+ // {{{
+ S_AXI_WVALID, S_AXI_WREADY, { S_AXI_WDATA, S_AXI_WSTRB },
+ wskd_valid, wskd_ready, { wskd_data, wskd_strb});
+ // }}}
+
+ // wskd_ready
+ // {{{
+ // As with awskd_ready, this logic is the critical key.
+ //
+ always @(*)
+ if (!M_AXI_ARESETN || o_write_fault)
+ wskd_ready = (aw_w_greater)
+ || ((w_zero)&&(!S_AXI_BVALID || S_AXI_BREADY));
+ else
+ wskd_ready = (!M_AXI_WVALID || M_AXI_WREADY) && (!w_full);
+ // }}}
+
+ // M_AXI_WVALID
+ // {{{
+ initial M_AXI_WVALID = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN)
+ M_AXI_WVALID <= 1'b0;
+ else if (!M_AXI_WVALID || M_AXI_WREADY)
+ M_AXI_WVALID <= wskd_valid && wskd_ready && !o_write_fault;
+ // }}}
+
+ // M_AXI_WDATA, M_AXI_WSTRB
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (OPT_LOWPOWER && (!M_AXI_ARESETN || o_write_fault))
+ begin
+ M_AXI_WDATA <= 0;
+ M_AXI_WSTRB <= 0;
+ end else if (!M_AXI_WVALID || M_AXI_WREADY)
+ begin
+ M_AXI_WDATA <= wskd_data;
+ M_AXI_WSTRB <= (o_write_fault) ? 0 : wskd_strb;
+ end
+ // }}}
+ // }}}
+
+ //
+ // Write return channel
+ // {{{
+
+ // bskd_valid, M_AXI_BREADY, bskd_resp
+ // {{{
+`ifdef FORMAL
+ assign bskd_valid = M_AXI_BVALID;
+ assign M_AXI_BREADY= bskd_ready;
+ assign bskd_resp = M_AXI_BRESP;
+`else
+ skidbuffer #(.DW(2)
+ ) bskd(S_AXI_ACLK, !S_AXI_ARESETN || !M_AXI_ARESETN,
+ M_AXI_BVALID, M_AXI_BREADY, M_AXI_BRESP,
+ bskd_valid, bskd_ready, bskd_resp);
+`endif
+ // }}}
+
+ // bskd_ready
+ // {{{
+ always @(*)
+ if (o_write_fault)
+ bskd_ready = 1'b1;
+ else
+ bskd_ready = (!S_AXI_BVALID || S_AXI_BREADY);
+ // }}}
+
+ // S_AXI_BVALID
+ // {{{
+ initial S_AXI_BVALID = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ S_AXI_BVALID <= 1'b0;
+ else if (!S_AXI_BVALID || S_AXI_BREADY)
+ begin
+ if (o_write_fault || !M_AXI_ARESETN)
+ S_AXI_BVALID <= (!S_AXI_BVALID&&(!aw_zero)&&(!w_zero));
+ else
+ S_AXI_BVALID <= (!downstream_aw_zero)
+ &&(!downstream_w_zero)&&(bskd_valid);
+ end
+ // }}}
+
+ // last_bvalid
+ // {{{
+ initial last_bvalid = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!M_AXI_ARESETN || o_write_fault)
+ last_bvalid <= 1'b0;
+ else
+ last_bvalid <= (M_AXI_BVALID && !M_AXI_BREADY);
+ // }}}
+
+ // last_bdata
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (M_AXI_BVALID)
+ last_bdata <= M_AXI_BRESP;
+ // }}}
+
+ // last_bchanged
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_write_fault)
+ last_bchanged <= 1'b0;
+ else
+ last_bchanged <= (last_bvalid && (!M_AXI_BVALID
+ || last_bdata != M_AXI_BRESP));
+ // }}}
+
+ // S_AXI_BRESP
+ // {{{
+ initial S_AXI_BRESP = OKAY;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_BVALID || S_AXI_BREADY)
+ begin
+ if (o_write_fault)
+ S_AXI_BRESP <= SLVERR;
+ else if (bskd_resp == EXOKAY)
+ S_AXI_BRESP <= SLVERR;
+ else
+ S_AXI_BRESP <= bskd_resp;
+ end
+ // }}}
+ // }}}
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Read signaling
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ //
+ // Read address channel
+ // {{{
+
+ skidbuffer #(.DW(AW+3)
+ // {{{
+`ifdef FORMAL
+ , .OPT_PASSTHROUGH(1'b1)
+`endif
+ // }}}
+ ) arskd(S_AXI_ACLK, !S_AXI_ARESETN,
+ // {{{
+ S_AXI_ARVALID, S_AXI_ARREADY, { S_AXI_ARPROT, S_AXI_ARADDR },
+ arskd_valid, arskd_ready, { arskd_prot, arskd_addr });
+ // }}}
+
+ // arskd_ready
+ // {{{
+ always @(*)
+ if (!M_AXI_ARESETN || o_read_fault)
+ arskd_ready =((r_zero)&&(!S_AXI_RVALID || S_AXI_RREADY));
+ else
+ arskd_ready = (!M_AXI_ARVALID || M_AXI_ARREADY) && (!r_full);
+ // }}}
+
+ // M_AXI_ARVALID
+ // {{{
+ initial M_AXI_ARVALID = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN)
+ M_AXI_ARVALID <= 1'b0;
+ else if (!M_AXI_ARVALID || M_AXI_ARREADY)
+ M_AXI_ARVALID <= arskd_valid && arskd_ready && !o_read_fault;
+ // }}}
+
+ // M_AXI_ARADDR, M_AXI_ARPROT
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (OPT_LOWPOWER && (!M_AXI_ARESETN || o_read_fault))
+ begin
+ M_AXI_ARADDR <= 0;
+ M_AXI_ARPROT <= 0;
+ end else if (!M_AXI_ARVALID || M_AXI_ARREADY)
+ begin
+ M_AXI_ARADDR <= arskd_addr;
+ M_AXI_ARPROT <= arskd_prot;
+ end
+ // }}}
+ // }}}
+
+ //
+ // Read data channel
+ // {{{
+
+ // rskd_valid, rskd_resp, rskd_data skid buffer
+ // {{{
+`ifdef FORMAL
+ assign rskd_valid = M_AXI_RVALID;
+ assign M_AXI_RREADY = rskd_ready;
+ assign { rskd_resp, rskd_data } = { M_AXI_RRESP, M_AXI_RDATA };
+`else
+ skidbuffer #(.DW(DW+2)
+ ) rskd(S_AXI_ACLK, !S_AXI_ARESETN || !M_AXI_ARESETN,
+ M_AXI_RVALID, M_AXI_RREADY, { M_AXI_RRESP, M_AXI_RDATA },
+ rskd_valid, rskd_ready, { rskd_resp, rskd_data });
+`endif
+ // ?}}}
+
+ // rskd_ready
+ // {{{
+ always @(*)
+ if (o_read_fault)
+ rskd_ready = 1;
+ else
+ rskd_ready = (!S_AXI_RVALID || S_AXI_RREADY);
+ // }}}
+
+ // S_AXI_RVALID
+ // {{{
+ initial S_AXI_RVALID = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ S_AXI_RVALID <= 1'b0;
+ else if (!S_AXI_RVALID || S_AXI_RREADY)
+ begin
+ if (o_read_fault || !M_AXI_ARESETN)
+ S_AXI_RVALID <= (!S_AXI_RVALID && !r_zero)
+ || (arskd_valid && arskd_ready);
+ else
+ S_AXI_RVALID <= (!downstream_r_zero)&&(rskd_valid);
+ end
+ // }}}
+
+ // S_AXI_RDATA, S_AXI_RRESP
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_RVALID || S_AXI_RREADY)
+ begin
+ if (o_read_fault || !M_AXI_ARESETN)
+ S_AXI_RDATA <= 0;
+ else
+ S_AXI_RDATA <= rskd_data;
+
+ S_AXI_RRESP <= OKAY;
+ if (o_read_fault || rskd_resp == EXOKAY || !M_AXI_ARESETN)
+ S_AXI_RRESP <= SLVERR;
+ else if (!downstream_r_zero)
+ S_AXI_RRESP <= rskd_resp;
+ end
+ // }}}
+
+ // last_rvalid
+ // {{{
+ initial last_rvalid = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_read_fault)
+ last_rvalid <= 1'b0;
+ else
+ last_rvalid <= (M_AXI_RVALID && !M_AXI_RREADY);
+ // }}}
+
+ // last_rdata
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (M_AXI_RVALID)
+ last_rdata <= { M_AXI_RRESP, M_AXI_RDATA };
+ // }}}
+
+ // last_rchanged
+ // {{{
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_read_fault)
+ last_rchanged <= 1'b0;
+ else
+ last_rchanged <= (last_rvalid && (!M_AXI_RVALID
+ || last_rdata != { M_AXI_RRESP, M_AXI_RDATA }));
+ // }}}
+ // }}}
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Usage counters
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ //
+ // Write address channel
+ // {{{
+
+ initial aw_count = 0;
+ initial aw_zero = 1;
+ initial aw_full = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ begin
+ aw_count <= 0;
+ aw_zero <= 1;
+ aw_full <= 0;
+ end else case({(awskd_valid && awskd_ready),S_AXI_BVALID&&S_AXI_BREADY})
+ 2'b10: begin
+ aw_count <= aw_count + 1;
+ aw_zero <= 0;
+ aw_full <= (aw_count == { {(LGDEPTH-1){1'b1}}, 1'b0 });
+ end
+ 2'b01: begin
+ aw_count <= aw_count - 1;
+ aw_zero <= (aw_count <= 1);
+ aw_full <= 0;
+ end
+ default: begin end
+ endcase
+ // }}}
+
+ //
+ // Write data channel
+ // {{{
+ initial w_count = 0;
+ initial w_zero = 1;
+ initial w_full = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ begin
+ w_count <= 0;
+ w_zero <= 1;
+ w_full <= 0;
+ end else case({(wskd_valid && wskd_ready), S_AXI_BVALID&& S_AXI_BREADY})
+ 2'b10: begin
+ w_count <= w_count + 1;
+ w_zero <= 0;
+ w_full <= (w_count == { {(LGDEPTH-1){1'b1}}, 1'b0 });
+ end
+ 2'b01: begin
+ w_count <= w_count - 1;
+ w_zero <= (w_count <= 1);
+ w_full <= 1'b0;
+ end
+ default: begin end
+ endcase
+ // }}}
+
+ // aw_w_greater, w_aw_greater
+ // {{{
+ initial aw_w_greater = 0;
+ initial w_aw_greater = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ begin
+ aw_w_greater <= 0;
+ w_aw_greater <= 0;
+ end else case({(awskd_valid && awskd_ready),
+ (wskd_valid && wskd_ready)})
+ 2'b10: begin
+ aw_w_greater <= (aw_count + 1 > w_count);
+ w_aw_greater <= ( w_count > aw_count + 1);
+ end
+ 2'b01: begin
+ aw_w_greater <= (aw_count > w_count + 1);
+ w_aw_greater <= ( w_count + 1 > aw_count);
+ end
+ default: begin end
+ endcase
+ // }}}
+ //
+ // Read channel
+ // {{{
+
+ // r_count, r_zero, r_full
+ initial r_count = 0;
+ initial r_zero = 1;
+ initial r_full = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ begin
+ r_count <= 0;
+ r_zero <= 1;
+ r_full <= 0;
+ end else case({(arskd_valid&&arskd_ready), S_AXI_RVALID&&S_AXI_RREADY})
+ 2'b10: begin
+ r_count <= r_count + 1;
+ r_zero <= 0;
+ r_full <= (r_count == { {(LGDEPTH-1){1'b1}}, 1'b0 });
+ end
+ 2'b01: begin
+ r_count <= r_count - 1;
+ r_zero <= (r_count <= 1);
+ r_full <= 0;
+ end
+ default: begin end
+ endcase
+ // }}}
+
+ //
+ // Downstream write address channel
+ // {{{
+
+ initial downstream_aw_count = 0;
+ initial downstream_aw_zero = 1;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_write_fault)
+ begin
+ downstream_aw_count <= 0;
+ downstream_aw_zero <= 1;
+ end else case({(M_AXI_AWVALID && M_AXI_AWREADY), M_AXI_BVALID && M_AXI_BREADY})
+ 2'b10: begin
+ downstream_aw_count <= downstream_aw_count + 1;
+ downstream_aw_zero <= 0;
+ end
+ 2'b01: begin
+ downstream_aw_count <= downstream_aw_count - 1;
+ downstream_aw_zero <= (downstream_aw_count <= 1);
+ end
+ default: begin end
+ endcase
+ // }}}
+
+ //
+ // Downstream write data channel
+ // {{{
+ initial downstream_w_count = 0;
+ initial downstream_w_zero = 1;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_write_fault)
+ begin
+ downstream_w_count <= 0;
+ downstream_w_zero <= 1;
+ end else case({(M_AXI_WVALID && M_AXI_WREADY), M_AXI_BVALID && M_AXI_BREADY})
+ 2'b10: begin
+ downstream_w_count <= downstream_w_count + 1;
+ downstream_w_zero <= 0;
+ end
+ 2'b01: begin
+ downstream_w_count <= downstream_w_count - 1;
+ downstream_w_zero <= (downstream_w_count <= 1);
+ end
+ default: begin end
+ endcase
+ // }}}
+
+ //
+ // Downstream read channel
+ // {{{
+
+ initial downstream_r_count = 0;
+ initial downstream_r_zero = 1;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_read_fault)
+ begin
+ downstream_r_count <= 0;
+ downstream_r_zero <= 1;
+ end else case({M_AXI_ARVALID && M_AXI_ARREADY, M_AXI_RVALID && M_AXI_RREADY})
+ 2'b10: begin
+ downstream_r_count <= downstream_r_count + 1;
+ downstream_r_zero <= 0;
+ end
+ 2'b01: begin
+ downstream_r_count <= downstream_r_count - 1;
+ downstream_r_zero <= (downstream_r_count <= 1);
+ end
+ default: begin end
+ endcase
+ // }}}
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Timeout checking
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ // The key piece here is that we define the timeout depending upon
+ // what happens (or doesn't happen) *DOWNSTREAM*. These timeouts
+ // will need to propagate upstream before taking place.
+
+ //
+ // Write address stall counter
+ // {{{
+ initial aw_stall_counter = 0;
+ initial aw_stall_limit = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || o_write_fault || !M_AXI_ARESETN)
+ begin
+ aw_stall_counter <= 0;
+ aw_stall_limit <= 0;
+ end else if (!M_AXI_AWVALID || M_AXI_AWREADY || M_AXI_BVALID)
+ begin
+ aw_stall_counter <= 0;
+ aw_stall_limit <= 0;
+ end else if (aw_w_greater && !M_AXI_WVALID)
+ begin
+ aw_stall_counter <= 0;
+ aw_stall_limit <= 0;
+ end else // if (!S_AXI_BVALID || S_AXI_BREADY)
+ begin
+ aw_stall_counter <= aw_stall_counter + 1;
+ aw_stall_limit <= (aw_stall_counter+1 >= OPT_TIMEOUT);
+ end
+ // }}}
+
+ //
+ // Write data stall counter
+ // {{{
+ initial w_stall_counter = 0;
+ initial w_stall_limit = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_write_fault)
+ begin
+ w_stall_counter <= 0;
+ w_stall_limit <= 0;
+ end else if (!M_AXI_WVALID || M_AXI_WREADY || M_AXI_BVALID)
+ begin
+ w_stall_counter <= 0;
+ w_stall_limit <= 0;
+ end else if (w_aw_greater && !M_AXI_AWVALID)
+ begin
+ w_stall_counter <= 0;
+ w_stall_limit <= 0;
+ end else // if (!M_AXI_BVALID || M_AXI_BREADY)
+ begin
+ w_stall_counter <= w_stall_counter + 1;
+ w_stall_limit <= (w_stall_counter + 1 >= OPT_TIMEOUT);
+ end
+ // }}}
+
+ //
+ // Write acknowledgment delay counter
+ // {{{
+ initial w_ack_timer = 0;
+ initial w_ack_limit = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_write_fault)
+ begin
+ w_ack_timer <= 0;
+ w_ack_limit <= 0;
+ end else if (M_AXI_BVALID || downstream_aw_zero || downstream_w_zero)
+ begin
+ w_ack_timer <= 0;
+ w_ack_limit <= 0;
+ end else
+ begin
+ w_ack_timer <= w_ack_timer + 1;
+ w_ack_limit <= (w_ack_timer + 1 >= OPT_TIMEOUT);
+ end
+ // }}}
+
+ //
+ // Read request stall counter
+ // {{{
+ initial r_stall_counter = 0;
+ initial r_stall_limit = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_read_fault)
+ begin
+ r_stall_counter <= 0;
+ r_stall_limit <= 0;
+ end else if (!M_AXI_ARVALID || M_AXI_ARREADY || M_AXI_RVALID)
+ begin
+ r_stall_counter <= 0;
+ r_stall_limit <= 0;
+ end else begin
+ r_stall_counter <= r_stall_counter + 1;
+ r_stall_limit <= (r_stall_counter + 1 >= OPT_TIMEOUT);
+ end
+ // }}}
+
+ //
+ // Read acknowledgement delay counter
+ // {{{
+ initial r_ack_timer = 0;
+ initial r_ack_limit = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_read_fault)
+ begin
+ r_ack_timer <= 0;
+ r_ack_limit <= 0;
+ end else if (M_AXI_RVALID || downstream_r_zero)
+ begin
+ r_ack_timer <= 0;
+ r_ack_limit <= 0;
+ end else begin
+ r_ack_timer <= r_ack_timer + 1;
+ r_ack_limit <= (r_ack_timer + 1 >= OPT_TIMEOUT);
+ end
+ // }}}
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Fault detection
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ //
+ // Determine if a write fault has taken place
+ // {{{
+ initial o_write_fault =1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ o_write_fault <= 1'b0;
+ else if (OPT_SELF_RESET && o_write_fault)
+ begin
+ //
+ // Clear any fault on reset
+ if (!M_AXI_ARESETN)
+ o_write_fault <= 1'b0;
+ end else begin
+ //
+ // A write fault takes place if you respond without a prior
+ // bus request on both write address and write data channels.
+ if ((downstream_aw_zero || downstream_w_zero)&&(bskd_valid))
+ o_write_fault <= 1'b1;
+
+ // AXI-lite slaves are not allowed to return EXOKAY responses
+ // from the bus
+ if (bskd_valid && bskd_resp == EXOKAY)
+ o_write_fault <= 1'b1;
+
+ // If the downstream core refuses to accept either a
+ // write address request, or a write data request, or for that
+ // matter if it doesn't return an acknowledgment in a timely
+ // fashion, then a fault has been detected.
+ if (aw_stall_limit || w_stall_limit || w_ack_limit)
+ o_write_fault <= 1'b1;
+
+ // If the downstream core changes BRESP while VALID && !READY,
+ // then it isn't stalling the channel properly--that's a fault.
+ if (last_bchanged)
+ o_write_fault <= 1'b1;
+ end
+ // }}}
+
+ // o_read_fault
+ // {{{
+ initial o_read_fault =1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ o_read_fault <= 1'b0;
+ else if (OPT_SELF_RESET && o_read_fault)
+ begin
+ //
+ // Clear any fault on reset
+ if (!M_AXI_ARESETN)
+ o_read_fault <= 1'b0;
+ end else begin
+ // Responding without a prior request is a fault. Can only
+ // respond after a request has been made.
+ if (downstream_r_zero && rskd_valid)
+ o_read_fault <= 1'b1;
+
+ // AXI-lite slaves are not allowed to return EXOKAY. This is
+ // an error.
+ if (rskd_valid && rskd_resp == EXOKAY)
+ o_read_fault <= 1'b1;
+
+ // The slave cannot stall the bus forever, nor should the
+ // master wait forever for a response from the slave.
+ if (r_stall_limit || r_ack_limit)
+ o_read_fault <= 1'b1;
+
+ // If the slave changes the data, or the RRESP on the wire,
+ // while the incoming bus is stalled, then that's also a fault.
+ if (last_rchanged)
+ o_read_fault <= 1'b1;
+ end
+ // }}}
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Self reset handling
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ generate if (OPT_SELF_RESET)
+ begin : SELF_RESET_GENERATION
+ // {{{
+ wire min_reset;
+
+ if (OPT_MIN_RESET > 1)
+ begin : MIN_RESET
+ // {{{
+ reg r_min_reset;
+ reg [$clog2(OPT_MIN_RESET+1):0] reset_counter;
+
+ //
+ // Optionally insist that any downstream reset have a
+ // minimum duration. Many Xilinx components require
+ // a 16-clock reset. This ensures such reset
+ // requirements are achieved.
+ //
+
+ initial reset_counter = OPT_MIN_RESET-1;
+ initial r_min_reset = 1'b0;
+ always @(posedge S_AXI_ARESETN)
+ if (M_AXI_ARESETN)
+ begin
+ reset_counter <= OPT_MIN_RESET-1;
+ r_min_reset <= 1'b0;
+ end else if (!M_AXI_ARESETN)
+ begin
+ if (reset_counter > 0)
+ reset_counter <= reset_counter-1;
+ min_reset <= (reset_counter <= 1);
+ end
+
+ assign min_reset = r_min_reset;
+`ifdef FORMAL
+ always @(*)
+ assert(reset_counter < OPT_MIN_RESET);
+ always @(*)
+ assert(min_reset == (reset_counter == 0));
+`endif
+ // }}}
+ end else begin : NO_MIN_RESET
+ // {{{
+ assign min_reset = 1'b1;
+ // }}}
+ end
+
+ // M_AXI_ARESETN
+ // {{{
+ // Reset the downstream bus on either a write or a read fault.
+ // Once the bus returns to idle, and any minimum reset durations
+ // have been achieved, then release the downstream from reset.
+ //
+ initial M_AXI_ARESETN = 1'b0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ M_AXI_ARESETN <= 1'b0;
+ else if (o_write_fault || o_read_fault)
+ M_AXI_ARESETN <= 1'b0;
+ else if (aw_zero && w_zero && r_zero && min_reset
+ && !awskd_valid && !wskd_valid && !arskd_valid)
+ M_AXI_ARESETN <= 1'b1;
+ // }}}
+ // }}}
+ end else begin : SAME_RESET
+ // {{{
+ //
+ // The downstream reset equals the upstream reset
+ //
+ always @(*)
+ M_AXI_ARESETN = S_AXI_ARESETN;
+ // }}}
+ end endgenerate
+ // }}}
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// Formal property section
+// {{{
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+`ifdef FORMAL
+ // {{{
+ //
+ // The following proof comes in several parts.
+ //
+ // 1. PROVE that the upstream properties will hold independent of
+ // what the downstream slave ever does.
+ //
+ // 2. PROVE that if the downstream slave follows protocol, then
+ // neither o_write_fault nor o_read_fault will never get raised.
+ //
+ // We then repeat these proofs again with both OPT_SELF_RESET set and
+ // clear. Which of the four proofs is accomplished is dependent upon
+ // parameters set by the formal engine.
+ //
+ //
+ wire [LGDEPTH:0] faxils_awr_outstanding, faxils_wr_outstanding,
+ faxils_rd_outstanding;
+
+ reg f_past_valid;
+ initial f_past_valid = 0;
+ always @(posedge S_AXI_ACLK)
+ f_past_valid <= 1;
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Upstream master Bus properties
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+ always @(*)
+ if (!f_past_valid)
+ begin
+ assume(!S_AXI_ARESETN);
+ assert(!M_AXI_ARESETN);
+ end
+
+ faxil_slave #(
+ // {{{
+ .C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH),
+ .C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH),
+ .F_OPT_ASSUME_RESET(1'b1),
+ .F_OPT_NO_RESET((OPT_MIN_RESET == 0) ? 1:0),
+// .F_AXI_MAXWAIT((F_OPT_FAULTLESS) ? (2*OPT_TIMEOUT+2) : 0),
+ .F_AXI_MAXRSTALL(3),
+// .F_AXI_MAXDELAY(OPT_TIMEOUT+OPT_TIMEOUT+5),
+ .F_LGDEPTH(LGDEPTH+1),
+ //
+ .F_AXI_MAXWAIT((F_OPT_FAULTLESS) ? (2*OPT_TIMEOUT+2) : 0),
+ .F_AXI_MAXDELAY(2*OPT_TIMEOUT+3)
+ // }}}
+ ) axils (
+ // {{{
+ .i_clk(S_AXI_ACLK),
+ .i_axi_reset_n(S_AXI_ARESETN),
+ //
+ .i_axi_awvalid(S_AXI_AWVALID),
+ .i_axi_awready(S_AXI_AWREADY),
+ .i_axi_awaddr( S_AXI_AWADDR),
+ .i_axi_awprot( S_AXI_AWPROT),
+ //
+ .i_axi_wvalid(S_AXI_WVALID),
+ .i_axi_wready(S_AXI_WREADY),
+ .i_axi_wdata( S_AXI_WDATA),
+ .i_axi_wstrb( S_AXI_WSTRB),
+ //
+ .i_axi_bvalid(S_AXI_BVALID),
+ .i_axi_bready(S_AXI_BREADY),
+ .i_axi_bresp( S_AXI_BRESP),
+ //
+ .i_axi_arvalid(S_AXI_ARVALID),
+ .i_axi_arready(S_AXI_ARREADY),
+ .i_axi_araddr( S_AXI_ARADDR),
+ .i_axi_arprot( S_AXI_ARPROT),
+ //
+ .i_axi_rvalid(S_AXI_RVALID),
+ .i_axi_rready(S_AXI_RREADY),
+ .i_axi_rdata( S_AXI_RDATA),
+ .i_axi_rresp( S_AXI_RRESP),
+ //
+ .f_axi_awr_outstanding(faxils_awr_outstanding),
+ .f_axi_wr_outstanding(faxils_wr_outstanding),
+ .f_axi_rd_outstanding(faxils_rd_outstanding)
+ // }}}
+ );
+
+ always @(*)
+ if (!F_OPT_WRITES)
+ begin
+ // {{{
+ assume(!S_AXI_AWVALID);
+ assume(!S_AXI_WVALID);
+ assert(aw_count == 0);
+ assert(w_count == 0);
+ assert(!M_AXI_AWVALID);
+ assert(!M_AXI_WVALID);
+ // }}}
+ end
+
+ always @(*)
+ if (!F_OPT_READS)
+ begin
+ // {{{
+ assume(!S_AXI_ARVALID);
+ assert(r_count == 0);
+ assert(!S_AXI_RVALID);
+ assert(!M_AXI_ARVALID);
+ // }}}
+ end
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // General Induction properties
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+
+ always @(*)
+ begin
+ // {{{
+ assert(aw_zero == (aw_count == 0));
+ assert(w_zero == (w_count == 0));
+ assert(r_zero == (r_count == 0));
+
+ //
+ assert(aw_full == (&aw_count));
+ assert(w_full == (&w_count));
+ assert(r_full == (&r_count));
+ //
+ if (M_AXI_ARESETN && !o_write_fault)
+ begin
+ assert(downstream_aw_zero == (downstream_aw_count == 0));
+ assert(downstream_w_zero == (downstream_w_count == 0));
+ assert(downstream_aw_count + (M_AXI_AWVALID ? 1:0)
+ + (S_AXI_BVALID ? 1:0) == aw_count);
+ assert(downstream_w_count + (M_AXI_WVALID ? 1:0)
+ + (S_AXI_BVALID ? 1:0) == w_count);
+ end
+
+ if (M_AXI_ARESETN && !o_read_fault)
+ begin
+ assert(downstream_r_zero == (downstream_r_count == 0));
+ assert(downstream_r_count + (M_AXI_ARVALID ? 1:0)
+ + (S_AXI_RVALID ? 1:0) == r_count);
+ end
+ //
+ assert(aw_count == faxils_awr_outstanding);
+ assert(w_count == faxils_wr_outstanding);
+ assert(r_count == faxils_rd_outstanding);
+
+ assert(aw_w_greater == (aw_count > w_count));
+ assert(w_aw_greater == (w_count > aw_count));
+ // }}}
+ end
+ // }}}
+ generate if (F_OPT_FAULTLESS)
+ begin : ASSUME_FAULTLESS
+ // {{{
+ ////////////////////////////////////////////////////////////////
+ //
+ // Assume the downstream core is protocol compliant, and
+ // prove that o_fault stays low.
+ // {{{
+ ////////////////////////////////////////////////////////////////
+ //
+ wire [LGDEPTH:0] faxilm_awr_outstanding,
+ faxilm_wr_outstanding,
+ faxilm_rd_outstanding;
+
+ faxil_master #(
+ // {{{
+ .C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH),
+ .C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH),
+ .F_OPT_NO_RESET((OPT_MIN_RESET == 0) ? 1:0),
+ .F_AXI_MAXWAIT(OPT_TIMEOUT),
+ .F_AXI_MAXRSTALL(4),
+ .F_AXI_MAXDELAY(OPT_TIMEOUT),
+ .F_LGDEPTH(LGDEPTH+1)
+ // }}}
+ ) axilm (
+ // {{{
+ .i_clk(S_AXI_ACLK),
+ .i_axi_reset_n(M_AXI_ARESETN && S_AXI_ARESETN),
+ //
+ .i_axi_awvalid(M_AXI_AWVALID),
+ .i_axi_awready(M_AXI_AWREADY),
+ .i_axi_awaddr( M_AXI_AWADDR),
+ .i_axi_awprot( M_AXI_AWPROT),
+ //
+ .i_axi_wvalid(M_AXI_WVALID),
+ .i_axi_wready(M_AXI_WREADY),
+ .i_axi_wdata( M_AXI_WDATA),
+ .i_axi_wstrb( M_AXI_WSTRB),
+ //
+ .i_axi_bvalid(M_AXI_BVALID),
+ .i_axi_bready(M_AXI_BREADY),
+ .i_axi_bresp( M_AXI_BRESP),
+ //
+ .i_axi_arvalid(M_AXI_ARVALID),
+ .i_axi_arready(M_AXI_ARREADY),
+ .i_axi_araddr( M_AXI_ARADDR),
+ .i_axi_arprot( M_AXI_ARPROT),
+ //
+ .i_axi_rvalid(M_AXI_RVALID),
+ .i_axi_rready(M_AXI_RREADY),
+ .i_axi_rdata( M_AXI_RDATA),
+ .i_axi_rresp( M_AXI_RRESP),
+ //
+ .f_axi_awr_outstanding(faxilm_awr_outstanding),
+ .f_axi_wr_outstanding(faxilm_wr_outstanding),
+ .f_axi_rd_outstanding(faxilm_rd_outstanding)
+ // }}}
+ );
+
+ //
+ // Here's the big proof
+ // {{{
+ always @(*)
+ assert(!o_write_fault);
+ always @(*)
+ assert(!o_read_fault);
+ // }}}
+ // }}}
+ ////////////////////////////////////////////////////////////////
+ //
+ // The following properties are necessary for passing induction
+ // {{{
+ ////////////////////////////////////////////////////////////////
+ //
+ //
+ always @(*)
+ begin
+ assert(!aw_stall_limit);
+ assert(!w_stall_limit);
+ assert(!w_ack_limit);
+
+ assert(!r_stall_limit);
+ assert(!r_ack_limit);
+
+ if (M_AXI_ARESETN)
+ begin
+ assert(downstream_aw_count == faxilm_awr_outstanding);
+ assert(downstream_w_count == faxilm_wr_outstanding);
+ assert(downstream_r_count == faxilm_rd_outstanding);
+ end
+ end
+
+ if (OPT_SELF_RESET)
+ begin
+ always @(posedge S_AXI_ACLK)
+ if (f_past_valid)
+ assert(M_AXI_ARESETN == $past(S_AXI_ARESETN));
+ end
+
+`ifdef VERIFIC
+ wire [LGDEPTH:0] f_axi_arstall;
+ wire [LGDEPTH:0] f_axi_awstall;
+ wire [LGDEPTH:0] f_axi_wstall;
+
+ assign f_axi_awstall = axilm.CHECK_STALL_COUNT.f_axi_awstall;
+ assign f_axi_wstall = axilm.CHECK_STALL_COUNT.f_axi_wstall;
+ assign f_axi_arstall = axilm.CHECK_STALL_COUNT.f_axi_arstall;
+
+ always @(*)
+ if (M_AXI_ARESETN && S_AXI_ARESETN && !o_write_fault)
+ assert(f_axi_awstall == aw_stall_counter);
+
+ always @(*)
+ if (M_AXI_ARESETN && S_AXI_ARESETN && !o_write_fault)
+ assert(f_axi_wstall == w_stall_counter);
+
+ always @(*)
+ if (M_AXI_ARESETN && S_AXI_ARESETN && !o_read_fault)
+ assert(f_axi_arstall == r_stall_counter);
+`endif
+ // }}}
+ // }}}
+ end else begin : WILD_DOWNSTREAM
+ // {{{
+ ////////////////////////////////////////////////////////////////
+ //
+ // cover() checks, checks that only make sense if faults are
+ // possible
+ //
+
+ reg write_faulted, read_faulted, faulted;
+ reg [3:0] cvr_writes, cvr_reads;
+
+
+ if (OPT_SELF_RESET)
+ begin
+ ////////////////////////////////////////////////////////
+ //
+ // Prove that we can actually reset the downstream
+ // bus/core as desired
+ // {{{
+ ////////////////////////////////////////////////////////
+ //
+ //
+ initial write_faulted = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ write_faulted <= 0;
+ else if (o_write_fault)
+ write_faulted <= 1;
+
+
+ initial faulted = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN)
+ read_faulted <= 0;
+ else if (o_read_fault)
+ read_faulted <= 1;
+
+ always @(*)
+ faulted = (write_faulted || read_faulted);
+
+ always @(posedge S_AXI_ACLK)
+ cover(write_faulted && $rose(M_AXI_ARESETN));
+
+ always @(posedge S_AXI_ACLK)
+ cover(read_faulted && $rose(M_AXI_ARESETN));
+
+ always @(posedge S_AXI_ACLK)
+ cover(faulted && M_AXI_ARESETN && S_AXI_BVALID);
+
+ always @(posedge S_AXI_ACLK)
+ cover(faulted && M_AXI_ARESETN && S_AXI_RVALID);
+
+
+ initial cvr_writes = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_write_fault)
+ cvr_writes <= 0;
+ else if (write_faulted && S_AXI_BVALID && S_AXI_BREADY
+ && S_AXI_BRESP == OKAY
+ &&(!(&cvr_writes)))
+ cvr_writes <= cvr_writes + 1;
+
+ always @(*)
+ cover(cvr_writes > 5);
+
+ initial cvr_reads = 0;
+ always @(posedge S_AXI_ACLK)
+ if (!S_AXI_ARESETN || !M_AXI_ARESETN || o_read_fault)
+ cvr_reads <= 0;
+ else if (read_faulted && S_AXI_RVALID && S_AXI_RREADY
+ && S_AXI_RRESP == OKAY
+ &&(!(&cvr_reads)))
+ cvr_reads <= cvr_reads + 1;
+
+ always @(*)
+ cover(cvr_reads > 5);
+ // }}}
+ end
+
+ // }}}
+ end endgenerate
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Never data properties
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+ (* anyconst *) reg [C_AXI_DATA_WIDTH-1:0] fc_never_read_data;
+ (* anyconst *) reg [C_AXI_DATA_WIDTH+C_AXI_DATA_WIDTH/8-1:0]
+ fc_never_write_data;
+
+ (* anyconst *) reg [C_AXI_ADDR_WIDTH-1:0] fc_never_read_addr,
+ fc_never_write_addr;
+
+ // Write address checking
+ // {{{
+ always @(*)
+ if (S_AXI_ARESETN && S_AXI_AWVALID)
+ assume(S_AXI_AWADDR != fc_never_write_addr);
+
+ always @(*)
+ if (S_AXI_ARESETN && M_AXI_ARESETN && !o_write_fault && M_AXI_AWVALID)
+ assert(M_AXI_AWADDR != fc_never_write_addr);
+ // }}}
+
+ // Write checking
+ // {{{
+ always @(*)
+ if (S_AXI_ARESETN && S_AXI_WVALID)
+ assume({ S_AXI_WDATA, S_AXI_WSTRB } != fc_never_write_data);
+
+ always @(*)
+ if (S_AXI_ARESETN && M_AXI_ARESETN && !o_write_fault && M_AXI_WVALID)
+ assert({ M_AXI_WDATA, M_AXI_WSTRB } != fc_never_write_data);
+ // }}}
+
+ // Read address checking
+ // {{{
+ always @(*)
+ if (S_AXI_ARESETN && S_AXI_ARVALID)
+ assume(S_AXI_ARADDR != fc_never_read_addr);
+
+ always @(*)
+ if (S_AXI_ARESETN && M_AXI_ARESETN && !o_read_fault && M_AXI_ARVALID)
+ assert(M_AXI_ARADDR != fc_never_read_addr);
+ // }}}
+
+ // Read checking
+ // {{{
+ always @(*)
+ if (S_AXI_ARESETN && M_AXI_ARESETN && M_AXI_RVALID)
+ assume(M_AXI_RDATA != fc_never_read_data);
+
+ always @(*)
+ if (S_AXI_ARESETN && S_AXI_RVALID && S_AXI_RRESP == 2'b00)
+ assert(S_AXI_RDATA != fc_never_read_data);
+ // }}}
+
+ // }}}
+
+`endif
+// }}}
+endmodule