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

Subversion Repositories wb2axip

[/] [wb2axip/] [trunk/] [rtl/] [aximrd2wbsp.v] - Diff between revs 8 and 16

Show entire file | Details | Blame | View Log

Rev 8 Rev 16
Line 5... Line 5...
// Project:     Pipelined Wishbone to AXI converter
// Project:     Pipelined Wishbone to AXI converter
//
//
// Purpose:     Bridge an AXI read channel pair to a single wishbone read
// Purpose:     Bridge an AXI read channel pair to a single wishbone read
//              channel.
//              channel.
//
//
 
// Rules:
 
//      1. Any read channel error *must* be returned to the correct
 
//              read channel ID.  In other words, we can't pipeline between IDs
 
//      2. A FIFO must be used on getting a WB return, to make certain that
 
//              the AXI return channel is able to stall with no loss
 
//      3. No request can be accepted unless there is room in the return
 
//              channel for it
 
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2016, Gisselquist Technology, LLC
// Copyright (C) 2019, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This file is part of the pipelined Wishbone to AXI converter project, a
// modify it under the terms of  the GNU General Public License as published
// project that contains multiple bus bridging designs and formal bus property
// by the Free Software Foundation, either version 3 of the License, or (at
// sets.
// your option) any later version.
//
//
// The bus bridge designs and property sets are free RTL designs: you can
// This program is distributed in the hope that it will be useful, but WITHOUT
// redistribute them and/or modify any of them under the terms of the GNU
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// Lesser General Public License as published by the Free Software Foundation,
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// either version 3 of the License, or (at your option) any later version.
// for more details.
//
//
// The bus bridge designs and property sets are distributed in the hope that
// You should have received a copy of the GNU General Public License along
// they will be useful, but WITHOUT ANY WARRANTY; without even the implied
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// warranty of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// target there if the PDF file isn't present.)  If not, see
// GNU Lesser General Public License for more details.
 
//
 
// You should have received a copy of the GNU Lesser General Public License
 
// along with these designs.  (It's in the $(ROOT)/doc directory.  Run make
 
// with no target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     LGPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/lgpl.html
//
 
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
`default_nettype        none
`default_nettype        none
//
//
 
