diff options
Diffstat (limited to 'rtl/wb2axip/axisafety.v')
| -rw-r--r-- | rtl/wb2axip/axisafety.v | 2339 |
1 files changed, 0 insertions, 2339 deletions
diff --git a/rtl/wb2axip/axisafety.v b/rtl/wb2axip/axisafety.v deleted file mode 100644 index ff7e351..0000000 --- a/rtl/wb2axip/axisafety.v +++ /dev/null @@ -1,2339 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Filename: axisafety.v -// {{{ -// Project: WB2AXIPSP: bus bridges and other odds and ends -// -// Purpose: Given that 1) AXI interfaces can be difficult to write and to -// get right, 2) my experiences with the AXI infrastructure of an -// ARM+FPGA is that the device needs a power cycle following a bus fault, -// and given that I've now found multiple interfaces that had some bug -// or other within them, the following is a bus fault isolator. It acts -// as a bump in the log between the interconnect and the user core. As -// such, it has two interfaces: The first is the slave interface, -// coming from the interconnect. The second interface is the master -// interface, proceeding to a slave that might be faulty. -// -// INTERCONNECT --> (S) AXISAFETY (M) --> POTENTIALLY FAULTY CORE -// -// The slave interface has been formally verified to be a valid AXI -// slave, independent of whatever the potentially faulty core might do. -// If the user core (i.e. the potentially faulty one) responds validly -// to the requests of a master, then this core will turn into a simple -// delay on the bus. If, on the other hand, the user core suffers from -// a protocol error, then this core will set one of two output -// flags--either o_write_fault or o_read_fault indicating whether a write -// or a read fault was detected. Further attempts to access the user -// core will result in bus errors, generated by the AXISAFETY core. -// -// Assuming the bus master can properly detect and deal with a bus error, -// this should then make it possible to properly recover from a bus -// protocol error without later needing to cycle power. -// -// The core does have a couple of limitations. For example, it can only -// handle one burst transaction, and one ID at a time. This matches the -// performances of Xilinx's example AXI full core, from which many user -// cores have have been copied/modified from. Therefore, there will be -// no performance loss for such a core. -// -// Because of this, it is still possible that the user core might have an -// undetected fault when using this core. For example, if the interconnect -// issues more than one bus request before receiving the response from the -// first request, this safety core will stall the second request, -// preventing the downstream core from seeing this second request. If the -// downstream core would suffer from an error while handling the second -// request, by preventing the user core from seeing the second request this -// core eliminates that potential for error. -// -// Usage: The important part of using this core is to connect the slave -// side to the interconnect, and the master side to the user core. -// -// Some options are available: -// -// 1) C_S_AXI_ADDR_WIDTH The number of address bits in the AXI channel -// 1) C_S_AXI_DATA_WIDTH The number of data bits in the AXI channel -// 3) C_S_AXI_ID_WIDTH The number of bits in an AXI ID. As currently -// written, this number cannot be zero. You can, however, set it -// to '1' and connect all of the relevant ID inputs to zero. -// -// These three parameters have currently been abbreviated with AW, DW, and -// IW. I anticipate returning them to their original meanings, I just -// haven't done so (yet). -// -// 4) OPT_TIMEOUT This is the number of clock periods, from -// interconnect request to interconnect response, that the -// slave needs to respond within. (The actual timeout from the -// user slave's perspective will be shorter than this.) -// -// This timeout is part of the check that a slave core will -// always return a response. From the standpoint of this core, -// it can be set arbitrarily large. (From the standpoint of -// formal verification, it needs to be kept short ...) -// Feel free to set this even as large as 1ms if you would like. -// -// 5) OPT_SELF_RESET If set, will send a reset signal to the slave -// following any write or read fault. This will cause the other -// side of the link (write or read) to fault as well. Once the -// channel then becomes inactive, the slave will be released from -// reset and will be able to interact with the rest of the bus -// again. -// -// 5) OPT_EXCLUSIVE If clear, will prohibit the slave from ever -// receiving an exclusive access request. This saves the logic -// in the firewall necessary to check that an EXOKAY response -// to a write request was truly an allowed response. Since that -// logic can explode with the ID width, sparing it can be quite -// useful. If set, provides full exclusive access checking in -// addition to the normal bus fault checking. -// -// Performance: As mentioned above, this core can handle one read burst and one -// write burst at a time, no more. Further, the core will delay -// an input path by one clock and the output path by another clock, so that -// the latency involved with using this core is a minimum of two extra -// clocks beyond the latency user slave core. -// -// Maximum write latency: N+3 clocks for a burst of N values -// Maximum read latency: N+3 clocks for a burst of N values -// -// Faults detected: -// -// Write channel: -// 1. Raising BVALID prior to the last write value being sent -// to the user/slave core. -// 2. Raising BVALID prior to accepting the write address -// 3. A BID return ID that doesn't match the request AWID -// 4. Sending too many returns, such as not dropping BVALID -// or raising it when there is no outstanding write -// request -// -// While the following technically isn't a violation of the -// AXI protocol, it is treated as such by this fault isolator. -// -// 5. Accepting write data prior to the write address -// -// The fault isolator will guarantee that AWVALID is raised before -// WVALID, so this shouldn't be a problem. -// -// Read channel: -// -// 1. Raising RVALID before accepting the read address, ARVALID -// 2. A return ID that doesn't match the ID that was sent. -// 3. Raising RVALID after the last return value, and so returning -// too many response values -// 4. Setting the RLAST value on anything but the last value from -// the bus. -// -// -// Creator: Dan Gisselquist, Ph.D. -// Gisselquist Technology, LLC -// -//////////////////////////////////////////////////////////////////////////////// -// }}} -// Copyright (C) 2019-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 axisafety #( - // {{{ - parameter C_S_AXI_ID_WIDTH = 1, - parameter C_S_AXI_DATA_WIDTH = 32, - parameter C_S_AXI_ADDR_WIDTH = 16, - // OPT_SELF_RESET: Set to true if the downstream slave should be - // reset upon detecting an error and separate from the upstream reset - // domain - parameter [0:0] OPT_SELF_RESET = 1'b0, - // OPT_EXCLUSIVE: Set to true if the downstream slave might possibly - // offer an exclusive access capability - parameter [0:0] OPT_EXCLUSIVE = 1'b0, - // - // I use the following abbreviations, IW, DW, and AW, to simplify - // the code below (and to help it fit within an 80 col terminal) - localparam IW = C_S_AXI_ID_WIDTH, - localparam DW = C_S_AXI_DATA_WIDTH, - localparam AW = C_S_AXI_ADDR_WIDTH, - // - // OPT_TIMEOUT references the number of clock cycles to wait - // between raising the *VALID signal and when the respective - // *VALID return signal must be high. You might wish to set this - // to a very high number, to allow your core to work its magic. - parameter OPT_TIMEOUT = 20 - // }}} - ) ( - // {{{ - output reg o_read_fault, - output reg o_write_fault, - // User ports ends - // Do not modify the ports beyond this line - - // Global Clock Signal - input wire S_AXI_ACLK, - // Global Reset Signal. This Signal is Active LOW - input wire S_AXI_ARESETN, - output reg M_AXI_ARESETN, - // - // The input side. This is where slave requests come into - // the core. - // {{{ - // - // Write address - input wire [IW-1 : 0] S_AXI_AWID, - input wire [AW-1 : 0] S_AXI_AWADDR, - input wire [7 : 0] S_AXI_AWLEN, - input wire [2 : 0] S_AXI_AWSIZE, - input wire [1 : 0] S_AXI_AWBURST, - input wire S_AXI_AWLOCK, - input wire [3 : 0] S_AXI_AWCACHE, - input wire [2 : 0] S_AXI_AWPROT, - input wire [3 : 0] S_AXI_AWQOS, - input wire S_AXI_AWVALID, - output reg S_AXI_AWREADY, - // Write data - input wire [DW-1 : 0] S_AXI_WDATA, - input wire [(DW/8)-1 : 0] S_AXI_WSTRB, - input wire S_AXI_WLAST, - input wire S_AXI_WVALID, - output reg S_AXI_WREADY, - // Write return - output reg [IW-1 : 0] S_AXI_BID, - output reg [1 : 0] S_AXI_BRESP, - output reg S_AXI_BVALID, - input wire S_AXI_BREADY, - // Read address - input wire [IW-1 : 0] S_AXI_ARID, - input wire [AW-1 : 0] S_AXI_ARADDR, - input wire [7 : 0] S_AXI_ARLEN, - input wire [2 : 0] S_AXI_ARSIZE, - input wire [1 : 0] S_AXI_ARBURST, - input wire S_AXI_ARLOCK, - input wire [3 : 0] S_AXI_ARCACHE, - input wire [2 : 0] S_AXI_ARPROT, - input wire [3 : 0] S_AXI_ARQOS, - input wire S_AXI_ARVALID, - output reg S_AXI_ARREADY, - // Read data - output reg [IW-1 : 0] S_AXI_RID, - output reg [DW-1 : 0] S_AXI_RDATA, - output reg [1 : 0] S_AXI_RRESP, - output reg S_AXI_RLAST, - output reg S_AXI_RVALID, - input wire S_AXI_RREADY, - // }}} - // - // The output side, where slave requests are forwarded to the - // actual slave - // {{{ - // Write address - // {{{ - output reg [IW-1 : 0] M_AXI_AWID, - output reg [AW-1 : 0] M_AXI_AWADDR, - output reg [7 : 0] M_AXI_AWLEN, - output reg [2 : 0] M_AXI_AWSIZE, - output reg [1 : 0] M_AXI_AWBURST, - output reg M_AXI_AWLOCK, - output reg [3 : 0] M_AXI_AWCACHE, - output reg [2 : 0] M_AXI_AWPROT, - output reg [3 : 0] M_AXI_AWQOS, - output reg M_AXI_AWVALID, - input wire M_AXI_AWREADY, - // Write data - output reg [DW-1 : 0] M_AXI_WDATA, - output reg [(DW/8)-1 : 0] M_AXI_WSTRB, - output reg M_AXI_WLAST, - output reg M_AXI_WVALID, - input wire M_AXI_WREADY, - // Write return - input wire [IW-1 : 0] M_AXI_BID, - input wire [1 : 0] M_AXI_BRESP, - input wire M_AXI_BVALID, - output wire M_AXI_BREADY, - // }}} - // Read address - // {{{ - output reg [IW-1 : 0] M_AXI_ARID, - output reg [AW-1 : 0] M_AXI_ARADDR, - output reg [7 : 0] M_AXI_ARLEN, - output reg [2 : 0] M_AXI_ARSIZE, - output reg [1 : 0] M_AXI_ARBURST, - output reg M_AXI_ARLOCK, - output reg [3 : 0] M_AXI_ARCACHE, - output reg [2 : 0] M_AXI_ARPROT, - output reg [3 : 0] M_AXI_ARQOS, - output reg M_AXI_ARVALID, - input wire M_AXI_ARREADY, - // Read data - input wire [IW-1 : 0] M_AXI_RID, - input wire [DW-1 : 0] M_AXI_RDATA, - input wire [1 : 0] M_AXI_RRESP, - input wire M_AXI_RLAST, - input wire M_AXI_RVALID, - output wire M_AXI_RREADY - // }}} - // }}} - // }}} - ); - - localparam LGTIMEOUT = $clog2(OPT_TIMEOUT+1); - localparam [1:0] OKAY = 2'b00, EXOKAY = 2'b01; - localparam SLAVE_ERROR = 2'b10; - // - // - // Register declarations - // {{{ - reg faulty_write_return, faulty_read_return; - reg clear_fault; - // - // Timer/timeout variables - reg [LGTIMEOUT-1:0] write_timer, read_timer; - reg write_timeout, read_timeout; - - // - // Double buffer the write address channel - reg r_awvalid, m_awvalid; - reg [IW-1:0] r_awid, m_awid; - reg [AW-1:0] r_awaddr, m_awaddr; - reg [7:0] r_awlen, m_awlen; - reg [2:0] r_awsize, m_awsize; - reg [1:0] r_awburst, m_awburst; - reg r_awlock, m_awlock; - reg [3:0] r_awcache, m_awcache; - reg [2:0] r_awprot, m_awprot; - reg [3:0] r_awqos, m_awqos; - - // - // Double buffer for the write channel - reg r_wvalid,m_wvalid; - reg [DW-1:0] r_wdata, m_wdata; - reg [DW/8-1:0] r_wstrb, m_wstrb; - reg r_wlast, m_wlast; - - // - // Double buffer the write response channel - reg m_bvalid; // r_bvalid == 0 - reg [IW-1:0] m_bid; - reg [1:0] m_bresp; - - // - // Double buffer the read address channel - reg r_arvalid, m_arvalid; - reg [IW-1:0] r_arid, m_arid; - reg [AW-1:0] r_araddr, m_araddr; - reg [7:0] r_arlen, m_arlen; - reg [2:0] r_arsize, m_arsize; - reg [1:0] r_arburst, m_arburst; - reg r_arlock, m_arlock; - reg [3:0] r_arcache, m_arcache; - reg [2:0] r_arprot, m_arprot; - reg [3:0] r_arqos, m_arqos; - - // - // Double buffer the read data response channel - reg r_rvalid,m_rvalid; - reg [IW-1:0] m_rid; - reg [1:0] r_rresp, m_rresp; - reg m_rlast; - reg [DW-1:0] r_rdata, m_rdata; - - // - // Write FIFO data - wire [IW-1:0] wfifo_id; - wire wfifo_lock; - - // - // Read FIFO data - reg [IW-1:0] rfifo_id; - reg rfifo_lock; - reg [8:0] rfifo_counter; - reg rfifo_empty, rfifo_last, rfifo_penultimate; - - // - // - reg [0:0] s_wbursts; - reg [8:0] m_wpending; - reg m_wempty, m_wlastctr; - wire waddr_valid, raddr_valid; - - wire lock_enabled, lock_failed; - wire [(1<<IW)-1:0] lock_active; - reg rfifo_first, exread; - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Write channel processing - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // - - // Write address processing - // {{{ - // S_AXI_AWREADY - // {{{ - initial S_AXI_AWREADY = (OPT_SELF_RESET) ? 0:1; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - S_AXI_AWREADY <= !OPT_SELF_RESET; - else if (S_AXI_AWVALID && S_AXI_AWREADY) - S_AXI_AWREADY <= 0; - // else if (clear_fault) - // S_AXI_AWREADY <= 1; - else if (!S_AXI_AWREADY) - S_AXI_AWREADY <= S_AXI_BVALID && S_AXI_BREADY; - // }}} - - generate if (OPT_EXCLUSIVE) - begin : GEN_LOCK_ENABLED - // {{{ - reg r_lock_enabled, r_lock_failed; - - // lock_enabled - // {{{ - initial r_lock_enabled = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || !OPT_EXCLUSIVE) - r_lock_enabled <= 0; - else if (S_AXI_AWVALID && S_AXI_AWREADY) - r_lock_enabled <= S_AXI_AWLOCK && lock_active[S_AXI_AWID]; - else if (S_AXI_BVALID && S_AXI_BREADY) - r_lock_enabled <= 0; - // }}} - - // lock_failed - // {{{ - initial r_lock_failed = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || !OPT_EXCLUSIVE) - r_lock_failed <= 0; - else if (S_AXI_AWVALID && S_AXI_AWREADY) - r_lock_failed <= S_AXI_AWLOCK && !lock_active[S_AXI_AWID]; - else if (S_AXI_BVALID && S_AXI_BREADY) - r_lock_failed <= 0; - // }}} - - assign lock_enabled = r_lock_enabled; - assign lock_failed = r_lock_failed; - // }}} - end else begin : NO_LOCK_ENABLE - // {{{ - assign lock_enabled = 0; - assign lock_failed = 0; - // }}} - end endgenerate - - // waddr_valid - // {{{ - generate if (OPT_SELF_RESET) - begin : GEN_LCL_RESET - reg r_waddr_valid; - - initial r_waddr_valid = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - r_waddr_valid <= 0; - else if (S_AXI_AWVALID && S_AXI_AWREADY) - r_waddr_valid <= 1; - else if (waddr_valid) - r_waddr_valid <= !S_AXI_BVALID || !S_AXI_BREADY; - - assign waddr_valid = r_waddr_valid; - end else begin : NO_LCL_RESET - assign waddr_valid = !S_AXI_AWREADY; - end endgenerate - // }}} - - // r_aw* - // {{{ - // Double buffer for the AW* channel - // - initial r_awvalid = 0; - always @(posedge S_AXI_ACLK) - begin - if (S_AXI_AWVALID && S_AXI_AWREADY) - begin - r_awvalid <= 1'b0; - r_awid <= S_AXI_AWID; - r_awaddr <= S_AXI_AWADDR; - r_awlen <= S_AXI_AWLEN; - r_awsize <= S_AXI_AWSIZE; - r_awburst <= S_AXI_AWBURST; - r_awlock <= S_AXI_AWLOCK; - r_awcache <= S_AXI_AWCACHE; - r_awprot <= S_AXI_AWPROT; - r_awqos <= S_AXI_AWQOS; - end else if (M_AXI_AWREADY) - r_awvalid <= 0; - - if (!S_AXI_ARESETN) - begin - r_awvalid <= 0; - r_awlock <= 0; - end - - if (!OPT_EXCLUSIVE) - r_awlock <= 1'b0; - end - // }}} - - // m_aw* - // {{{ - // Second half of the AW* double-buffer. The m_* terms reference - // either the value in the double buffer (assuming one is in there), - // or the incoming value (if the double buffer is empty) - // - always @(*) - if (r_awvalid) - begin - m_awvalid = r_awvalid; - m_awid = r_awid; - m_awaddr = r_awaddr; - m_awlen = r_awlen; - m_awsize = r_awsize; - m_awburst = r_awburst; - m_awlock = r_awlock; - m_awcache = r_awcache; - m_awprot = r_awprot; - m_awqos = r_awqos; - end else begin - m_awvalid = S_AXI_AWVALID && S_AXI_AWREADY; - m_awid = S_AXI_AWID; - m_awaddr = S_AXI_AWADDR; - m_awlen = S_AXI_AWLEN; - m_awsize = S_AXI_AWSIZE; - m_awburst = S_AXI_AWBURST; - m_awlock = S_AXI_AWLOCK && OPT_EXCLUSIVE; - m_awcache = S_AXI_AWCACHE; - m_awprot = S_AXI_AWPROT; - m_awqos = S_AXI_AWQOS; - end - // }}} - - // M_AXI_AW* - // {{{ - // Set the output AW* channel outputs--but only on no fault - // - initial M_AXI_AWVALID = 0; - always @(posedge S_AXI_ACLK) - begin - if (!M_AXI_AWVALID || M_AXI_AWREADY) - begin - - if (o_write_fault) - M_AXI_AWVALID <= 0; - else - M_AXI_AWVALID <= m_awvalid; - - M_AXI_AWID <= m_awid; - M_AXI_AWADDR <= m_awaddr; - M_AXI_AWLEN <= m_awlen; - M_AXI_AWSIZE <= m_awsize; - M_AXI_AWBURST <= m_awburst; - M_AXI_AWLOCK <= m_awlock && lock_active[m_awid]; - M_AXI_AWCACHE <= m_awcache; - M_AXI_AWPROT <= m_awprot; - M_AXI_AWQOS <= m_awqos; - end - - if (!OPT_EXCLUSIVE) - M_AXI_AWLOCK <= 0; - if (!M_AXI_ARESETN) - M_AXI_AWVALID <= 0; - end - // }}} - // }}} - - // s_wbursts - // {{{ - // Count write bursts outstanding from the standpoint of - // the incoming (slave) channel - // - // Notice that, as currently built, the count can only ever be one - // or zero. - // - // We'll use this count in a moment to determine if a response - // has taken too long, or if a response is returned when there's - // no outstanding request - initial s_wbursts = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - s_wbursts <= 0; - else if (S_AXI_WVALID && S_AXI_WREADY && S_AXI_WLAST) - s_wbursts <= 1; - else if (S_AXI_BVALID && S_AXI_BREADY) - s_wbursts <= 0; - // }}} - - // wfifo_id, wfifo_lock - // {{{ - // Keep track of the ID of the last transaction. Since we only - // ever have one write transaction outstanding, this will need to be - // the ID of the returned value. - - assign wfifo_id = r_awid; - assign wfifo_lock = r_awlock; - // }}} - - // m_wpending, m_wempty, m_wlastctr - // {{{ - // m_wpending counts the number of (remaining) write data values that - // need to be sent to the slave. It counts this number with respect - // to the *SLAVE*, not the master. When m_wpending == 1, WLAST shall - // be true. To make comparisons of (m_wpending == 0) or (m_wpending>0), - // m_wempty is assigned to (m_wpending). Similarly, m_wlastctr is - // assigned to (m_wpending == 1). - // - initial m_wpending = 0; - initial m_wempty = 1; - initial m_wlastctr = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || o_write_fault) - begin - // {{{ - m_wpending <= 0; - m_wempty <= 1; - m_wlastctr <= 0; - // }}} - end else if (M_AXI_AWVALID && M_AXI_AWREADY) - begin - // {{{ - if (M_AXI_WVALID && M_AXI_WREADY) - begin - // {{{ - // Accepting AW* and W* packets on the same - // clock - if (m_wpending == 0) - begin - // The AW* and W* packets go together - m_wpending <= {1'b0, M_AXI_AWLEN}; - m_wempty <= (M_AXI_AWLEN == 0); - m_wlastctr <= (M_AXI_AWLEN == 1); - end else begin - // The W* packet goes with the last - // AW* command, the AW* packet with a - // new one - m_wpending <= M_AXI_AWLEN+1; - m_wempty <= 0; - m_wlastctr <= (M_AXI_AWLEN == 0); - end - // }}} - end else begin - // {{{ - m_wpending <= M_AXI_AWLEN+1; - m_wempty <= 0; - m_wlastctr <= (M_AXI_AWLEN == 0); - // }}} - end - // }}} - end else if (M_AXI_WVALID && M_AXI_WREADY && (!m_wempty)) - begin - // {{{ - // The AW* channel is idle, and we just accepted a value - // on the W* channel - m_wpending <= m_wpending - 1; - m_wempty <= (m_wpending <= 1); - m_wlastctr <= (m_wpending == 2); - // }}} - end - // }}} - - // Write data processing - // {{{ - // S_AXI_WREADY - // {{{ - // The S_AXI_WREADY or write channel stall signal - // - // For this core, we idle at zero (stalled) until an AW* packet - // comes through - // - initial S_AXI_WREADY = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - S_AXI_WREADY <= 0; - else if (S_AXI_WVALID && S_AXI_WREADY) - begin - // {{{ - if (S_AXI_WLAST) - S_AXI_WREADY <= 0; - else if (o_write_fault) - S_AXI_WREADY <= 1; - else if (!M_AXI_WVALID || M_AXI_WREADY) - S_AXI_WREADY <= 1; - else - S_AXI_WREADY <= 0; - // }}} - end else if ((s_wbursts == 0)&&(waddr_valid) - &&(o_write_fault || M_AXI_WREADY)) - S_AXI_WREADY <= 1; - else if (S_AXI_AWVALID && S_AXI_AWREADY) - S_AXI_WREADY <= 1; - // }}} - - // r_w* - // {{{ - // Double buffer for the write channel - // - // As before, the r_* values contain the values in the double - // buffer itself - // - initial r_wvalid = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - r_wvalid <= 0; - else if (!r_wvalid) - begin - // {{{ - r_wvalid <= (S_AXI_WVALID && S_AXI_WREADY - && M_AXI_WVALID && !M_AXI_WREADY); - r_wdata <= S_AXI_WDATA; - r_wstrb <= S_AXI_WSTRB; - r_wlast <= S_AXI_WLAST; - // }}} - end else if (o_write_fault || M_AXI_WREADY || !M_AXI_ARESETN) - r_wvalid <= 0; - // }}} - - // m_w* - // {{{ - // Here's the result of our double buffer - // - // m_* references the value within the double buffer in the case that - // something is in the double buffer. Otherwise, it is the values - // directly from the inputs. In the case of a fault, neither is true. - // Write faults override. - // - always @(*) - if (o_write_fault) - begin - // {{{ - m_wvalid = !m_wempty; - m_wlast = m_wlastctr; - m_wstrb = 0; - // }}} - end else if (r_wvalid) - begin - // {{{ - m_wvalid = 1; - m_wstrb = r_wstrb; - m_wlast = r_wlast; - // }}} - end else begin - // {{{ - m_wvalid = S_AXI_WVALID && S_AXI_WREADY; - m_wstrb = S_AXI_WSTRB; - m_wlast = S_AXI_WLAST; - // }}} - end - // }}} - - // m_wdata - // {{{ - // The logic for the DATA output of the double buffer doesn't - // matter so much in the case of o_write_fault - always @(*) - if (r_wvalid) - m_wdata = r_wdata; - else - m_wdata = S_AXI_WDATA; - // }}} - - // M_AXI_W* - // {{{ - // Set the downstream write channel values - // - // As per AXI spec, these values *must* be registered. Note that our - // source here is the m_* double buffer/incoming write data switch. - initial M_AXI_WVALID = 0; - always @(posedge S_AXI_ACLK) - begin - if (!M_AXI_WVALID || M_AXI_WREADY) - begin - M_AXI_WVALID <= m_wvalid; - M_AXI_WDATA <= m_wdata; - M_AXI_WSTRB <= m_wstrb; - if (OPT_EXCLUSIVE && lock_failed) - M_AXI_WSTRB <= 0; - M_AXI_WLAST <= m_wlast; - end - - // Override the WVALID signal (only) on reset, voiding any - // output we might otherwise send. - if (!M_AXI_ARESETN) - M_AXI_WVALID <= 0; - end - // }}} - // }}} - - // Write fault detection - // {{{ - // write_timer - // {{{ - // The write timer - // - // The counter counts up to saturation. It is reset any time - // the write channel is either clear, or a value is accepted - // at the *MASTER* (not slave) side. Why the master side? Simply - // because it makes the proof below easier. (At one time I checked - // both, but then couldn't prove that the faults wouldn't get hit - // if the slave responded in time.) - initial write_timer = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || !waddr_valid) - write_timer <= 0; - else if (!o_write_fault && M_AXI_BVALID) - write_timer <= 0; - else if (S_AXI_WREADY) - write_timer <= 0; - else if (!(&write_timer)) - write_timer <= write_timer + 1; - // }}} - - // write_timeout - // {{{ - // Write timeout detector - // - // If the write_timer reaches the OPT_TIMEOUT, then the write_timeout - // will get set true. This will force a fault, taking the write - // channel off line. - initial write_timeout = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || clear_fault) - write_timeout <= 0; - else if (M_AXI_BVALID) - write_timeout <= write_timeout; - else if (S_AXI_WVALID && S_AXI_WREADY) - write_timeout <= write_timeout; - else if (write_timer >= OPT_TIMEOUT) - write_timeout <= 1; - // }}} - - // faulty_write_return - // {{{ - // fault_write_return - // - // This combinational logic is used to catch an invalid return, and - // so take the slave off-line before the return can corrupt the master - // channel. Reasons for taking the write return off line are listed - // below. - always @(*) - begin - faulty_write_return = 0; - if (M_AXI_WVALID && M_AXI_WREADY - && M_AXI_AWVALID && !M_AXI_AWREADY) - // Accepting the write *data* prior to the write - // *address* is a fault - faulty_write_return = 1; - if (M_AXI_BVALID) - begin - if (M_AXI_AWVALID || M_AXI_WVALID) - // Returning a B* acknowledgement while the - // request remains outstanding is also a fault - faulty_write_return = 1; - if (!m_wempty) - // Same as above, but this time the write - // channel is neither complete, nor is *WVALID - // active. Values remain to be written, - // and so a return is a fault. - faulty_write_return = 1; - if (s_wbursts <= (S_AXI_BVALID ? 1:0)) - // Too many acknowledgments - // - // Returning more than one BVALID&BREADY for - // every AWVALID & AWREADY is a fault. - faulty_write_return = 1; - if (M_AXI_BID != wfifo_id) - // An attempt to return the wrong ID - faulty_write_return = 1; - if (M_AXI_BRESP == EXOKAY && (!OPT_EXCLUSIVE - || !lock_enabled)) - // An attempt to return a valid lock, without - // a prior request - faulty_write_return = 1; - end - end - // }}} - - // o_write_fault - // {{{ - // On a write fault, we're going to disconnect the write port from - // the slave, and return errors on each write connect. o_write_fault - // is our signal determining if the write channel is disconnected. - // - // Most of this work is determined within faulty_write_return above. - // Here we do just a bit more: - initial o_write_fault = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || clear_fault) - o_write_fault <= 0; - else if ((!M_AXI_ARESETN&&o_read_fault) || write_timeout) - o_write_fault <= 1; - else if (M_AXI_BVALID && M_AXI_BREADY) - o_write_fault <= (o_write_fault) || faulty_write_return; - else if (M_AXI_WVALID && M_AXI_WREADY - && M_AXI_AWVALID && !M_AXI_AWREADY) - // Accepting the write data prior to the write address - // is a fault - o_write_fault <= 1; - // }}} - // }}} - - // Write return generation - // {{{ - // m_b* - // {{{ - // Since we only ever allow a single write burst at a time, we don't - // need to double buffer the return channel. Hence, we'll set our - // return channel based upon the incoming values alone. Note that - // we're overriding the M_AXI_BID below, in order to make certain that - // the return goes to the right source. - // - always @(*) - if (o_write_fault) - begin - m_bvalid = (s_wbursts > (S_AXI_BVALID ? 1:0)); - m_bid = wfifo_id; - m_bresp = SLAVE_ERROR; - end else begin - m_bvalid = M_AXI_BVALID; - if (faulty_write_return) - m_bvalid = 0; - m_bid = wfifo_id; - m_bresp = M_AXI_BRESP; - end - // }}} - - // S_AXI_B* - // {{{ - // We'll *never* stall the slaves BREADY channel - // - // If the slave returns the response we are expecting, then S_AXI_BVALID - // will be low and it can go directly into the S_AXI_BVALID slot. If - // on the other hand the slave returns M_AXI_BVALID at the wrong time, - // then we'll quietly accept it and send the write interface into - // fault detected mode, setting o_write_fault. - // - // Sadly, this will create a warning in Vivado. If/when you see it, - // see this note and then just ignore it. - assign M_AXI_BREADY = 1; - - // - // Return a write acknowlegement at the end of every write - // burst--regardless of whether or not the slave does so - // - initial S_AXI_BVALID = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - S_AXI_BVALID <= 0; - else if (!S_AXI_BVALID || S_AXI_BREADY) - S_AXI_BVALID <= m_bvalid; - - // - // Set the values associated with the response - // - always @(posedge S_AXI_ACLK) - if (!S_AXI_BVALID || S_AXI_BREADY) - begin - S_AXI_BID <= m_bid; - S_AXI_BRESP <= m_bresp; - end - // }}} - - // }}} - - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Read channel processing - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // - - // - // Read address channel - // {{{ - - // S_AXI_ARREADY - // {{{ - initial S_AXI_ARREADY = (OPT_SELF_RESET) ? 0:1; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - S_AXI_ARREADY <= !OPT_SELF_RESET; - else if (S_AXI_ARVALID && S_AXI_ARREADY) - S_AXI_ARREADY <= 0; - // else if (clear_fault) - // S_AXI_ARREADY <= 1; - else if (!S_AXI_ARREADY) - S_AXI_ARREADY <= (S_AXI_RVALID && S_AXI_RLAST && S_AXI_RREADY); - // }}} - - // raddr_valid - // {{{ - generate if (OPT_SELF_RESET) - begin : GEN_READ_RESET - assign raddr_valid = !rfifo_empty; - end else begin : SIMPLE_RADDR_VALID - assign raddr_valid = !S_AXI_ARREADY; - end endgenerate - // }}} - - // r_ar* - // {{{ - // Double buffer the values associated with any read address request - // - initial r_arvalid = 0; - always @(posedge S_AXI_ACLK) - begin - if (S_AXI_ARVALID && S_AXI_ARREADY) - begin - r_arvalid <= 0; // (M_AXI_ARVALID && !M_AXI_ARREADY); - r_arid <= S_AXI_ARID; - r_araddr <= S_AXI_ARADDR; - r_arlen <= S_AXI_ARLEN; - r_arsize <= S_AXI_ARSIZE; - r_arburst <= S_AXI_ARBURST; - r_arlock <= S_AXI_ARLOCK; - r_arcache <= S_AXI_ARCACHE; - r_arprot <= S_AXI_ARPROT; - r_arqos <= S_AXI_ARQOS; - end else if (M_AXI_ARREADY) - r_arvalid <= 0; - - if (!M_AXI_ARESETN) - r_arvalid <= 0; - if (!OPT_EXCLUSIVE || !S_AXI_ARESETN) - r_arlock <= 1'b0; - end - // }}} - - // m_ar* - // {{{ - always @(*) - if (r_arvalid) - begin - m_arvalid = r_arvalid; - m_arid = r_arid; - m_araddr = r_araddr; - m_arlen = r_arlen; - m_arsize = r_arsize; - m_arburst = r_arburst; - m_arlock = r_arlock; - m_arcache = r_arcache; - m_arprot = r_arprot; - m_arqos = r_arqos; - end else begin - m_arvalid = S_AXI_ARVALID && S_AXI_ARREADY; - m_arid = S_AXI_ARID; - m_araddr = S_AXI_ARADDR; - m_arlen = S_AXI_ARLEN; - m_arsize = S_AXI_ARSIZE; - m_arburst = S_AXI_ARBURST; - m_arlock = S_AXI_ARLOCK && OPT_EXCLUSIVE; - m_arcache = S_AXI_ARCACHE; - m_arprot = S_AXI_ARPROT; - m_arqos = S_AXI_ARQOS; - end - // }}} - - // M_AXI_AR* - // {{{ - // Set the downstream values according to the transaction we've just - // received. - // - initial M_AXI_ARVALID = 0; - always @(posedge S_AXI_ACLK) - begin - if (!M_AXI_ARVALID || M_AXI_ARREADY) - begin - - if (o_read_fault) - M_AXI_ARVALID <= 0; - else - M_AXI_ARVALID <= m_arvalid; - - M_AXI_ARID <= m_arid; - M_AXI_ARADDR <= m_araddr; - M_AXI_ARLEN <= m_arlen; - M_AXI_ARSIZE <= m_arsize; - M_AXI_ARBURST <= m_arburst; - M_AXI_ARLOCK <= m_arlock && OPT_EXCLUSIVE; - M_AXI_ARCACHE <= m_arcache; - M_AXI_ARPROT <= m_arprot; - M_AXI_ARQOS <= m_arqos; - end - - if (!M_AXI_ARESETN) - M_AXI_ARVALID <= 0; - end - // }}} - - // }}} - - // - // Read fault detection - // {{{ - - // read_timer - // {{{ - // First step: a timer. The timer starts as soon as the S_AXI_ARVALID - // is accepted. Once that happens, rfifo_empty will no longer be true. - // The count is reset any time the slave produces a value for us to - // read. Once the count saturates, it stops counting. - initial read_timer = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || clear_fault) - read_timer <= 0; - else if (rfifo_empty||(S_AXI_RVALID)) - read_timer <= 0; - else if (M_AXI_RVALID) - read_timer <= 0; - else if (!(&read_timer)) - read_timer <= read_timer + 1; - // }}} - - // read_timeout - // {{{ - // Once the counter > OPT_TIMEOUT, we have a timeout condition. - // We'll detect this one clock earlier below. If we ever enter - // a read time out condition, we'll set the read fault. The read - // timeout condition can only be cleared by a reset. - initial read_timeout = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || clear_fault) - read_timeout <= 0; - else if (rfifo_empty||S_AXI_RVALID) - read_timeout <= read_timeout; - else if (M_AXI_RVALID) - read_timeout <= read_timeout; - else if (read_timer == OPT_TIMEOUT) - read_timeout <= 1; - // }}} - - // - // faulty_read_return - // {{{ - // To avoid returning a fault from the slave, it is important to - // determine within a single clock period whether or not the slaves - // return value is at fault or not. That's the purpose of the code - // below. - always @(*) - begin - faulty_read_return = 0; - if (M_AXI_RVALID) - begin - if (M_AXI_ARVALID) - // It is a fault to return data before the - // request has been accepted - faulty_read_return = 1; - if (M_AXI_RID != rfifo_id) - // It is a fault to return data from a - // different ID - faulty_read_return = 1; - if (rfifo_last && (S_AXI_RVALID || !M_AXI_RLAST)) - faulty_read_return = 1; - if (rfifo_penultimate && S_AXI_RVALID && (r_rvalid || !M_AXI_RLAST)) - faulty_read_return = 1; - if (M_AXI_RRESP == EXOKAY && (!OPT_EXCLUSIVE || !rfifo_lock)) - faulty_read_return = 1; - if (OPT_EXCLUSIVE && exread && M_AXI_RRESP == OKAY) - // Can't switch from EXOKAY to OKAY - faulty_read_return = 1; - if ((!OPT_EXCLUSIVE || (!rfifo_first && !exread)) - && M_AXI_RRESP == EXOKAY) - // Can't switch from OKAY to EXOKAY - faulty_read_return = 1; - end - end - // }}} - - // o_read_fault - // {{{ - initial o_read_fault = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || clear_fault) - o_read_fault <= 0; - else if ((!M_AXI_ARESETN && o_write_fault) || read_timeout) - o_read_fault <= 1; - else if (M_AXI_RVALID) - begin - if (faulty_read_return) - o_read_fault <= 1; - if (!raddr_valid) - // It is a fault if we haven't issued an AR* request - // yet, and a value is returned - o_read_fault <= 1; - end - // }}} - - // }}} - - // - // Read return/acknowledgment processing - // {{{ - - - // exread - // {{{ - always @(posedge S_AXI_ACLK) - if (!M_AXI_ARESETN || !OPT_EXCLUSIVE) - exread <= 0; - else if (M_AXI_RVALID && M_AXI_RREADY) - begin - if (!M_AXI_RRESP[1]) - exread <= (M_AXI_RRESP == EXOKAY); - end else if (S_AXI_RVALID && S_AXI_RREADY) - begin - if (S_AXI_RLAST) - exread <= 1'b0; - end - // }}} - - // r_rvalid - // {{{ - // Step one, set/create the read return double buffer. If r_rvalid - // is true, there's a valid value in the double buffer location. - // - initial r_rvalid = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || o_read_fault) - r_rvalid <= 0; - else if (!r_rvalid) - begin - // {{{ - // Refuse to set the double-buffer valid on any fault. - // That will also keep (below) M_AXI_RREADY high--so that - // following the fault the slave might still (pretend) to - // respond properly - if (faulty_read_return) - r_rvalid <= 0; - else if (o_read_fault) - r_rvalid <= 0; - // If there's nothing in the double buffer, then we might - // place something in there. The double buffer only gets - // filled under two conditions: 1) something is pending to be - // returned, and 2) there's another return that we can't - // stall and so need to accept here. - r_rvalid <= M_AXI_RVALID && M_AXI_RREADY - && (S_AXI_RVALID && !S_AXI_RREADY); - // }}} - end else if (S_AXI_RREADY) - // Once the up-stream read-channel clears, we can always - // clear the double buffer - r_rvalid <= 0; - // }}} - - // r_rresp, r_rdata - // {{{ - // Here's the actual values kept whenever r_rvalid is true. This is - // the double buffer. Notice that r_rid and r_last are generated - // locally, so not recorded here. - // - always @(posedge S_AXI_ACLK) - if (!r_rvalid) - begin - r_rresp <= M_AXI_RRESP; - r_rdata <= M_AXI_RDATA; - end - // }}} - - // M_AXI_RREADY - // {{{ - // Stall the downstream channel any time there's something in the - // double buffer. In spite of the ! here, this is a registered value. - assign M_AXI_RREADY = !r_rvalid; - // }}} - - // rfifo_id, rfifo_lock - // {{{ - // Copy the ID for later comparisons on the return - always @(*) - rfifo_id = r_arid; - always @(*) - rfifo_lock = r_arlock; - // }}} - - // rfifo_[counter|empty|last|penultimate - // {{{ - // Count the number of outstanding read elements. This is the number - // of read returns we still expect--from the upstream perspective. The - // downstream perspective will be off by both what's waiting for - // S_AXI_RREADY and what's in the double buffer - // - initial rfifo_counter = 0; - initial rfifo_empty = 1; - initial rfifo_last = 0; - initial rfifo_penultimate= 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - begin - rfifo_counter <= 0; - rfifo_empty <= 1; - rfifo_last <= 0; - rfifo_penultimate<= 0; - end else if (S_AXI_ARVALID && S_AXI_ARREADY) - begin - rfifo_counter <= S_AXI_ARLEN+1; - rfifo_empty <= 0; - rfifo_last <= (S_AXI_ARLEN == 0); - rfifo_penultimate <= (S_AXI_ARLEN == 1); - end else if (!rfifo_empty) - begin - if (S_AXI_RVALID && S_AXI_RREADY) - begin - rfifo_counter <= rfifo_counter - 1; - rfifo_empty <= (rfifo_counter <= 1); - rfifo_last <= (rfifo_counter == 2); - rfifo_penultimate <= (rfifo_counter == 3); - end - end - // }}} - - // lock_active - // {{{ - generate if (OPT_EXCLUSIVE) - begin : CALC_LOCK_ACTIVE - // {{{ - genvar gk; - - for(gk=0; gk<(1<<IW); gk=gk+1) - begin : LOCK_PER_ID - reg r_lock_active; - - initial r_lock_active = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || !M_AXI_ARESETN - || faulty_read_return || faulty_write_return) - r_lock_active <= 0; - else if (M_AXI_RVALID && M_AXI_RREADY && rfifo_lock - && !S_AXI_ARREADY - && r_arid == gk[IW-1:0] - &&(!faulty_read_return && !o_read_fault) - && M_AXI_RRESP == EXOKAY) - r_lock_active <= 1; - else if (M_AXI_BVALID && M_AXI_BREADY && wfifo_lock - && r_awid == gk[IW-1:0] - && (S_AXI_ARREADY - || r_arid != gk[IW-1:0] - || !r_arlock) - && M_AXI_BRESP == OKAY) - r_lock_active <= 0; - else if (S_AXI_ARVALID && S_AXI_ARREADY && S_AXI_ARLOCK - && S_AXI_ARID == gk[IW-1:0]) - r_lock_active <= 0; - - assign lock_active[gk] = r_lock_active; - end - // }}} - end else begin : LOCK_NEVER_ACTIVE - // {{{ - assign lock_active = 0; - - // Keep Verilator happy - // Verilator lint_off UNUSED - wire unused_lock; - assign unused_lock = &{ 1'b0, wfifo_lock }; - // Verilator lint_on UNUSED - // }}} - end endgenerate - // }}} - - // rfifo_first - // {{{ - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || !OPT_EXCLUSIVE) - rfifo_first <= 1'b0; - else if (S_AXI_ARVALID && S_AXI_ARREADY) - rfifo_first <= 1'b1; - else if (M_AXI_RVALID && M_AXI_RREADY) - rfifo_first <= 1'b0; - else if (o_read_fault) - rfifo_first <= 1'b0; - // }}} - - // m_rvalid, m_rresp - // {{{ - // Determine values to send back and return - // - // This data set includes all the return values, even though only - // RRESP and RVALID are set in this block. - always @(*) - if (o_read_fault || (!M_AXI_ARESETN && OPT_SELF_RESET)) - begin - m_rvalid = !rfifo_empty; - if (S_AXI_RVALID && rfifo_last) - m_rvalid = 0; - m_rresp = SLAVE_ERROR; - end else if (r_rvalid) - begin - m_rvalid = r_rvalid; - m_rresp = r_rresp; - end else begin - m_rvalid = M_AXI_RVALID && raddr_valid && !faulty_read_return; - m_rresp = M_AXI_RRESP; - end - // }}} - - // m_rid - // {{{ - // We've stored the ID locally, so that our response will never be in - // error - always @(*) - m_rid = rfifo_id; - // }}} - - // m_rlast - // {{{ - // Ideally, we'd want to say m_rlast = rfifo_last. However, we might - // have a value in S_AXI_RVALID already. In that case, the last - // value can only be true if we are one further away from the end. - // (Remember, rfifo_last and rfifo_penultimate are both dependent upon - // the *upstream* number of read values outstanding, not the downstream - // number which we can't trust in all cases) - always @(*) - if (S_AXI_RVALID) - m_rlast = rfifo_penultimate; - else - m_rlast = (rfifo_last); - // }}} - - // m_rdata - // {{{ - // In the case of a fault, rdata is a don't care. Therefore we can - // always set it based upon the values returned from the slave. - always @(*) - if (r_rvalid) - m_rdata = r_rdata; - else - m_rdata = M_AXI_RDATA; - // }}} - - // S_AXI_R* - // {{{ - // Record our return data values - // - // These are the values from either the slave, the double buffer, - // or an error value bypassing either as determined by the m_* values. - // Per spec, all of these values must be registered. First the valid - // signal - initial S_AXI_RVALID = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - S_AXI_RVALID <= 0; - else if (!S_AXI_RVALID || S_AXI_RREADY) - S_AXI_RVALID <= m_rvalid; - - // Then the various slave data channels - always @(posedge S_AXI_ACLK) - if (!S_AXI_RVALID || S_AXI_RREADY) - begin - S_AXI_RID <= m_rid; - S_AXI_RRESP <= m_rresp; - S_AXI_RLAST <= m_rlast; - S_AXI_RDATA <= m_rdata; - end - // }}} - - // }}} - - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Self-reset - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // - generate if (OPT_SELF_RESET) - begin : GEN_SELFRESET - // {{{ - // Declarations - // {{{ - reg [4:0] reset_counter; - reg r_clear_fault, w_clear_fault; - wire reset_timeout; - // }}} - - // M_AXI_ARESETN - // {{{ - initial M_AXI_ARESETN = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - M_AXI_ARESETN <= 0; - else if (clear_fault) - M_AXI_ARESETN <= 1; - else if (o_read_fault || o_write_fault) - M_AXI_ARESETN <= 0; - // }}} - - // reset_counter - // {{{ - initial reset_counter = 0; - always @(posedge S_AXI_ACLK) - if (M_AXI_ARESETN) - reset_counter <= 0; - else if (!reset_timeout) - reset_counter <= reset_counter+1; - // }}} - - assign reset_timeout = reset_counter[4]; - - // r_clear_fault - // {{{ - initial r_clear_fault <= 1; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN) - r_clear_fault <= 1; - else if (!M_AXI_ARESETN && !reset_timeout) - r_clear_fault <= 0; - else if (!o_read_fault && !o_write_fault) - r_clear_fault <= 0; - else if (raddr_valid || waddr_valid) - r_clear_fault <= 0; - else - r_clear_fault <= 1; - // }}} - - // clear_fault - // {{{ - always @(*) - if (S_AXI_AWVALID || S_AXI_ARVALID) - w_clear_fault = 0; - else if (raddr_valid || waddr_valid) - w_clear_fault = 0; - else - w_clear_fault = r_clear_fault; - - assign clear_fault = w_clear_fault; - // }}} - - // }}} - end else begin : NO_SELFRESET - // {{{ - always @(*) - M_AXI_ARESETN = S_AXI_ARESETN; - assign clear_fault = 0; - // }}} - end endgenerate - // }}} - - // Make Verilator happy - // {{{ - // Verilator lint_off UNUSED - wire unused; - assign unused = &{ 1'b0 }; - // Verilator lint_on UNUSED - // }}} -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// -// Formal properties -// {{{ -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -`ifdef FORMAL - // {{{ - // Below are just some of the formal properties used to verify - // this core. The full property set is maintained elsewhere. - // - parameter [0:0] F_OPT_FAULTLESS = 1; - - // - // ... - // }}} - - faxi_slave #( - // {{{ - .C_AXI_ID_WIDTH(C_S_AXI_ID_WIDTH), - .C_AXI_DATA_WIDTH(C_S_AXI_DATA_WIDTH), - .C_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH) - // ... - // }}} - ) f_slave( - // {{{ - .i_clk(S_AXI_ACLK), - .i_axi_reset_n(S_AXI_ARESETN), - // - // Address write channel - // {{{ - .i_axi_awid(S_AXI_AWID), - .i_axi_awaddr(S_AXI_AWADDR), - .i_axi_awlen(S_AXI_AWLEN), - .i_axi_awsize(S_AXI_AWSIZE), - .i_axi_awburst(S_AXI_AWBURST), - .i_axi_awlock(S_AXI_AWLOCK), - .i_axi_awcache(S_AXI_AWCACHE), - .i_axi_awprot(S_AXI_AWPROT), - .i_axi_awqos(S_AXI_AWQOS), - .i_axi_awvalid(S_AXI_AWVALID), - .i_axi_awready(S_AXI_AWREADY), - // }}} - // Write Data Channel - // {{{ - .i_axi_wdata(S_AXI_WDATA), - .i_axi_wstrb(S_AXI_WSTRB), - .i_axi_wlast(S_AXI_WLAST), - .i_axi_wvalid(S_AXI_WVALID), - .i_axi_wready(S_AXI_WREADY), - // }}} - // Write response channel - // {{{ - .i_axi_bid(S_AXI_BID), - .i_axi_bresp(S_AXI_BRESP), - .i_axi_bvalid(S_AXI_BVALID), - .i_axi_bready(S_AXI_BREADY), - // }}} - // Read address channel - // {{{ - .i_axi_arid(S_AXI_ARID), - .i_axi_araddr(S_AXI_ARADDR), - .i_axi_arlen(S_AXI_ARLEN), - .i_axi_arsize(S_AXI_ARSIZE), - .i_axi_arburst(S_AXI_ARBURST), - .i_axi_arlock(S_AXI_ARLOCK), - .i_axi_arcache(S_AXI_ARCACHE), - .i_axi_arprot(S_AXI_ARPROT), - .i_axi_arqos(S_AXI_ARQOS), - .i_axi_arvalid(S_AXI_ARVALID), - .i_axi_arready(S_AXI_ARREADY), - // }}} - // Read data return channel - // {{{ - .i_axi_rvalid(S_AXI_RVALID), - .i_axi_rready(S_AXI_RREADY), - .i_axi_rid(S_AXI_RID), - .i_axi_rdata(S_AXI_RDATA), - .i_axi_rresp(S_AXI_RRESP), - .i_axi_rlast(S_AXI_RLAST), - // }}} - // Formal induction values - // {{{ - .f_axi_awr_nbursts(f_axi_awr_nbursts), - .f_axi_wr_pending(f_axi_wr_pending), - .f_axi_rd_nbursts(f_axi_rd_nbursts), - .f_axi_rd_outstanding(f_axi_rd_outstanding) - // - // ... - // }}} - // }}} - ); - - //////////////////////////////////////////////////////////////////////// - // - // Write induction properties - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // - - // 1. We will only ever handle a single burst--never any more - always @(*) - assert(f_axi_awr_nbursts <= 1); - - always @(*) - if (f_axi_awr_nbursts == 1) - begin - assert(!S_AXI_AWREADY); - if (S_AXI_BVALID) - assert(f_axi_wr_pending == 0); - if (!o_write_fault && M_AXI_AWVALID) - assert(f_axi_wr_pending == M_AXI_AWLEN + 1 - - (M_AXI_WVALID ? 1:0) - - (r_wvalid ? 1 : 0)); - if (!o_write_fault && f_axi_wr_pending > 0) - assert((!M_AXI_WVALID || !M_AXI_WLAST) - &&(!r_wvalid || !r_wlast)); - if (!o_write_fault && M_AXI_WVALID && M_AXI_WLAST) - assert(!r_wvalid || !r_wlast); - end else begin - assert(s_wbursts == 0); - assert(!S_AXI_WREADY); - if (OPT_SELF_RESET) - begin - assert(1 || S_AXI_AWREADY || !M_AXI_ARESETN || !S_AXI_ARESETN); - end else - assert(S_AXI_AWREADY); - end - - // - // ... - // - - // - // AWREADY will always be low mid-burst - always @(posedge S_AXI_ACLK) - if (!f_past_valid || $past(!S_AXI_ARESETN)) - begin - assert(S_AXI_AWREADY == !OPT_SELF_RESET); - end else if (f_axi_wr_pending > 0) - begin - assert(!S_AXI_AWREADY); - end else if (s_wbursts) - begin - assert(!S_AXI_AWREADY); - end else if (!OPT_SELF_RESET) - begin - assert(S_AXI_AWREADY); - end else if (!o_write_fault && !o_read_fault) - assert(S_AXI_AWREADY || OPT_SELF_RESET); - - always @(*) - if (f_axi_wr_pending > 0) - begin - assert(s_wbursts == 0); - end else if (f_axi_awr_nbursts > 0) - begin - assert((s_wbursts ? 1:0) == f_axi_awr_nbursts); - end else - assert(s_wbursts == 0); - - always @(*) - if (!o_write_fault && S_AXI_AWREADY) - assert(!M_AXI_AWVALID); - - always @(*) - if (M_AXI_ARESETN && (f_axi_awr_nbursts == 0)) - begin - assert(o_write_fault || !M_AXI_AWVALID); - assert(!S_AXI_BVALID); - assert(s_wbursts == 0); - end else if (M_AXI_ARESETN && s_wbursts == 0) - assert(f_axi_wr_pending > 0); - - always @(*) - if (S_AXI_WREADY) - begin - assert(waddr_valid); - end else if (f_axi_wr_pending > 0) - begin - if (!o_write_fault) - assert(M_AXI_WVALID && r_wvalid); - end - - always @(*) - if (!OPT_SELF_RESET) - begin - assert(waddr_valid == !S_AXI_AWREADY); - end else begin - // ... - assert(waddr_valid == (f_axi_awr_nbursts > 0)); - end - - always @(*) - if (S_AXI_ARESETN && !o_write_fault && f_axi_wr_pending > 0 && !S_AXI_WREADY) - assert(M_AXI_WVALID); - - always @(*) - if (S_AXI_ARESETN && !o_write_fault && m_wempty) - begin - assert(M_AXI_AWVALID || !M_AXI_WVALID); - assert(M_AXI_AWVALID || f_axi_wr_pending == 0); - end - - always @(*) - if (S_AXI_ARESETN && M_AXI_AWVALID) - begin - if (!o_write_fault && !M_AXI_AWVALID) - begin - assert(f_axi_wr_pending + (M_AXI_WVALID ? 1:0) + (r_wvalid ? 1:0) == m_wpending); - end else if (!o_write_fault) - begin - assert(f_axi_wr_pending == M_AXI_AWLEN + 1 - (M_AXI_WVALID ? 1:0) - (r_wvalid ? 1:0)); - assert(m_wpending == 0); - end - end - - always @(*) - assert(m_wpending <= 9'h100); - - always @(*) - if (M_AXI_ARESETN && (!o_write_fault)&&(f_axi_awr_nbursts == 0)) - assert(!M_AXI_AWVALID); - - always @(*) - if (S_AXI_ARESETN && !o_write_fault) - begin - if (f_axi_awr_nbursts == 0) - begin - assert(!M_AXI_AWVALID); - assert(!M_AXI_WVALID); - end - - if (!M_AXI_AWVALID) - assert(f_axi_wr_pending - +(M_AXI_WVALID ? 1:0) - + (r_wvalid ? 1:0) - == m_wpending); - if (f_axi_awr_nbursts == (S_AXI_BVALID ? 1:0)) - begin - assert(!M_AXI_AWVALID); - assert(!M_AXI_WVALID); - end - - if (S_AXI_BVALID) - assert(f_axi_awr_nbursts == 1); - - if (M_AXI_AWVALID) - assert(m_wpending == 0); - - if (S_AXI_AWREADY) - assert(!M_AXI_AWVALID); - end - - always @(*) - assert(!r_awvalid); - - always @(*) - assert(m_wempty == (m_wpending == 0)); - always @(*) - assert(m_wlastctr == (m_wpending == 1)); - - // - // Verify the contents of the skid buffers - // - - // - // ... - // - - always @(*) - if (write_timer > OPT_TIMEOUT) - assert(o_write_fault || write_timeout); - - always @(*) - if (!OPT_SELF_RESET) - begin - assert(waddr_valid == !S_AXI_AWREADY); - end else if (waddr_valid) - assert(!S_AXI_AWREADY); - - always @(*) - if (!o_write_fault && M_AXI_ARESETN) - assert(waddr_valid == !S_AXI_AWREADY); - - always @(*) - if (f_axi_wr_pending == 0) - assert(!S_AXI_WREADY); - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Read induction properties - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // - - always @(*) - assert(f_axi_rd_nbursts <= 1); - always @(*) - assert(raddr_valid == (f_axi_rd_nbursts>0)); - always @(*) - if (f_axi_rdid_nbursts > 0) - begin - assert(rfifo_id == f_axi_rd_checkid); - end else if (f_axi_rd_nbursts > 0) - assert(rfifo_id != f_axi_rd_checkid); - - always @(*) - if (f_axi_rd_nbursts > 0) - assert(raddr_valid); - - always @(*) - if (raddr_valid) - assert(!S_AXI_ARREADY); - - always @(*) - if (!OPT_SELF_RESET) - begin - assert(raddr_valid == !S_AXI_ARREADY); - end else begin - // ... - assert(raddr_valid == (f_axi_rd_nbursts > 0)); - end - - // - // ... - // - - always @(*) - if (f_axi_rd_outstanding == 0) - assert(!raddr_valid || OPT_SELF_RESET); - - always @(*) - if (!o_read_fault && S_AXI_ARREADY) - assert(!M_AXI_ARVALID); - - // Our "FIFO" counter - always @(*) - assert(rfifo_counter == f_axi_rd_outstanding); - - always @(*) - begin - assert(rfifo_empty == (rfifo_counter == 0)); - assert(rfifo_last == (rfifo_counter == 1)); - assert(rfifo_penultimate == (rfifo_counter == 2)); - end - - // - // ... - // - - always @(*) - if (r_arvalid) - assert(skid_arvalid); - - always @(*) - if (read_timer > OPT_TIMEOUT) - assert(read_timeout); - - - always @(posedge S_AXI_ACLK) - if (OPT_SELF_RESET && (!f_past_valid || !$past(M_AXI_ARESETN))) - begin - assume(!M_AXI_BVALID); - assume(!M_AXI_RVALID); - end - - always @(*) - if (!o_read_fault && M_AXI_ARESETN) - assert(raddr_valid == !S_AXI_ARREADY); - - always @(*) - if (f_axi_rd_nbursts > 0) - assert(raddr_valid); - - always @(*) - if (S_AXI_ARESETN && OPT_SELF_RESET) - begin - if (!M_AXI_ARESETN) - assert(o_read_fault || o_write_fault /* ... */ ); - end - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Exclusive access property checking - // {{{ - // - //////////////////////////////////////////////////////////////////////// - // - // ... - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Cover properties - // - //////////////////////////////////////////////////////////////////////// - // - // }}} - - //////////////////////////////////////////////////////////////////////// - // - // Good interface check - // - //////////////////////////////////////////////////////////////////////// - // - // - generate if (F_OPT_FAULTLESS) - begin : ASSUME_FAULTLESS - // {{{ - // - // ... - // - - faxi_master #( - // {{{ - .C_AXI_ID_WIDTH(C_S_AXI_ID_WIDTH), - .C_AXI_DATA_WIDTH(C_S_AXI_DATA_WIDTH), - .C_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH) - // ... - // }}} - ) f_master( - // {{{ - .i_clk(S_AXI_ACLK), - .i_axi_reset_n(M_AXI_ARESETN), - // - // Address write channel - // {{{ - .i_axi_awid(M_AXI_AWID), - .i_axi_awaddr(M_AXI_AWADDR), - .i_axi_awlen(M_AXI_AWLEN), - .i_axi_awsize(M_AXI_AWSIZE), - .i_axi_awburst(M_AXI_AWBURST), - .i_axi_awlock(M_AXI_AWLOCK), - .i_axi_awcache(M_AXI_AWCACHE), - .i_axi_awprot(M_AXI_AWPROT), - .i_axi_awqos(M_AXI_AWQOS), - .i_axi_awvalid(M_AXI_AWVALID), - .i_axi_awready(M_AXI_AWREADY), - // }}} - // Write Data Channel - // {{{ - .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_wlast(M_AXI_WLAST), - // }}} - // Write response channel - // {{{ - .i_axi_bvalid(M_AXI_BVALID), - .i_axi_bready(M_AXI_BREADY), - .i_axi_bid(M_AXI_BID), - .i_axi_bresp(M_AXI_BRESP), - // }}} - // Read address channel - // {{{ - .i_axi_arid(M_AXI_ARID), - .i_axi_araddr(M_AXI_ARADDR), - .i_axi_arlen(M_AXI_ARLEN), - .i_axi_arsize(M_AXI_ARSIZE), - .i_axi_arburst(M_AXI_ARBURST), - .i_axi_arlock(M_AXI_ARLOCK), - .i_axi_arcache(M_AXI_ARCACHE), - .i_axi_arprot(M_AXI_ARPROT), - .i_axi_arqos(M_AXI_ARQOS), - .i_axi_arvalid(M_AXI_ARVALID), - .i_axi_arready(M_AXI_ARREADY), - // }}} - // Read data return channel - // {{{ - .i_axi_rvalid(M_AXI_RVALID), - .i_axi_rready(M_AXI_RREADY), - .i_axi_rid(M_AXI_RID), - .i_axi_rdata(M_AXI_RDATA), - .i_axi_rresp(M_AXI_RRESP), - .i_axi_rlast(M_AXI_RLAST), - // }}} - // Formal outputs - // {{{ - .f_axi_awr_nbursts(fm_axi_awr_nbursts), - .f_axi_wr_pending(fm_axi_wr_pending), - .f_axi_rd_nbursts(fm_axi_rd_nbursts), - .f_axi_rd_outstanding(fm_axi_rd_outstanding) - // - // ... - // }}} - // }}} - ); - - //////////////////////////////////////////////////////////////// - // - // Contract: If the downstream has no faults, then we - // shouldn't detect any here. - // {{{ - //////////////////////////////////////////////////////////////// - // - // - - always @(*) - if (OPT_SELF_RESET) - begin - assert(!o_write_fault || !M_AXI_ARESETN); - end else - assert(!o_write_fault); - - always @(*) - if (OPT_SELF_RESET) - begin - assert(!o_read_fault || !M_AXI_ARESETN); - end else - assert(!o_read_fault); - - always @(*) - if (OPT_SELF_RESET) - begin - assert(!read_timeout || !M_AXI_ARESETN); - end else - assert(!read_timeout); - - always @(*) - if (OPT_SELF_RESET) - begin - assert(!write_timeout || !M_AXI_ARESETN); - end else - assert(!write_timeout); - - always @(*) - if (S_AXI_AWREADY) - assert(!M_AXI_AWVALID); - - // - // ... - // - - always @(*) - if (M_AXI_ARESETN && f_axi_rd_nbursts > 0) - assert(f_axi_rd_nbursts == fm_axi_rd_nbursts - + (M_AXI_ARVALID ? 1 : 0) - + (r_rvalid&&m_rlast ? 1 : 0) - + (S_AXI_RVALID&&S_AXI_RLAST ? 1 : 0)); - - always @(*) - if (M_AXI_ARESETN && f_axi_rd_outstanding > 0) - assert(f_axi_rd_outstanding == fm_axi_rd_outstanding - + (M_AXI_ARVALID ? M_AXI_ARLEN+1 : 0) - + (r_rvalid ? 1 : 0) - + (S_AXI_RVALID ? 1 : 0)); - - // - // ... - // - always @(*) - if (M_AXI_RVALID) - assert(!M_AXI_ARVALID); - - always @(*) - if (S_AXI_ARESETN) - assert(m_wpending == fm_axi_wr_pending); - - always @(*) - if (S_AXI_ARESETN && fm_axi_awr_nbursts > 0) - begin - assert(fm_axi_awr_nbursts== f_axi_awr_nbursts); - assert(fm_axi_awr_nbursts == 1); - // - // ... - // - end - // }}} - //////////////////////////////////////////////////////////////// - // - // Exclusive address checking - // {{{ - //////////////////////////////////////////////////////////////// - // - // - - // - // - // ... - // - - //////////////////////////////////////////////////////////////// - // - // Cover checks - // {{{ - //////////////////////////////////////////////////////////////// - // - // - - // }}} - //////////////////////////////////////////////////////////////// - // - // "Careless" assumptions - // {{{ - //////////////////////////////////////////////////////////////// - // - // - end endgenerate - - // - // ... - // - - //////////////////////////////////////////////////////////////////////// - // - // Never path check - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // - (* anyconst *) reg [C_S_AXI_ADDR_WIDTH-1:0] fc_never_write_addr, - fc_never_read_addr; - (* anyconst *) reg [C_S_AXI_DATA_WIDTH + C_S_AXI_DATA_WIDTH/8-1:0] - fc_never_write_data; - (* anyconst *) reg [C_S_AXI_DATA_WIDTH-1:0] fc_never_read_data; - - // Write address - // {{{ - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && S_AXI_AWVALID) - assume(S_AXI_AWADDR != fc_never_write_addr); - - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && !o_write_fault && M_AXI_ARESETN && M_AXI_AWVALID) - assert(M_AXI_AWADDR != fc_never_write_addr); - // }}} - - // Write data - // {{{ - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && S_AXI_WVALID) - assume({ S_AXI_WDATA, S_AXI_WSTRB } != fc_never_write_data); - - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && !o_write_fault && M_AXI_ARESETN && M_AXI_WVALID) - begin - if (lock_failed) - assert(M_AXI_WSTRB == 0); - else - assert({ M_AXI_WDATA, M_AXI_WSTRB } != fc_never_write_data); - end - // }}} - - // Read address - // {{{ - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && S_AXI_ARVALID) - assume(S_AXI_ARADDR != fc_never_read_addr); - - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && r_arvalid) - assume(r_araddr != fc_never_read_addr); - - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && !o_read_fault && M_AXI_ARESETN && M_AXI_ARVALID) - assert(M_AXI_ARADDR != fc_never_read_addr); - // }}} - - // Read data - // {{{ - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && M_AXI_ARESETN && M_AXI_RVALID) - assume(M_AXI_RDATA != fc_never_read_data); - - always @(posedge S_AXI_ACLK) - if (S_AXI_ARESETN && S_AXI_RVALID && S_AXI_RRESP != SLAVE_ERROR) - assert(S_AXI_RDATA != fc_never_read_data); - // }}} - - // }}} - //////////////////////////////////////////////////////////////////////// - // - // Cover properties - // {{{ - //////////////////////////////////////////////////////////////////////// - // - // We'll use these to determine the best performance this core - // can achieve - // - reg [4:0] f_dbl_rd_count, f_dbl_wr_count; - reg [4:0] f_rd_count, f_wr_count; - - // f_wr_count - // {{{ - initial f_wr_count = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || o_write_fault) - f_wr_count <= 0; - else if (S_AXI_BVALID && S_AXI_BREADY) - begin - if (!(&f_wr_count)) - f_wr_count <= f_wr_count + 1; - end - // }}} - - // f_dbl_wr_count - // {{{ - initial f_dbl_wr_count = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || o_write_fault||(S_AXI_AWVALID && S_AXI_AWLEN < 3)) - f_dbl_wr_count <= 0; - else if (S_AXI_BVALID && S_AXI_BREADY) - begin - if (!(&f_dbl_wr_count)) - f_dbl_wr_count <= f_dbl_wr_count + 1; - end - // }}} - - // f_rd_count - // {{{ - initial f_rd_count = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || o_read_fault) - f_rd_count <= 0; - else if (S_AXI_RVALID && S_AXI_RREADY && S_AXI_RLAST) - begin - if (!(&f_rd_count)) - f_rd_count <= f_rd_count + 1; - end - // }}} - - // f_dbl_rd_count - // {{{ - initial f_dbl_rd_count = 0; - always @(posedge S_AXI_ACLK) - if (!S_AXI_ARESETN || o_read_fault||(S_AXI_ARVALID && S_AXI_ARLEN < 3)) - f_dbl_rd_count <= 0; - else if (S_AXI_RVALID && S_AXI_RREADY && S_AXI_RLAST) - begin - if (!(&f_dbl_rd_count)) - f_dbl_rd_count <= f_dbl_rd_count + 1; - end - // }}} - - // Can we complete a single write burst without fault? - // {{{ - always @(*) - if (S_AXI_ARESETN) - cover((f_wr_count > 1) && (!o_write_fault)); - - always @(*) - if (S_AXI_ARESETN) - cover((f_dbl_wr_count > 1) && (!o_write_fault)); - // }}} - - // Can we complete four write bursts without fault? (and return to idle) - // {{{ - always @(*) - if (S_AXI_ARESETN) - cover((f_wr_count > 3) && (!o_write_fault) - &&(!S_AXI_AWVALID && !S_AXI_WVALID - && !S_AXI_BVALID) - && (f_axi_awr_nbursts == 0) - && (f_axi_wr_pending == 0)); - - always @(*) - if (S_AXI_ARESETN) - cover((f_dbl_wr_count > 3) && (!o_write_fault) - &&(!S_AXI_AWVALID && !S_AXI_WVALID - && !S_AXI_BVALID) - && (f_axi_awr_nbursts == 0) - && (f_axi_wr_pending == 0)); - // }}} - - // Can we complete a single read burst without fault? - // {{{ - always @(*) - if (S_AXI_ARESETN) - cover((f_rd_count > 1) && (!o_read_fault)); - - always @(*) - if (S_AXI_ARESETN) - cover((f_dbl_rd_count > 1) && (!o_read_fault)); - // }}} - - // Can we complete four read bursts without fault? - // {{{ - always @(*) - if (S_AXI_ARESETN) - cover((f_rd_count > 3) && (f_axi_rd_nbursts == 0) - && !S_AXI_ARVALID && !S_AXI_RVALID); - - always @(*) - if (S_AXI_ARESETN) - cover((f_dbl_rd_count > 3) && (f_axi_rd_nbursts == 0) - && !S_AXI_ARVALID && !S_AXI_RVALID); - // }}} -`endif -// }}} -endmodule -`ifndef YOSYS -`default_nettype wire -`endif |
