// ---------------------------------------------------------------------- // Copyright (c) 2015, The Regents of the University of California All // rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // * Neither the name of The Regents of the University of California // nor the names of its contributors may be used to endorse or // promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE // UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // Filename: Filename: tx_multiplexer.v // Version: Version: 1.0 // Verilog Standard: Verilog-2005 // Description: the TX Multiplexer services read and write requests from // RIFFA channels in round robin order. // Author: Dustin Richmond (@darichmond) // ---------------------------------------------------------------------- `include "trellis.vh" module tx_multiplexer #( parameter C_PCI_DATA_WIDTH = 128, parameter C_NUM_CHNL = 12, parameter C_TAG_WIDTH = 5, parameter C_VENDOR = "ALTERA", parameter C_DEPTH_PACKETS = 10 ) ( input CLK, input RST_IN, input [C_NUM_CHNL-1:0] WR_REQ, // Write request input [(C_NUM_CHNL*`SIG_ADDR_W)-1:0] WR_ADDR, // Write address input [(C_NUM_CHNL*`SIG_LEN_W)-1:0] WR_LEN, // Write data length input [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0] WR_DATA, // Write data output [C_NUM_CHNL-1:0] WR_DATA_REN, // Write data read enable output [C_NUM_CHNL-1:0] WR_ACK, // Write request has been accepted output [C_NUM_CHNL-1:0] WR_SENT, // Write Reuqest has been sent to the core input [C_NUM_CHNL-1:0] RD_REQ, // Read request input [(C_NUM_CHNL*2)-1:0] RD_SG_CHNL, // Read request channel for scatter gather lists input [(C_NUM_CHNL*`SIG_ADDR_W)-1:0] RD_ADDR, // Read request address input [(C_NUM_CHNL*`SIG_LEN_W)-1:0] RD_LEN, // Read request length output [C_NUM_CHNL-1:0] RD_ACK, // Read request has been accepted output [5:0] INT_TAG, // Internal tag to exchange with external output INT_TAG_VALID, // High to signal tag exchange input [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag input EXT_TAG_VALID, // High to signal external tag is valid output TX_ENG_RD_REQ_SENT, // Read completion request issued input RXBUF_SPACE_AVAIL, // Interface: TXR Engine output TXR_DATA_VALID, output [C_PCI_DATA_WIDTH-1:0] TXR_DATA, output TXR_DATA_START_FLAG, output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_DATA_START_OFFSET, output TXR_DATA_END_FLAG, output [clog2s(C_PCI_DATA_WIDTH/32)-1:0] TXR_DATA_END_OFFSET, input TXR_DATA_READY, output TXR_META_VALID, output [`SIG_FBE_W-1:0] TXR_META_FDWBE, output [`SIG_LBE_W-1:0] TXR_META_LDWBE, output [`SIG_ADDR_W-1:0] TXR_META_ADDR, output [`SIG_LEN_W-1:0] TXR_META_LENGTH, output [`SIG_TAG_W-1:0] TXR_META_TAG, output [`SIG_TC_W-1:0] TXR_META_TC, output [`SIG_ATTR_W-1:0] TXR_META_ATTR, output [`SIG_TYPE_W-1:0] TXR_META_TYPE, output TXR_META_EP, input TXR_META_READY, input TXR_SENT); wire [C_NUM_CHNL-1:0] wAckRdData; reg [C_NUM_CHNL-1:0] rAckWrData; // Registered fifo input (only write acks) reg [C_NUM_CHNL-1:0] rAckRdData; // Registered fifo output (only write acks) reg rAckWrEn,_rAckWrEn; // Fifo write enable (RD or WR_ACK) reg rAckRdEn; // Fifo read enable (TXR_SENT) always @(*) begin _rAckWrEn = (WR_ACK != 0) | (RD_ACK != 0); end always @(posedge CLK) begin rAckWrData <= WR_ACK; rAckWrEn <= _rAckWrEn; end always @(posedge CLK) begin rAckRdEn <= TXR_SENT; if(rAckRdEn) begin rAckRdData <= wAckRdData; end else begin rAckRdData <= 0; end end assign WR_SENT = rAckRdData; fifo #(// Parameters .C_WIDTH (C_NUM_CHNL), .C_DEPTH (C_DEPTH_PACKETS*3), // This is an extremely conservative estimate... .C_DELAY (0) /*AUTOINSTPARAM*/) req_ack_fifo (// Outputs .WR_READY (), .RD_DATA (wAckRdData), .RD_VALID (), // Inputs .WR_DATA (rAckWrData), .WR_VALID (rAckWrEn), .RD_READY (rAckRdEn), .RST (RST_IN), /*AUTOINST*/ // Inputs .CLK (CLK)); generate if(C_PCI_DATA_WIDTH == 32) begin tx_multiplexer_32 #(/*AUTOINSTPARAM*/ // Parameters .C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH), .C_NUM_CHNL (C_NUM_CHNL), .C_TAG_WIDTH (C_TAG_WIDTH), .C_VENDOR (C_VENDOR)) tx_mux (/*AUTOINST*/ // Outputs .WR_DATA_REN (WR_DATA_REN[C_NUM_CHNL-1:0]), .WR_ACK (WR_ACK[C_NUM_CHNL-1:0]), .RD_ACK (RD_ACK[C_NUM_CHNL-1:0]), .INT_TAG (INT_TAG[5:0]), .INT_TAG_VALID (INT_TAG_VALID), .TX_ENG_RD_REQ_SENT (TX_ENG_RD_REQ_SENT), .TXR_DATA_VALID (TXR_DATA_VALID), .TXR_DATA (TXR_DATA[C_PCI_DATA_WIDTH-1:0]), .TXR_DATA_START_FLAG (TXR_DATA_START_FLAG), .TXR_DATA_START_OFFSET (TXR_DATA_START_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]), .TXR_DATA_END_FLAG (TXR_DATA_END_FLAG), .TXR_DATA_END_OFFSET (TXR_DATA_END_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]), .TXR_META_VALID (TXR_META_VALID), .TXR_META_FDWBE (TXR_META_FDWBE[`SIG_FBE_W-1:0]), .TXR_META_LDWBE (TXR_META_LDWBE[`SIG_LBE_W-1:0]), .TXR_META_ADDR (TXR_META_ADDR[`SIG_ADDR_W-1:0]), .TXR_META_LENGTH (TXR_META_LENGTH[`SIG_LEN_W-1:0]), .TXR_META_TAG (TXR_META_TAG[`SIG_TAG_W-1:0]), .TXR_META_TC (TXR_META_TC[`SIG_TC_W-1:0]), .TXR_META_ATTR (TXR_META_ATTR[`SIG_ATTR_W-1:0]), .TXR_META_TYPE (TXR_META_TYPE[`SIG_TYPE_W-1:0]), .TXR_META_EP (TXR_META_EP), // Inputs .CLK (CLK), .RST_IN (RST_IN), .WR_REQ (WR_REQ[C_NUM_CHNL-1:0]), .WR_ADDR (WR_ADDR[(C_NUM_CHNL*`SIG_ADDR_W)-1:0]), .WR_LEN (WR_LEN[(C_NUM_CHNL*`SIG_LEN_W)-1:0]), .WR_DATA (WR_DATA[(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0]), .RD_REQ (RD_REQ[C_NUM_CHNL-1:0]), .RD_SG_CHNL (RD_SG_CHNL[(C_NUM_CHNL*2)-1:0]), .RD_ADDR (RD_ADDR[(C_NUM_CHNL*`SIG_ADDR_W)-1:0]), .RD_LEN (RD_LEN[(C_NUM_CHNL*`SIG_LEN_W)-1:0]), .EXT_TAG (EXT_TAG[C_TAG_WIDTH-1:0]), .EXT_TAG_VALID (EXT_TAG_VALID), .RXBUF_SPACE_AVAIL (RXBUF_SPACE_AVAIL), .TXR_DATA_READY (TXR_DATA_READY), .TXR_META_READY (TXR_META_READY)); end else if(C_PCI_DATA_WIDTH == 64) begin tx_multiplexer_64 #(/*AUTOINSTPARAM*/ // Parameters .C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH), .C_NUM_CHNL (C_NUM_CHNL), .C_TAG_WIDTH (C_TAG_WIDTH), .C_VENDOR (C_VENDOR)) tx_mux (/*AUTOINST*/ // Outputs .WR_DATA_REN (WR_DATA_REN[C_NUM_CHNL-1:0]), .WR_ACK (WR_ACK[C_NUM_CHNL-1:0]), .RD_ACK (RD_ACK[C_NUM_CHNL-1:0]), .INT_TAG (INT_TAG[5:0]), .INT_TAG_VALID (INT_TAG_VALID), .TX_ENG_RD_REQ_SENT (TX_ENG_RD_REQ_SENT), .TXR_DATA_VALID (TXR_DATA_VALID), .TXR_DATA (TXR_DATA[C_PCI_DATA_WIDTH-1:0]), .TXR_DATA_START_FLAG (TXR_DATA_START_FLAG), .TXR_DATA_START_OFFSET (TXR_DATA_START_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]), .TXR_DATA_END_FLAG (TXR_DATA_END_FLAG), .TXR_DATA_END_OFFSET (TXR_DATA_END_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]), .TXR_META_VALID (TXR_META_VALID), .TXR_META_FDWBE (TXR_META_FDWBE[`SIG_FBE_W-1:0]), .TXR_META_LDWBE (TXR_META_LDWBE[`SIG_LBE_W-1:0]), .TXR_META_ADDR (TXR_META_ADDR[`SIG_ADDR_W-1:0]), .TXR_META_LENGTH (TXR_META_LENGTH[`SIG_LEN_W-1:0]), .TXR_META_TAG (TXR_META_TAG[`SIG_TAG_W-1:0]), .TXR_META_TC (TXR_META_TC[`SIG_TC_W-1:0]), .TXR_META_ATTR (TXR_META_ATTR[`SIG_ATTR_W-1:0]), .TXR_META_TYPE (TXR_META_TYPE[`SIG_TYPE_W-1:0]), .TXR_META_EP (TXR_META_EP), // Inputs .CLK (CLK), .RST_IN (RST_IN), .WR_REQ (WR_REQ[C_NUM_CHNL-1:0]), .WR_ADDR (WR_ADDR[(C_NUM_CHNL*`SIG_ADDR_W)-1:0]), .WR_LEN (WR_LEN[(C_NUM_CHNL*`SIG_LEN_W)-1:0]), .WR_DATA (WR_DATA[(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0]), .RD_REQ (RD_REQ[C_NUM_CHNL-1:0]), .RD_SG_CHNL (RD_SG_CHNL[(C_NUM_CHNL*2)-1:0]), .RD_ADDR (RD_ADDR[(C_NUM_CHNL*`SIG_ADDR_W)-1:0]), .RD_LEN (RD_LEN[(C_NUM_CHNL*`SIG_LEN_W)-1:0]), .EXT_TAG (EXT_TAG[C_TAG_WIDTH-1:0]), .EXT_TAG_VALID (EXT_TAG_VALID), .RXBUF_SPACE_AVAIL (RXBUF_SPACE_AVAIL), .TXR_DATA_READY (TXR_DATA_READY), .TXR_META_READY (TXR_META_READY)); end else if(C_PCI_DATA_WIDTH == 128) begin tx_multiplexer_128 #(/*AUTOINSTPARAM*/ // Parameters .C_PCI_DATA_WIDTH (C_PCI_DATA_WIDTH), .C_NUM_CHNL (C_NUM_CHNL), .C_TAG_WIDTH (C_TAG_WIDTH), .C_VENDOR (C_VENDOR)) tx_mux_128_inst (/*AUTOINST*/ // Outputs .WR_DATA_REN (WR_DATA_REN[C_NUM_CHNL-1:0]), .WR_ACK (WR_ACK[C_NUM_CHNL-1:0]), .RD_ACK (RD_ACK[C_NUM_CHNL-1:0]), .INT_TAG (INT_TAG[5:0]), .INT_TAG_VALID (INT_TAG_VALID), .TX_ENG_RD_REQ_SENT (TX_ENG_RD_REQ_SENT), .TXR_DATA_VALID (TXR_DATA_VALID), .TXR_DATA (TXR_DATA[C_PCI_DATA_WIDTH-1:0]), .TXR_DATA_START_FLAG (TXR_DATA_START_FLAG), .TXR_DATA_START_OFFSET (TXR_DATA_START_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]), .TXR_DATA_END_FLAG (TXR_DATA_END_FLAG), .TXR_DATA_END_OFFSET (TXR_DATA_END_OFFSET[clog2s(C_PCI_DATA_WIDTH/32)-1:0]), .TXR_META_VALID (TXR_META_VALID), .TXR_META_FDWBE (TXR_META_FDWBE[`SIG_FBE_W-1:0]), .TXR_META_LDWBE (TXR_META_LDWBE[`SIG_LBE_W-1:0]), .TXR_META_ADDR (TXR_META_ADDR[`SIG_ADDR_W-1:0]), .TXR_META_LENGTH (TXR_META_LENGTH[`SIG_LEN_W-1:0]), .TXR_META_TAG (TXR_META_TAG[`SIG_TAG_W-1:0]), .TXR_META_TC (TXR_META_TC[`SIG_TC_W-1:0]), .TXR_META_ATTR (TXR_META_ATTR[`SIG_ATTR_W-1:0]), .TXR_META_TYPE (TXR_META_TYPE[`SIG_TYPE_W-1:0]), .TXR_META_EP (TXR_META_EP), // Inputs .CLK (CLK), .RST_IN (RST_IN), .WR_REQ (WR_REQ[C_NUM_CHNL-1:0]), .WR_ADDR (WR_ADDR[(C_NUM_CHNL*`SIG_ADDR_W)-1:0]), .WR_LEN (WR_LEN[(C_NUM_CHNL*`SIG_LEN_W)-1:0]), .WR_DATA (WR_DATA[(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0]), .RD_REQ (RD_REQ[C_NUM_CHNL-1:0]), .RD_SG_CHNL (RD_SG_CHNL[(C_NUM_CHNL*2)-1:0]), .RD_ADDR (RD_ADDR[(C_NUM_CHNL*`SIG_ADDR_W)-1:0]), .RD_LEN (RD_LEN[(C_NUM_CHNL*`SIG_LEN_W)-1:0]), .EXT_TAG (EXT_TAG[C_TAG_WIDTH-1:0]), .EXT_TAG_VALID (EXT_TAG_VALID), .RXBUF_SPACE_AVAIL (RXBUF_SPACE_AVAIL), .TXR_DATA_READY (TXR_DATA_READY), .TXR_META_READY (TXR_META_READY)); end endgenerate endmodule // Local Variables: // verilog-library-directories:("." "registers/" "../common/") // End: