mirror of
https://github.com/KastnerRG/riffa.git
synced 2025-01-30 23:02:54 +08:00
273 lines
9.3 KiB
Verilog
273 lines
9.3 KiB
Verilog
// ----------------------------------------------------------------------
|
|
// 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: sg_list_requester.v
|
|
// Version: 1.00.a
|
|
// Verilog Standard: Verilog-2001
|
|
// Description: Receives scatter gather address/length info and requests
|
|
// the scatter gather data from the RX engine. Monitors the state of the scatter
|
|
// gather FIFO to make sure it can accommodate the requested data. Also signals
|
|
// when the entire scatter gather data has been received so the buffer can be
|
|
// overwritten with new data.
|
|
// Author: Matt Jacobsen
|
|
// History: @mattj: Version 2.0
|
|
//-----------------------------------------------------------------------------
|
|
`define S_SGREQ_IDLE 8'b0000_0001
|
|
`define S_SGREQ_WAIT_0 8'b0000_0010
|
|
`define S_SGREQ_WAIT_1 8'b0000_0100
|
|
`define S_SGREQ_CHECK 8'b0000_1000
|
|
`define S_SGREQ_ISSUE 8'b0001_0000
|
|
`define S_SGREQ_UPDATE 8'b0010_0000
|
|
`define S_SGREQ_COUNT 8'b0100_0000
|
|
`define S_SGREQ_FLUSH 8'b1000_0000
|
|
|
|
`timescale 1ns/1ns
|
|
module sg_list_requester #(
|
|
parameter C_FIFO_DATA_WIDTH = 9'd64,
|
|
parameter C_FIFO_DEPTH = 1024,
|
|
parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
|
|
// Local parameters
|
|
parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1),
|
|
parameter C_WORDS_PER_ELEM = 4,
|
|
parameter C_MAX_ELEMS = 200,
|
|
parameter C_MAX_ENTRIES = (C_MAX_ELEMS*C_WORDS_PER_ELEM),
|
|
parameter C_FIFO_COUNT_THRESH = C_FIFO_DEPTH - C_MAX_ENTRIES
|
|
)
|
|
(
|
|
input CLK,
|
|
input RST,
|
|
input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
|
|
|
|
input USER_RST, // User reset, should clear FIFO data too
|
|
|
|
output BUF_RECVD, // Signals when scatter gather buffer received
|
|
input [31:0] BUF_DATA, // Buffer data
|
|
input BUF_LEN_VALID, // Buffer length valid
|
|
input BUF_ADDR_HI_VALID, // Buffer high address valid
|
|
input BUF_ADDR_LO_VALID, // Buffer low address valid
|
|
|
|
input [C_FIFO_DEPTH_WIDTH-1:0] FIFO_COUNT, // Scatter gather FIFO count
|
|
output FIFO_FLUSH, // Scatter gather FIFO flush request
|
|
input FIFO_FLUSHED, // Scatter gather FIFO flushed
|
|
output FIFO_RST, // Scatter gather FIFO data reset request
|
|
|
|
output RX_REQ, // Issue a read request
|
|
output [63:0] RX_ADDR, // Request address
|
|
output [9:0] RX_LEN, // Request length
|
|
input RX_REQ_ACK, // Request has been issued
|
|
input RX_DONE // Request has completed (data received)
|
|
);
|
|
|
|
`include "functions.vh"
|
|
|
|
reg [31:0] rData=0, _rData=0;
|
|
reg rAddrHiValid=0, _rAddrHiValid=0;
|
|
reg rAddrLoValid=0, _rAddrLoValid=0;
|
|
reg rLenValid=0, _rLenValid=0;
|
|
|
|
(* syn_encoding = "user" *)
|
|
(* fsm_encoding = "user" *)
|
|
reg [7:0] rState=`S_SGREQ_IDLE, _rState=`S_SGREQ_IDLE;
|
|
reg rDone=0, _rDone=0;
|
|
reg rDelay=0, _rDelay=0;
|
|
reg [2:0] rCarry=0, _rCarry=0;
|
|
reg [3:0] rValsProp=0, _rValsProp=0;
|
|
reg [63:0] rAddr=64'd0, _rAddr=64'd0;
|
|
reg [31:0] rBufWords=0, _rBufWords=0;
|
|
reg [10:0] rPageRem=0, _rPageRem=0;
|
|
reg rPageSpill=0, _rPageSpill=0;
|
|
reg [10:0] rPreLen=0, _rPreLen=0;
|
|
reg [2:0] rMaxPayloadTrain=0, _rMaxPayloadTrain=0;
|
|
reg [2:0] rMaxPayloadShift=0, _rMaxPayloadShift=0;
|
|
reg [9:0] rMaxPayload=0, _rMaxPayload=0;
|
|
reg rPayloadSpill=0, _rPayloadSpill=0;
|
|
reg [9:0] rLen=0, _rLen=0;
|
|
reg rBufWordsEQ0Hi=0, _rBufWordsEQ0Hi=0;
|
|
reg rBufWordsEQ0Lo=0, _rBufWordsEQ0Lo=0;
|
|
reg rUserRst=0, _rUserRst=0;
|
|
|
|
reg rRecvdAll=0, _rRecvdAll=0;
|
|
reg [10:0] rAckCount=0, _rAckCount=0;
|
|
|
|
|
|
assign BUF_RECVD = rDone;
|
|
|
|
assign FIFO_FLUSH = rState[7]; // S_SGREQ_FLUSH
|
|
assign FIFO_RST = (rUserRst & rState[0]); // S_SGREQ_IDLE
|
|
|
|
assign RX_ADDR = rAddr;
|
|
assign RX_LEN = rLen;
|
|
assign RX_REQ = rState[4]; // S_SGREQ_ISSUE
|
|
|
|
|
|
// Buffer signals coming from outside the rx_port.
|
|
always @ (posedge CLK) begin
|
|
rData <= #1 _rData;
|
|
rAddrHiValid <= #1 _rAddrHiValid;
|
|
rAddrLoValid <= #1 _rAddrLoValid;
|
|
rLenValid <= #1 _rLenValid;
|
|
end
|
|
|
|
always @ (*) begin
|
|
_rData = BUF_DATA;
|
|
_rAddrHiValid = BUF_ADDR_HI_VALID;
|
|
_rAddrLoValid = BUF_ADDR_LO_VALID;
|
|
_rLenValid = BUF_LEN_VALID;
|
|
end
|
|
|
|
|
|
// Handle requesting the next scatter gather buffer data.
|
|
wire [9:0] wAddrLoInv = ~rAddr[11:2];
|
|
always @ (posedge CLK) begin
|
|
rState <= #1 (RST ? `S_SGREQ_IDLE : _rState);
|
|
rDone <= #1 (RST ? 1'd0 : _rDone);
|
|
rDelay <= #1 _rDelay;
|
|
rAddr <= #1 _rAddr;
|
|
rCarry <= #1 _rCarry;
|
|
rBufWords <= #1 _rBufWords;
|
|
rValsProp <= #1 _rValsProp;
|
|
rPageRem <= #1 _rPageRem;
|
|
rPageSpill <= #1 _rPageSpill;
|
|
rPreLen <= #1 _rPreLen;
|
|
rMaxPayloadTrain <= #1 _rMaxPayloadTrain;
|
|
rMaxPayloadShift <= #1 _rMaxPayloadShift;
|
|
rMaxPayload <= #1 _rMaxPayload;
|
|
rPayloadSpill <= #1 _rPayloadSpill;
|
|
rLen <= #1 _rLen;
|
|
rBufWordsEQ0Hi <= #1 _rBufWordsEQ0Hi;
|
|
rBufWordsEQ0Lo <= #1 _rBufWordsEQ0Lo;
|
|
rUserRst <= #1 (RST ? 1'd0 : _rUserRst);
|
|
end
|
|
|
|
always @ (*) begin
|
|
_rState = rState;
|
|
_rDone = rDone;
|
|
_rDelay = rDelay;
|
|
|
|
_rUserRst = ((rUserRst & !rState[0]) | USER_RST);
|
|
_rValsProp = ((rValsProp<<1) | RX_REQ_ACK);
|
|
{_rCarry[0], _rAddr[15:0]} = (rAddrLoValid ? rData[15:0] : (rAddr[15:0] + ({12{RX_REQ_ACK}} & {2'b0,rLen}<<2)));
|
|
{_rCarry[1], _rAddr[31:16]} = (rAddrLoValid ? rData[31:16] : (rAddr[31:16] + rCarry[0]));
|
|
{_rCarry[2], _rAddr[47:32]} = (rAddrHiValid ? rData[15:0] : (rAddr[47:32] + rCarry[1]));
|
|
_rAddr[63:48] = (rAddrHiValid ? rData[31:16] : (rAddr[63:48] + rCarry[2]));
|
|
_rBufWords = (rLenValid ? rData : rBufWords) - ({10{RX_REQ_ACK}} & rLen);
|
|
_rPageRem = (wAddrLoInv + 1'd1);
|
|
_rPageSpill = (rBufWords > rPageRem);
|
|
_rPreLen = (rPageSpill ? rPageRem : rBufWords[10:0]);
|
|
_rMaxPayloadTrain = (CONFIG_MAX_READ_REQUEST_SIZE > 3'd4 ? 3'd4 : CONFIG_MAX_READ_REQUEST_SIZE);
|
|
_rMaxPayloadShift = (C_MAX_READ_REQ[2:0] < rMaxPayloadTrain ? C_MAX_READ_REQ[2:0] : rMaxPayloadTrain);
|
|
_rMaxPayload = (6'd32<<rMaxPayloadShift);
|
|
_rPayloadSpill = (rPreLen > rMaxPayload);
|
|
_rLen = (rPayloadSpill ? rMaxPayload : rPreLen[9:0]);
|
|
_rBufWordsEQ0Hi = (16'd0 == rBufWords[31:16]);
|
|
_rBufWordsEQ0Lo = (16'd0 == rBufWords[15:0]);
|
|
|
|
case (rState)
|
|
|
|
`S_SGREQ_IDLE: begin // Wait for addr & length
|
|
_rDone = 0;
|
|
if (rLenValid)
|
|
_rState = `S_SGREQ_WAIT_0;
|
|
end
|
|
|
|
`S_SGREQ_WAIT_0: begin // Wait 1 cycle for values to propagate
|
|
_rDelay = 0;
|
|
_rState = `S_SGREQ_WAIT_1;
|
|
end
|
|
|
|
`S_SGREQ_WAIT_1: begin // Wait 2 cycles for values to propagate
|
|
_rDelay = 1;
|
|
if (rDelay)
|
|
_rState = `S_SGREQ_CHECK;
|
|
end
|
|
|
|
`S_SGREQ_CHECK: begin // Wait for space to be made available
|
|
if (FIFO_COUNT < C_FIFO_COUNT_THRESH)
|
|
_rState = `S_SGREQ_ISSUE;
|
|
else if (rUserRst)
|
|
_rState = `S_SGREQ_COUNT;
|
|
end
|
|
|
|
`S_SGREQ_ISSUE: begin // Wait for read request to be serviced
|
|
if (RX_REQ_ACK)
|
|
_rState = `S_SGREQ_UPDATE;
|
|
end
|
|
|
|
`S_SGREQ_UPDATE: begin // Update the address and length
|
|
if (rUserRst | (rBufWordsEQ0Hi & rBufWordsEQ0Lo))
|
|
_rState = `S_SGREQ_COUNT;
|
|
else if (rValsProp[3])
|
|
_rState = `S_SGREQ_ISSUE;
|
|
end
|
|
|
|
`S_SGREQ_COUNT: begin // Wait for read data to arrive
|
|
if (rRecvdAll)
|
|
_rState = `S_SGREQ_FLUSH;
|
|
end
|
|
|
|
`S_SGREQ_FLUSH: begin // Wait for read data to arrive
|
|
if (FIFO_FLUSHED) begin
|
|
_rDone = !rUserRst;
|
|
_rState = `S_SGREQ_IDLE;
|
|
end
|
|
end
|
|
|
|
default: begin
|
|
_rState = `S_SGREQ_IDLE;
|
|
end
|
|
|
|
endcase
|
|
end
|
|
|
|
|
|
// Keep track of requests made and requests completed so we know when all
|
|
// the outstanding data has been received.
|
|
always @ (posedge CLK) begin
|
|
rAckCount <= #1 (RST ? 10'd0 : _rAckCount);
|
|
rRecvdAll <= #1 _rRecvdAll;
|
|
end
|
|
|
|
always @ (*) begin
|
|
// Track REQ_DONE and SG_DONE to maintain an outstanding request count.
|
|
_rRecvdAll = (rAckCount == 10'd0);
|
|
if (rState[0]) // S_SGREQ_IDLE
|
|
_rAckCount = 0;
|
|
else
|
|
_rAckCount = rAckCount + RX_REQ_ACK - RX_DONE;
|
|
end
|
|
|
|
|
|
endmodule
|