// module       aximrd2wbsp #(
module  aximrd2wbsp #(
module  aximrd2wbsp #(
        parameter C_AXI_ID_WIDTH        = 6, // The AXI id width used for R&W
        parameter C_AXI_ID_WIDTH        = 6, // The AXI id width used for R&W
                                             // This is an int between 1-16
                                             // This is an int between 1-16
        parameter C_AXI_DATA_WIDTH      = 32,// Width of the AXI R&W data
        parameter C_AXI_DATA_WIDTH      = 32,// Width of the AXI R&W data
        parameter C_AXI_ADDR_WIDTH      = 28,   // AXI Address width
        parameter C_AXI_ADDR_WIDTH      = 28,   // AXI Address width
        parameter AW                    = 26,   // AXI Address width
        parameter AW                    = 26,   // AXI Address width
        parameter LGFIFO                =  4
        parameter LGFIFO                =  9    // Must be >= 8
        // parameter    WBMODE          = "B4PIPELINE"
        // parameter    WBMODE          = "B4PIPELINE"
                // Could also be "BLOCK"
                // Could also be "BLOCK"
        ) (
        ) (
        input   wire                    i_axi_clk,      // Bus clock
        input   wire                    i_axi_clk,      // Bus clock
        input   wire                    i_axi_reset_n,  // Bus reset
        input   wire                    i_axi_reset_n,  // Bus reset
 
 
// AXI read address channel signals
// AXI read address channel signals
        output  wire                    o_axi_arready,  // Read address ready
        output  reg                     o_axi_arready,  // Read address ready
        input   wire    [C_AXI_ID_WIDTH-1:0]     i_axi_arid,     // Read ID
        input   wire    [C_AXI_ID_WIDTH-1:0]     i_axi_arid,     // Read ID
        input   wire    [C_AXI_ADDR_WIDTH-1:0]   i_axi_araddr,   // Read address
        input   wire    [C_AXI_ADDR_WIDTH-1:0]   i_axi_araddr,   // Read address
        input   wire    [7:0]            i_axi_arlen,    // Read Burst Length
        input   wire    [7:0]            i_axi_arlen,    // Read Burst Length
        input   wire    [2:0]            i_axi_arsize,   // Read Burst size
        input   wire    [2:0]            i_axi_arsize,   // Read Burst size
        input   wire    [1:0]            i_axi_arburst,  // Read Burst type
        input   wire    [1:0]            i_axi_arburst,  // Read Burst type
Line 73... Line 85...
        input   wire                    i_axi_rready,  // Read Response ready
        input   wire                    i_axi_rready,  // Read Response ready
 
 
        // We'll share the clock and the reset
        // We'll share the clock and the reset
        output  reg                             o_wb_cyc,
        output  reg                             o_wb_cyc,
        output  reg                             o_wb_stb,
        output  reg                             o_wb_stb,
        output  wire [(AW-1):0]  o_wb_addr,
        output  reg [(AW-1):0]                   o_wb_addr,
        input   wire                            i_wb_ack,
        input   wire                            i_wb_ack,
        input   wire                            i_wb_stall,
        input   wire                            i_wb_stall,
        input   [(C_AXI_DATA_WIDTH-1):0] i_wb_data,
        input   wire [(C_AXI_DATA_WIDTH-1):0]    i_wb_data,
        input   wire                            i_wb_err
        input   wire                            i_wb_err
 
`ifdef  FORMAL
 
        // ,
 
        // output       wire    [LGFIFO-1:0]            f_fifo_head,
 
        // output       wire    [LGFIFO-1:0]            f_fifo_neck,
 
        // output       wire    [LGFIFO-1:0]            f_fifo_torso,
 
        // output       wire    [LGFIFO-1:0]            f_fifo_tail
 
`endif
        );
        );
 
 
        localparam      DW = C_AXI_DATA_WIDTH;
        localparam      DW = C_AXI_DATA_WIDTH;
 
 
        wire    w_reset;
        wire    w_reset;
        assign  w_reset = (i_axi_reset_n == 1'b0);
        assign  w_reset = (i_axi_reset_n == 1'b0);
 
 
 
 
        reg     [(C_AXI_ID_WIDTH+AW+1)-1:0]      afifo   [0:((1<<(LGFIFO))-1)];
        wire    [C_AXI_ID_WIDTH+C_AXI_ADDR_WIDTH+25-1:0] i_rd_request;
        reg     [(DW+1)-1:0]                     dfifo   [0:((1<<(LGFIFO))-1)];
        reg     [C_AXI_ID_WIDTH+C_AXI_ADDR_WIDTH+25-1:0] r_rd_request;
        reg     [(C_AXI_ID_WIDTH+AW+1)-1:0]      fifo_at_neck, afifo_at_tail;
        wire    [C_AXI_ID_WIDTH+C_AXI_ADDR_WIDTH+25-1:0] w_rd_request;
        reg     [(DW+1)-1:0]                     dfifo_at_tail;
 
 
        reg     [LGFIFO:0]       next_ackptr, next_rptr;
 
 
 
        reg     [C_AXI_ID_WIDTH:0]       request_fifo    [0:((1<<LGFIFO)-1)];
 
        reg     [C_AXI_ID_WIDTH:0]       rsp_data;
 
 
 
        reg     [C_AXI_DATA_WIDTH:0]     response_fifo   [0:((1<<LGFIFO)-1)];
 
        reg     [C_AXI_DATA_WIDTH:0]     ack_data;
 
 
 
        reg                             advance_ack;
 
 
 
 
 
        reg                     r_valid, last_stb, last_ack, err_state;
 
        reg     [C_AXI_ID_WIDTH-1:0]     axi_id;
 
        reg     [LGFIFO:0]       fifo_wptr, fifo_ackptr, fifo_rptr;
 
        reg             incr;
 
        reg     [7:0]    stblen;
 
 
 
        wire    [C_AXI_ID_WIDTH-1:0]     w_id;//    r_id;
 
        wire    [C_AXI_ADDR_WIDTH-1:0]   w_addr;//  r_addr;
 
        wire    [7:0]                    w_len;//   r_len;
 
        wire    [2:0]                    w_size;//  r_size;
 
        wire    [1:0]                    w_burst;// r_burst;
 
        wire    [0:0]                     w_lock;//  r_lock;
 
        wire    [3:0]                    w_cache;// r_cache;
 
        wire    [2:0]                    w_prot;//  r_prot;
 
        wire    [3:0]                    w_qos;//   r_qos;
 
        wire    [LGFIFO:0]               fifo_fill;
 
        wire    [LGFIFO:0]               max_fifo_fill;
 
        wire                            accept_request;
 
 
        // We're going to need to keep track of transaction bursts in progress,
 
        // since the wishbone doesn't.  For this, we'll use a FIFO, but with
 
        // multiple pointers:
 
        //
 
        //      fifo_head       - pointer to where to write the next incoming
 
        //                              bus request .. adjusted when
 
        //                              (o_axi_arready)&&(i_axi_arvalid)
 
        //      fifo_neck       - pointer to where to read from the FIFO in
 
        //                              order to issue another request.  Used
 
        //                              when (o_wb_stb)&&(!i_wb_stall)
 
        //      fifo_torso      - pointer to where to write a wishbone
 
        //                              transaction upon return.
 
        //                              when (i_ack)
 
        //      fifo_tail       - pointer to where the last transaction is to
 
        //                              be retired when
 
        //                                      (i_axi_rvalid)&&(i_axi_rready)
 
        //
 
        // All of these are to be set to zero upon a reset signal.
 
        //
 
        reg     [LGFIFO-1:0]     fifo_head, fifo_neck, fifo_torso, fifo_tail;
 
 
 
        // Since we need to insure that these pointers wrap properly at
 
        // LGFIFO bits, and since it is confusing to do that within IF 
 
        // statements, 
 
        wire    [LGFIFO-1:0]     next_head, next_neck, next_torso, next_tail,
 
                                almost_head;
 
        wire            fifo_full;
 
        assign  next_head  = fifo_head  + 1;
 
        assign  next_neck  = fifo_neck  + 1;
 
        assign  next_torso = fifo_torso + 1;
 
        assign  next_tail  = fifo_tail  + 1;
 
        assign  almost_head = fifo_head  + 1;
 
 
 
        assign fifo_full = (almost_head == fifo_tail);
        assign  fifo_fill = (fifo_wptr - fifo_rptr);
 
        assign  max_fifo_fill = (1<<LGFIFO);
 
 
 
        assign  accept_request = (i_axi_reset_n)&&(!err_state)
 
                        &&((!o_wb_cyc)||(!i_wb_err))
 
                        &&((!o_wb_stb)||(last_stb && !i_wb_stall))
 
                        &&(r_valid ||((i_axi_arvalid)&&(o_axi_arready)))
 
                        // The request must fit into our FIFO before making
 
                        // it
 
                        &&(fifo_fill + {{(LGFIFO-8){1'b0}},w_len} +1
 
                                        < max_fifo_fill)
 
                        // One ID at a time, lest we return a bus error
 
                        // to the wrong AXI master
 
                        &&((fifo_fill == 0)||(w_id == axi_id));
 
 
 
 
 
        assign  i_rd_request = { i_axi_arid, i_axi_araddr, i_axi_arlen,
 
                                i_axi_arsize, i_axi_arburst, i_axi_arcache,
 
                                i_axi_arlock, i_axi_arprot, i_axi_arqos };
 
 
        reg     wr_last, filling_fifo, incr;
        initial r_rd_request = 0;
        reg     [7:0]                    len;
        initial r_valid      = 0;
        reg     [(AW-1):0]               wr_fifo_addr;
 
        reg     [(C_AXI_ID_WIDTH-1):0]   wr_fifo_id;
 
 
 
        //
 
        //
 
        //
 
        //
 
        // Here's our plan: Any time READY & VALID are both true, initiate a
 
        // transfer (unless one is ongoing).  Hold READY false while initiating
 
        // any burst transaction.  Keep the request RID and burst length stuffs
 
        // into a FIFO.
 
        // queue are both valid, issue the wishbone read request.  Once a read
 
        // request returns, retire the value in the FIFO queue.
 
        //
 
        // The FIFO queue *must* include:
 
        //
 
        //      RQ, ADDR, LAST
 
        //
 
        initial len          = 0;
 
        initial filling_fifo = 0;
 
        initial fifo_head    = 0;
 
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
 
        if (!i_axi_reset_n)
        begin
        begin
                wr_last <= 1'b0;
                r_rd_request <= 0;
 
                r_valid <= 1'b0;
                if (filling_fifo)
        end else if ((i_axi_arvalid)&&(o_axi_arready))
                begin
        begin
                        if (!fifo_full)
                r_rd_request <= i_rd_request;
                        begin
                if (!accept_request)
                                len <= len - 1;
                        r_valid <= 1'b1;
                                if (len == 1)
        end else if (accept_request)
                                        filling_fifo <= 1'b0;
                r_valid <= 1'b0;
                                fifo_head <= next_head;
 
                                wr_fifo_addr <= wr_fifo_addr
 
                                        + {{(AW-1){1'b0}}, incr};
 
                                wr_last <= (len == 1);
 
                        end
 
                end else begin
 
                        wr_fifo_addr <= i_axi_araddr[(C_AXI_ADDR_WIDTH-1):(C_AXI_ADDR_WIDTH-AW)];
 
                        wr_fifo_id <= i_axi_arid;
 
                        incr <= i_axi_arburst[0];
 
                        if ((o_axi_arready)&&(i_axi_arvalid))
 
                        begin
 
                                fifo_head <= next_head;
 
                                len <= i_axi_arlen;
 
                                filling_fifo <= (i_axi_arlen != 0);
 
                                wr_last <= 1'b1;
 
                        end
 
                end
 
 
 
                if (w_reset)
 
                begin
 
                        len <= 0;
 
                        filling_fifo <= 1'b0;
 
                        fifo_head <= 0;
 
                end
 
        end
 
 
 
        always @(posedge i_axi_clk)
        always @(*)
                afifo[fifo_head] <= { wr_fifo_id, wr_last, wr_fifo_addr };
                o_axi_arready = !r_valid;
 
 
        reg     err_state;
        /*
        initial o_wb_cyc   = 1'b0;
        assign  r_id    = r_rd_request[25 + C_AXI_ADDR_WIDTH +: C_AXI_ID_WIDTH];
        initial o_wb_stb   = 1'b0;
        assign  r_addr  = r_rd_request[25 +: C_AXI_ADDR_WIDTH];
        initial fifo_neck  = 0;
        assign  r_len   = r_rd_request[17 +: 8];
        initial fifo_torso = 0;
        assign  r_size  = r_rd_request[14 +: 3];
        initial err_state  = 0;
        assign  r_burst = r_rd_request[12 +: 2];
 
        assign  r_lock  = r_rd_request[11 +: 1];
 
        assign  r_cache = r_rd_request[ 7 +: 4];
 
        assign  r_prot  = r_rd_request[ 4 +: 3];
 
        assign  r_qos   = r_rd_request[ 0 +: 4];
 
        */
 
 
 
        assign  w_rd_request = (r_valid) ? (r_rd_request) : i_rd_request;
 
 
 
        assign  w_id    = w_rd_request[25 + C_AXI_ADDR_WIDTH +: C_AXI_ID_WIDTH];
 
        assign  w_addr  = w_rd_request[25 +: C_AXI_ADDR_WIDTH];
 
        assign  w_len   = w_rd_request[17 +: 8];
 
        assign  w_size  = w_rd_request[14 +: 3];
 
        assign  w_burst = w_rd_request[12 +: 2];
 
        assign  w_lock  = w_rd_request[11 +: 1];
 
        assign  w_cache = w_rd_request[ 7 +: 4];
 
        assign  w_prot  = w_rd_request[ 4 +: 3];
 
        assign  w_qos   = w_rd_request[ 0 +: 4];
 
 
 
        initial o_wb_cyc        = 0;
 
        initial o_wb_stb        = 0;
 
        initial stblen          = 0;
 
        initial incr            = 0;
 
        initial last_stb        = 0;
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
        begin
 
                if (w_reset)
                if (w_reset)
                begin
                begin
                        o_wb_cyc <= 1'b0;
 
                        o_wb_stb <= 1'b0;
                        o_wb_stb <= 1'b0;
 
                o_wb_cyc <= 1'b0;
 
                incr     <= 1'b0;
 
                stblen   <= 0;
 
                last_stb <= 0;
 
        end else if ((!o_wb_stb)||(!i_wb_stall))
 
        begin
 
                if (accept_request)
 
                begin
 
                        // Process the new request
 
                        o_wb_cyc <= 1'b1;
 
                        o_wb_stb <= 1'b1;
 
                        last_stb <= (w_len == 0);
 
 
                        fifo_neck  <= 0;
                        o_wb_addr <= w_addr[(C_AXI_ADDR_WIDTH-1):(C_AXI_ADDR_WIDTH-AW)];
                        fifo_torso <= 0;
                        incr <= w_burst[0];
 
                        stblen <= w_len;
                        err_state <= 0;
                        axi_id <= w_id;
                end else if (o_wb_stb)
                // end else if ((o_wb_cyc)&&(i_wb_err)||(err_state))
 
                end else if (o_wb_stb && !last_stb)
                begin
                begin
 
                        // Step forward on the burst request
 
                        last_stb <= (stblen == 1);
 
 
 
                        o_wb_addr <= o_wb_addr + ((incr)? 1'b1:1'b0);
 
                        stblen <= stblen - 1'b1;
 
 
                        if (i_wb_err)
                        if (i_wb_err)
                        begin
                        begin
 
                                stblen <= 0;
                                o_wb_stb <= 1'b0;
                                o_wb_stb <= 1'b0;
                                err_state <= 1'b1;
                                o_wb_cyc <= 1'b0;
                        end else if (!i_wb_stall)
 
                        begin
 
                                o_wb_stb <= (fifo_head != next_neck);
 
                                                // && (WBMODE != "B3SINGLE");
 
                                // o_wb_cyc <= (WBMODE != "B3SINGLE");
 
                        end
                        end
 
                end else if (!o_wb_stb || last_stb)
                        if (!i_wb_stall)
 
                                fifo_neck <= next_neck;
 
                        if (i_wb_ack)
 
                                fifo_torso <= next_torso;
 
                end else if (err_state)
 
                begin
                begin
                        fifo_torso <= next_torso;
                        // End the request
                        if (fifo_neck == next_torso)
                        o_wb_stb <= 1'b0;
                                err_state <= 1'b0;
                        last_stb <= 1'b0;
 
                        stblen <= 0;
 
 
 
                        // Check for the last acknowledgment
 
                        if ((i_wb_ack)&&(last_ack))
                        o_wb_cyc <= 1'b0;
                        o_wb_cyc <= 1'b0;
                end else if (o_wb_cyc)
                        if (i_wb_err)
                begin
 
                        if (i_wb_ack)
 
                                fifo_torso <= next_torso;
 
                        if (fifo_neck == next_torso)
 
                                o_wb_cyc <= 1'b0;
                                o_wb_cyc <= 1'b0;
                end else if (fifo_neck != fifo_head)
                end
 
        end else if ((o_wb_cyc)&&(i_wb_err))
                begin
                begin
                        o_wb_cyc <= 1'b1;
                stblen <= 0;
                        o_wb_stb <= 1'b1;
                o_wb_stb <= 1'b0;
 
                o_wb_cyc <= 1'b0;
 
                last_stb <= 1'b0;
                end
                end
 
 
 
        always @(*)
 
                next_ackptr = fifo_ackptr + 1'b1;
 
 
 
        always @(*)
 
        begin
 
                last_ack = 1'b0;
 
                if (err_state)
 
                        last_ack = 1'b1;
 
                else if ((o_wb_stb)&&(stblen == 0)&&(fifo_wptr == fifo_ackptr))
 
                        last_ack = 1'b1;
 
                else if ((fifo_wptr == next_ackptr)&&(!o_wb_stb))
 
                        last_ack = 1'b1;
        end
        end
 
 
 
        initial fifo_wptr = 0;
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
                fifo_at_neck <= afifo[fifo_neck];
        if (w_reset)
        assign  o_wb_addr = fifo_at_neck[(AW-1):0];
                fifo_wptr <= 0;
 
        else if (o_wb_cyc && i_wb_err)
 
                fifo_wptr <= fifo_wptr + {{(LGFIFO-8){1'b0}},stblen}
 
                                + ((o_wb_stb)? 1:0);
 
        else if ((o_wb_stb)&&(!i_wb_stall))
 
                fifo_wptr <= fifo_wptr + 1'b1;
 
 
 
        initial fifo_ackptr = 0;
 
        always @(posedge i_axi_clk)
 
        if (w_reset)
 
                fifo_ackptr <= 0;
 
        else if ((o_wb_cyc)&&((i_wb_ack)||(i_wb_err)))
 
                fifo_ackptr <= fifo_ackptr + 1'b1;
 
        else if (err_state && (fifo_ackptr != fifo_wptr))
 
                fifo_ackptr <= fifo_ackptr + 1'b1;
 
 
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
                dfifo[fifo_torso] <= { (err_state)||(i_wb_err), i_wb_data };
        if ((o_wb_stb)&&(!i_wb_stall))
 
                request_fifo[fifo_wptr[LGFIFO-1:0]] <= { last_stb, axi_id };
 
 
 
        always @(posedge i_axi_clk)
 
        if ((o_wb_cyc && ((i_wb_ack)||(i_wb_err)))
 
                ||(err_state && (fifo_ackptr != fifo_wptr)))
 
                response_fifo[fifo_ackptr[LGFIFO-1:0]]
 
                        <= { (err_state||i_wb_err), i_wb_data };
 
 
 
        initial fifo_rptr = 0;
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
                if (w_reset)
                if (w_reset)
                        fifo_tail <= 0;
                fifo_rptr <= 0;
                else if ((o_axi_rvalid)&&(i_axi_rready))
                else if ((o_axi_rvalid)&&(i_axi_rready))
                        fifo_tail <= next_tail;
                fifo_rptr <= fifo_rptr + 1'b1;
 
 
 
        always @(*)
 
                next_rptr = fifo_rptr + 1'b1;
 
 
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
        begin
        if (advance_ack)
                afifo_at_tail <= afifo[fifo_tail];
                ack_data <= response_fifo[fifo_rptr[LGFIFO-1:0]];
                dfifo_at_tail <= dfifo[fifo_tail];
 
                // o_axi_rdata <= dfifo[fifo_tail];
        always @(posedge i_axi_clk)
                // o_axi_rlast <= afifo[fifo_tail];
        if (advance_ack)
                // o_axi_rid   <= afifo[fifo_tail];
                rsp_data <= request_fifo[fifo_rptr[LGFIFO-1:0]];
        end
 
        assign  o_axi_rlast = afifo_at_tail[AW];
        always @(*)
        assign  o_axi_rid   = afifo_at_tail[(C_AXI_ID_WIDTH+AW):(AW+1)];
        if ((o_axi_rvalid)&&(i_axi_rready))
        assign  o_axi_rresp = { (2){dfifo_at_tail[DW]} };
                advance_ack = (fifo_ackptr != next_rptr);
        assign  o_axi_rdata = dfifo_at_tail[(DW-1):0];
        else if ((!o_axi_rvalid)&&(fifo_ackptr != fifo_rptr))
 
                advance_ack = 1'b1;
 
        else
 
                advance_ack = 1'b0;
 
 
 
        initial o_axi_rvalid = 0;
 
        always @(posedge i_axi_clk)
 
        if (w_reset)
 
                o_axi_rvalid <= 1'b0;
 
        else if (advance_ack)
 
                o_axi_rvalid <= 1'b1;
 
        else if (i_axi_rready)
 
                o_axi_rvalid <= 1'b0;
 
 
        initial o_axi_rvalid = 1'b0;
        initial err_state = 0;
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
                if (w_reset)
                if (w_reset)
                        o_axi_rvalid <= 0;
                err_state <= 1'b0;
                else if (fifo_tail != fifo_neck)
        else if ((o_wb_cyc)&&(i_wb_err))
                        o_axi_rvalid <= (fifo_tail != fifo_neck + 1);
                err_state <= 1'b1;
 
        else if ((!o_wb_stb)&&(fifo_wptr == fifo_rptr))
 
                err_state <= 1'b0;
 
 
        assign o_axi_arready = (!fifo_full)&&(!filling_fifo);
        assign  o_axi_rlast = rsp_data[C_AXI_ID_WIDTH];
 
        assign  o_axi_rid   = rsp_data[0 +: C_AXI_ID_WIDTH];
 
        assign  o_axi_rresp = {(2){ack_data[C_AXI_DATA_WIDTH]}};
 
        assign  o_axi_rdata = ack_data[0 +: C_AXI_DATA_WIDTH];
 
 
        // Make Verilator happy
        // Make Verilator happy
        // verilator lint_off UNUSED
        // verilator lint_off UNUSED
        wire    [(C_AXI_ID_WIDTH+1)+(C_AXI_ADDR_WIDTH-AW)
        wire    [(C_AXI_ID_WIDTH+1)+(C_AXI_ADDR_WIDTH-AW)
                +3+1+1+4+3+4-1:0]        unused;
                +27-1:0] unused;
        assign  unused = { i_axi_arsize, i_axi_arburst[1],
        assign  unused = { i_axi_arsize, i_axi_arburst[1],
                        i_axi_arlock, i_axi_arcache, i_axi_arprot,
                i_axi_arlock, i_axi_arcache, i_axi_arprot, i_axi_arqos,
                        i_axi_arqos,
                w_burst[1], w_size, w_lock, w_cache, w_prot, w_qos, w_addr[1:0],
                        fifo_at_neck[(C_AXI_ID_WIDTH+AW+1)-1:AW],
 
                        i_axi_araddr[(C_AXI_ADDR_WIDTH-AW-1):0] };
                        i_axi_araddr[(C_AXI_ADDR_WIDTH-AW-1):0] };
        // verilator lint_on  UNUSED
        // verilator lint_on  UNUSED
 
 
`ifdef  FORMAL
`ifdef  FORMAL
        reg     f_past_valid;
        reg     f_past_valid;
        initial f_past_valid = 1'b0;
        initial f_past_valid = 1'b0;
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
                f_past_valid <= 1'b1;
                f_past_valid <= 1'b1;
 
 
        wire    [LGFIFO-1:0]     f_fifo_used, f_fifo_neck_used,
        ////////////////////////////////////////////////////////////////////////
                                f_fifo_torso_used;
        //
        assign  f_fifo_used       = fifo_head - fifo_tail;
        // Assumptions
        assign  f_fifo_neck_used  = fifo_head - fifo_neck;
        //
        assign  f_fifo_torso_used = fifo_head - fifo_torso;
        //
 
        always @(*)
 
        if (!f_past_valid)
 
                assume(w_reset);
 
 
 
 
 
        ////////////////////////////////////////////////////////////////////////
 
        //
 
        // Ad-hoc assertions
 
        //
 
        //
        always @(*)
        always @(*)
                assert((f_fifo_used < {(LGFIFO){1'b1}})||(!o_axi_arready));
        if (o_wb_stb)
 
                assert(last_stb == (stblen == 0));
 
        else
 
                assert((!last_stb)&&(stblen == 0));
 
 
 
        ////////////////////////////////////////////////////////////////////////
 
        //
 
        // Error state
 
        //
 
        //
 
        /*
 
        always @(*)
 
                assume(!i_wb_err);
 
        always @(*)
 
                assert(!err_state);
 
        */
        always @(*)
        always @(*)
                assert(f_fifo_neck_used  <= f_fifo_used);
        if ((!err_state)&&(o_axi_rvalid))
 
                assert(o_axi_rresp == 2'b00);
 
 
 
        ////////////////////////////////////////////////////////////////////////
 
        //
 
        // FIFO pointers
 
        //
 
        //
 
        wire    [LGFIFO:0]       f_fifo_wb_used, f_fifo_ackremain, f_fifo_used;
 
        assign  f_fifo_used       = fifo_wptr   - fifo_rptr;
 
        assign  f_fifo_wb_used    = fifo_wptr   - fifo_ackptr;
 
        assign  f_fifo_ackremain  = fifo_ackptr - fifo_rptr;
 
 
 
        always @(*)
 
        if (o_wb_stb)
 
                assert(f_fifo_used + stblen + 1 < {(LGFIFO){1'b1}});
 
        else
 
                assert(f_fifo_used < {(LGFIFO){1'b1}});
        always @(*)
        always @(*)
                assert(f_fifo_torso_used <= f_fifo_used);
                assert(f_fifo_wb_used   <= f_fifo_used);
 
        always @(*)
 
                assert(f_fifo_ackremain <= f_fifo_used);
 
 
 
        // Reset properties
        always @(posedge i_axi_clk)
        always @(posedge i_axi_clk)
        if ((f_past_valid)&&(!$past(i_axi_reset_n)))
        if ((!f_past_valid)||($past(w_reset)))
                assert(f_fifo_used == 0);
        begin
 
                assert(fifo_wptr   == 0);
 
                assert(fifo_ackptr == 0);
 
                assert(fifo_rptr   == 0);
 
        end
 
 
 
        localparam      F_LGDEPTH = LGFIFO+1, F_LGRDFIFO = 72; // 9*F_LGFIFO;
 
        wire    [(9-1):0]                f_axi_rd_count;
 
        wire    [(F_LGRDFIFO-1):0]       f_axi_rdfifo;
 
        wire    [(F_LGDEPTH-1):0]        f_axi_rd_nbursts, f_axi_rd_outstanding,
 
                                        f_axi_awr_outstanding,
 
                        f_wb_nreqs, f_wb_nacks, f_wb_outstanding;
 
 
 
        fwb_master #(.AW(AW), .DW(C_AXI_DATA_WIDTH), .F_MAX_STALL(2),
 
                .F_MAX_ACK_DELAY(3), .F_LGDEPTH(F_LGDEPTH),
 
                .F_OPT_DISCONTINUOUS(1))
 
                fwb(i_axi_clk, w_reset,
 
                        o_wb_cyc, o_wb_stb, 1'b0, o_wb_addr, {(DW){1'b0}}, 4'hf,
 
                        i_wb_ack, i_wb_stall, i_wb_data, i_wb_err,
 
                        f_wb_nreqs, f_wb_nacks, f_wb_outstanding);
 
 
 
        always @(*)
 
        if (err_state)
 
                assert(f_wb_outstanding == 0);
 
        else
 
                assert(f_wb_outstanding == f_fifo_wb_used);
 
 
 
 
 
        faxi_slave      #(.C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH),
 
                        .C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH),
 
                        .F_OPT_BURSTS(1'b0),
 
                        .F_LGDEPTH(F_LGDEPTH),
 
                        .F_AXI_MAXSTALL(0),
 
                        .F_AXI_MAXDELAY(0))
 
                faxi(.i_clk(i_axi_clk), .i_axi_reset_n(!w_reset),
 
                        .i_axi_awready(1'b0),
 
                        .i_axi_awaddr(0),
 
                        .i_axi_awlen(0),
 
                        .i_axi_awsize(0),
 
                        .i_axi_awburst(0),
 
                        .i_axi_awlock(0),
 
                        .i_axi_awcache(0),
 
                        .i_axi_awprot(0),
 
                        .i_axi_awqos(0),
 
                        .i_axi_awvalid(1'b0),
 
                        //
 
                        .i_axi_wready(1'b0),
 
                        .i_axi_wdata(0),
 
                        .i_axi_wstrb(0),
 
                        .i_axi_wlast(0),
 
                        .i_axi_wvalid(1'b0),
 
                        //
 
                        .i_axi_bresp(0),
 
                        .i_axi_bvalid(1'b0),
 
                        .i_axi_bready(1'b0),
 
                        //
 
                        .i_axi_arready(o_axi_arready),
 
                        .i_axi_araddr(i_axi_araddr),
 
                        .i_axi_arlen(i_axi_arlen),
 
                        .i_axi_arsize(i_axi_arsize),
 
                        .i_axi_arburst(i_axi_arburst),
 
                        .i_axi_arlock(i_axi_arlock),
 
                        .i_axi_arcache(i_axi_arcache),
 
                        .i_axi_arprot(i_axi_arprot),
 
                        .i_axi_arqos(i_axi_arqos),
 
                        .i_axi_arvalid(i_axi_arvalid),
 
                        //
 
                        .i_axi_rresp(o_axi_rresp),
 
                        .i_axi_rvalid(o_axi_rvalid),
 
                        .i_axi_rdata(o_axi_rdata),
 
                        .i_axi_rlast(o_axi_rlast),
 
                        .i_axi_rready(i_axi_rready),
 
                        //
 
                        .f_axi_rd_nbursts(f_axi_rd_nbursts),
 
                        .f_axi_rd_outstanding(f_axi_rd_outstanding),
 
                        .f_axi_wr_nbursts(),
 
                        .f_axi_awr_outstanding(f_axi_awr_outstanding),
 
                        .f_axi_awr_nbursts(),
 
                        //
 
                        .f_axi_rd_count(f_axi_rd_count),
 
                        .f_axi_rdfifo(f_axi_rdfifo));
 
 
 
        always @(*)
 
                assert(f_axi_awr_outstanding == 0);
 
 
`endif
`endif
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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