1
0
mirror of https://github.com/KastnerRG/riffa.git synced 2025-01-30 23:02:54 +08:00
riffa/fpga/riffa_hdl/reorder_queue_output.v

292 lines
10 KiB
Coq
Raw Normal View History

// ----------------------------------------------------------------------
// 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.
// ----------------------------------------------------------------------
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 19:27:32 06/14/2012
// Design Name:
// Module Name: reorder_queue_output
// Project Name:
// Target Devices:
// Tool versions:
// Description:
// Outputs stored TLPs in increasing tag order.
//
// Dependencies:
// reorder_queue.v
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`include "trellis.vh"
module reorder_queue_output #(
parameter C_PCI_DATA_WIDTH = 9'd128,
parameter C_NUM_CHNL = 4'd12,
parameter C_TAG_WIDTH = 5, // Number of outstanding requests
parameter C_TAG_DW_COUNT_WIDTH = 8, // Width of max count DWs per packet
parameter C_DATA_ADDR_STRIDE_WIDTH = 5, // Width of max num stored data addr positions per tag
parameter C_DATA_ADDR_WIDTH = 10, // Width of stored data address
// Local parameters
parameter C_PCI_DATA_WORD = C_PCI_DATA_WIDTH/32,
parameter C_PCI_DATA_WORD_WIDTH = clog2s(C_PCI_DATA_WORD),
parameter C_PCI_DATA_COUNT_WIDTH = clog2s(C_PCI_DATA_WORD+1),
parameter C_NUM_TAGS = 2**C_TAG_WIDTH
)
(
input CLK, // Clock
input RST, // Synchronous reset
output [C_DATA_ADDR_WIDTH-1:0] DATA_ADDR, // Address of stored packet data
input [C_PCI_DATA_WIDTH-1:0] DATA, // Stored packet data
input [C_NUM_TAGS-1:0] TAG_FINISHED, // Bitmap of finished tags
output [C_NUM_TAGS-1:0] TAG_CLEAR, // Bitmap of tags to clear
output [C_TAG_WIDTH-1:0] TAG, // Tag for which to retrieve packet data
input [5:0] TAG_MAPPED, // Mapped tag (i.e. internal tag)
input [C_TAG_DW_COUNT_WIDTH-1:0] PKT_WORDS, // Total count of packet payload in DWs
input PKT_WORDS_LTE1, // True if total count of packet payload is <= 4 DWs
input PKT_WORDS_LTE2, // True if total count of packet payload is <= 8 DWs
input PKT_DONE, // Packet done flag
input PKT_ERR, // Packet error flag
output [C_PCI_DATA_WIDTH-1:0] ENG_DATA, // Engine data
output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] MAIN_DATA_EN, // Main data enable
output [C_NUM_CHNL-1:0] MAIN_DONE, // Main data complete
output [C_NUM_CHNL-1:0] MAIN_ERR, // Main data completed with error
output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_RX_DATA_EN, // Scatter gather for RX data enable
output [C_NUM_CHNL-1:0] SG_RX_DONE, // Scatter gather for RX data complete
output [C_NUM_CHNL-1:0] SG_RX_ERR, // Scatter gather for RX data completed with error
output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_TX_DATA_EN, // Scatter gather for TX data enable
output [C_NUM_CHNL-1:0] SG_TX_DONE, // Scatter gather for TX data complete
output [C_NUM_CHNL-1:0] SG_TX_ERR // Scatter gather for TX data completed with error
);
reg [1:0] rState=0;
reg [C_DATA_ADDR_WIDTH-1:0] rDataAddr=0;
reg [C_PCI_DATA_WIDTH-1:0] rData=0;
reg rTagFinished=0;
reg [C_NUM_TAGS-1:0] rClear=0;
reg [C_TAG_WIDTH-1:0] rTag=0;
reg [C_TAG_WIDTH-1:0] rTagCurr=0;
wire [C_TAG_WIDTH-1:0] wTagNext = rTag + 1'd1;
reg [5:0] rShift;
reg rDone=0;
reg rDoneLast=0;
reg rErr=0;
reg rErrLast=0;
reg [C_PCI_DATA_COUNT_WIDTH-1:0] rDE=0;
reg [C_TAG_DW_COUNT_WIDTH-1:0] rWords=0;
reg rLTE2Pkts=0;
reg [C_PCI_DATA_WIDTH-1:0] rDataOut={C_PCI_DATA_WIDTH{1'b0}};
reg [(3*16*C_PCI_DATA_COUNT_WIDTH)-1:0] rDEOut={3*16*C_PCI_DATA_COUNT_WIDTH{1'd0}};
reg [(3*16)-1:0] rDoneOut={3*16{1'd0}};
reg [(3*16)-1:0] rErrOut={3*16{1'd0}};
assign DATA_ADDR = rDataAddr;
assign TAG = rTag;
assign TAG_CLEAR = rClear;
assign ENG_DATA = rDataOut;
assign MAIN_DATA_EN = rDEOut[(0*16*C_PCI_DATA_COUNT_WIDTH) +:(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)];
assign MAIN_DONE = rDoneOut[(0*16) +:C_NUM_CHNL];
assign MAIN_ERR = rErrOut[(0*16) +:C_NUM_CHNL];
assign SG_RX_DATA_EN = rDEOut[(1*16*C_PCI_DATA_COUNT_WIDTH) +:(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)];
assign SG_RX_DONE = rDoneOut[(1*16) +:C_NUM_CHNL];
assign SG_RX_ERR = rErrOut[(1*16) +:C_NUM_CHNL];
assign SG_TX_DATA_EN = rDEOut[(2*16*C_PCI_DATA_COUNT_WIDTH) +:(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)];
assign SG_TX_DONE = rDoneOut[(2*16) +:C_NUM_CHNL];
assign SG_TX_ERR = rErrOut[(2*16) +:C_NUM_CHNL];
// Output completed data in increasing tag order, avoid stalls if possible
always @ (posedge CLK) begin
if (RST) begin
rState <= #1 0;
rTag <= #1 0;
rDataAddr <= #1 0;
rDone <= #1 0;
rErr <= #1 0;
rDE <= #1 0;
rClear <= #1 0;
rTagFinished <= #1 0;
rShift <= 0; // Added
end
else begin
rTagFinished <= #1 TAG_FINISHED[rTag];
case (rState)
2'd0: begin // Request initial data and final info, output nothing
rDone <= #1 0;
rErr <= #1 0;
rDE <= #1 0;
rClear <= #1 0;
if (rTagFinished) begin
rTag <= #1 wTagNext;
rTagCurr <= #1 rTag;
rDataAddr <= #1 rDataAddr + 1'd1;
rState <= #1 2'd2;
end
else begin
rState <= #1 2'd0;
end
end
2'd1: begin // Request initial data and final info, output last data
rDone <= #1 rDoneLast;
rErr <= #1 rErrLast;
rDE <= #1 rWords[C_PCI_DATA_COUNT_WIDTH-1:0];
rClear <= #1 1<<rTagCurr; // Clear the tag
if (rTagFinished) begin
rTag <= #1 wTagNext;
rTagCurr <= #1 rTag;
rDataAddr <= #1 rDataAddr + 1'd1;
rState <= #1 2'd2;
end
else begin
rState <= #1 2'd0;
end
end
2'd2: begin // Initial data now available, output data
rShift <= #1 TAG_MAPPED;
rDoneLast <= #1 PKT_DONE;
rErrLast <= #1 PKT_ERR;
rWords <= #1 PKT_WORDS - C_PCI_DATA_WORD[C_PCI_DATA_WORD_WIDTH:0];
rLTE2Pkts <= #1 (PKT_WORDS <= (C_PCI_DATA_WORD*3));
if (PKT_WORDS_LTE1) begin // Guessed wrong, no addl data, need to reset
rDone <= #1 PKT_DONE;
rErr <= #1 PKT_ERR;
rDE <= #1 PKT_WORDS[C_PCI_DATA_COUNT_WIDTH-1:0];
rClear <= #1 1<<rTagCurr; // Clear the tag
rDataAddr <= #1 rTag<<C_DATA_ADDR_STRIDE_WIDTH; // rTag is already on the next
rState <= #1 2'd0;
end
else if (PKT_WORDS_LTE2) begin // Guessed right, end of data, output last and continue
rDone <= #1 0;
rErr <= #1 0;
rDE <= #1 C_PCI_DATA_WORD[C_PCI_DATA_WORD_WIDTH:0];
rClear <= #1 0;
rDataAddr <= #1 rTag<<C_DATA_ADDR_STRIDE_WIDTH; // rTag is already on the next
rState <= #1 2'd1;
end
else begin // Guessed right, more data, output it and continue
rDone <= #1 0;
rErr <= #1 0;
rDE <= #1 C_PCI_DATA_WORD[C_PCI_DATA_WORD_WIDTH:0];
rClear <= #1 0;
rDataAddr <= #1 rDataAddr + 1'd1;
rState <= #1 2'd3;
end
end
2'd3: begin // Next data now available, output data
rDone <= #1 0;
rErr <= #1 0;
rDE <= #1 C_PCI_DATA_WORD[C_PCI_DATA_WORD_WIDTH:0];
rWords <= #1 rWords - C_PCI_DATA_WORD[C_PCI_DATA_WORD_WIDTH:0];
rLTE2Pkts <= #1 (rWords <= (C_PCI_DATA_WORD*3));
if (rLTE2Pkts) begin // End of data, output last and continue
rDataAddr <= #1 rTag<<C_DATA_ADDR_STRIDE_WIDTH; // rTag is already on the next
rState <= #1 2'd1;
end
else begin // More data, output it and continue
rDataAddr <= #1 rDataAddr + 1'd1;
rState <= #1 2'd3;
end
end
endcase
end
end
// Output the data
always @ (posedge CLK) begin
rData <= #1 DATA;
rDataOut <= #1 rData;
if (RST) begin
rDEOut <= #1 0;
rDoneOut <= #1 0;
rErrOut <= #1 0;
end
else begin
rDEOut <= #1 rDE<<(C_PCI_DATA_COUNT_WIDTH*rShift);
rDoneOut <= #1 (rDone | rErr)<<rShift;
rErrOut <= #1 rErr<<rShift;
end
end
/*
wire [35:0] wControl0;
chipscope_icon_1 cs_icon(
.CONTROL0(wControl0)
);
chipscope_ila_t8_512 a0(
.CLK(DVI_CLK),
.CONTROL(wControl0),
.TRIG0({wFifoFull, wFifoEmpty, rState, rPrevDVI_VS, DVI_DE, DVI_HS, DVI_VS}),
.DATA({457'd0,
rCount, // 21
rFrameCount, // 21
wCapture, // 1
RD_EN, // 1
RD_EMPTY, // 1
EOF, // 1
wPackerFull, // 1
wFifoFull, // 1
wFifoEmpty, // 1
rState, // 2
rPrevDVI_VS, // 1
DVI_DE, // 1
DVI_HS, // 1
DVI_VS}) // 1
);
*/
endmodule