// ---------------------------------------------------------------------- // 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: tx_engine_selector.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Searches for read and write requests. // PCIe Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: //----------------------------------------------------------------------------- `timescale 1ns/1ns module tx_engine_selector #( parameter C_NUM_CHNL = 4'd12 ) ( input CLK, input RST, input [C_NUM_CHNL-1:0] REQ_ALL, // Write requests output REQ, // Write request output [3:0] CHNL// Write channel ); reg [3:0] rReqChnl=0, _rReqChnl=0; reg [3:0] rReqChnlNext=0, _rReqChnlNext=0; reg rReqChnlsSame=0, _rReqChnlsSame=0; reg [3:0] rChnlNext=0, _rChnlNext=0; reg [3:0] rChnlNextNext=0, _rChnlNextNext=0; reg rChnlNextDfrnt=0, _rChnlNextDfrnt=0; reg rChnlNextNextOn=0, _rChnlNextNextOn=0; wire wChnlNextNextOn; reg rReq=0, _rReq=0; wire wReq;// = (REQ_ALL>>(rReqChnl)); reg rReqChnlNextUpdated=0, _rReqChnlNextUpdated=0; assign wReq = REQ_ALL[rReqChnl]; assign wChnlNextNextOn = REQ_ALL[rChnlNextNext]; assign REQ = rReq; assign CHNL = rReqChnl; // Search for the next request so that we can move onto it immediately after // the current channel has released its request. always @ (posedge CLK) begin rReq <= #1 (RST ? 1'd0 : _rReq); rReqChnl <= #1 (RST ? 4'd0 : _rReqChnl); rReqChnlNext <= #1 (RST ? 4'd0 : _rReqChnlNext); rChnlNext <= #1 (RST ? 4'd0 : _rChnlNext); rChnlNextNext <= #1 (RST ? 4'd0 : _rChnlNextNext); rChnlNextDfrnt <= #1 (RST ? 1'd0 : _rChnlNextDfrnt); rChnlNextNextOn <= #1 (RST ? 1'd0 : _rChnlNextNextOn); rReqChnlsSame <= #1 (RST ? 1'd0 : _rReqChnlsSame); rReqChnlNextUpdated <= #1 (RST ? 1'd1 : _rReqChnlNextUpdated); end always @ (*) begin // Go through each channel (RR), looking for requests _rChnlNextNextOn = wChnlNextNextOn; _rChnlNext = rChnlNextNext; _rChnlNextNext = (rChnlNextNext == C_NUM_CHNL - 1 ? 4'd0 : rChnlNextNext + 1'd1); _rChnlNextDfrnt = (rChnlNextNext != rReqChnl); _rReqChnlsSame = (rReqChnlNext == rReqChnl); // Save ready channel if it is not the same channel we're currently on if (rChnlNextNextOn & rChnlNextDfrnt & rReqChnlsSame & !rReqChnlNextUpdated) begin _rReqChnlNextUpdated = 1; _rReqChnlNext = rChnlNext; end else begin _rReqChnlNextUpdated = 0; _rReqChnlNext = rReqChnlNext; end // Assign the new channel _rReq = wReq; _rReqChnl = (!rReq ? rReqChnlNext : rReqChnl); end endmodule