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

495 lines
16 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: rx_port_32.v
// Version: 1.00.a
// Verilog Standard: Verilog-2001
// Description: Receives data from the rx_engine and buffers the output
// for the RIFFA channel.
// Author: Matt Jacobsen
// History: @mattj: Version 2.0
//-----------------------------------------------------------------------------
`timescale 1ns/1ns
module rx_port_32 #(
parameter C_DATA_WIDTH = 9'd32,
parameter C_MAIN_FIFO_DEPTH = 1024,
parameter C_SG_FIFO_DEPTH = 512,
parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
// Local parameters
parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1),
parameter C_MAIN_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_MAIN_FIFO_DEPTH))+1),
parameter C_SG_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_SG_FIFO_DEPTH))+1)
)
(
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
output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable)
input [31:0] SG_RX_BUF_DATA, // Scatter gather RX buffer data
input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid
input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid
input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid
output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable)
input [31:0] SG_TX_BUF_DATA, // Scatter gather TX buffer data
input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid
input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid
input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid
output [C_DATA_WIDTH-1:0] SG_DATA, // Scatter gather TX buffer data
output SG_DATA_EMPTY, // Scatter gather TX buffer data empty
input SG_DATA_REN, // Scatter gather TX buffer data read enable
input SG_RST, // Scatter gather TX buffer data reset
output SG_ERR, // Scatter gather TX encountered an error
input [31:0] TXN_DATA, // Read transaction data
input TXN_LEN_VALID, // Read transaction length valid
input TXN_OFF_LAST_VALID, // Read transaction offset/last valid
output [31:0] TXN_DONE_LEN, // Read transaction actual transfer length
output TXN_DONE, // Read transaction done
input TXN_DONE_ACK, // Read transaction actual transfer length read
output RX_REQ, // Read request
input RX_REQ_ACK, // Read request accepted
output [1:0] RX_REQ_TAG, // Read request data tag
output [63:0] RX_REQ_ADDR, // Read request address
output [9:0] RX_REQ_LEN, // Read request length
input [C_DATA_WIDTH-1:0] MAIN_DATA, // Main incoming data
input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable
input MAIN_DONE, // Main incoming data complete
input MAIN_ERR, // Main incoming data completed with error
input [C_DATA_WIDTH-1:0] SG_RX_DATA, // Scatter gather for RX incoming data
input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable
input SG_RX_DONE, // Scatter gather for RX incoming data complete
input SG_RX_ERR, // Scatter gather for RX incoming data completed with error
input [C_DATA_WIDTH-1:0] SG_TX_DATA, // Scatter gather for TX incoming data
input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable
input SG_TX_DONE, // Scatter gather for TX incoming data complete
input SG_TX_ERR, // Scatter gather for TX incoming data completed with error
input CHNL_CLK, // Channel read clock
output CHNL_RX, // Channel read receive signal
input CHNL_RX_ACK, // Channle read received signal
output CHNL_RX_LAST, // Channel last read
output [31:0] CHNL_RX_LEN, // Channel read length
output [30:0] CHNL_RX_OFF, // Channel read offset
output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data
output CHNL_RX_DATA_VALID, // Channel read data valid
input CHNL_RX_DATA_REN // Channel read data has been recieved
);
`include "functions.vh"
wire [C_DATA_WIDTH-1:0] wPackedMainData;
wire wPackedMainWen;
wire wPackedMainDone;
wire wPackedMainErr;
wire wMainFlush;
wire wMainFlushed;
wire [C_DATA_WIDTH-1:0] wPackedSgRxData;
wire wPackedSgRxWen;
wire wPackedSgRxDone;
wire wPackedSgRxErr;
wire wSgRxFlush;
wire wSgRxFlushed;
wire [C_DATA_WIDTH-1:0] wPackedSgTxData;
wire wPackedSgTxWen;
wire wPackedSgTxDone;
wire wPackedSgTxErr;
wire wSgTxFlush;
wire wSgTxFlushed;
wire wMainDataRen;
wire wMainDataEmpty;
wire [C_DATA_WIDTH-1:0] wMainData;
wire wSgRxRst;
wire wSgRxDataRen;
wire wSgRxDataEmpty;
wire [C_DATA_WIDTH-1:0] wSgRxData;
wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgRxFifoCount;
wire wSgTxRst;
wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgTxFifoCount;
wire wSgRxReq;
wire [63:0] wSgRxReqAddr;
wire [9:0] wSgRxReqLen;
wire wSgTxReq;
wire [63:0] wSgTxReqAddr;
wire [9:0] wSgTxReqLen;
wire wSgRxReqProc;
wire wSgTxReqProc;
wire wMainReqProc;
wire wReqAck;
wire wSgElemRdy;
wire wSgElemRen;
wire [63:0] wSgElemAddr;
wire [31:0] wSgElemLen;
wire wSgRst;
wire wMainReq;
wire [63:0] wMainReqAddr;
wire [9:0] wMainReqLen;
wire wTxnErr;
wire wChnlRx;
wire wChnlRxRecvd;
wire wChnlRxAckRecvd;
wire wChnlRxLast;
wire [31:0] wChnlRxLen;
wire [30:0] wChnlRxOff;
wire [31:0] wChnlRxConsumed;
reg [4:0] rWideRst=0;
reg rRst=0;
assign SG_ERR = (wPackedSgTxDone & wPackedSgTxErr);
// Generate a wide reset from the input reset.
always @ (posedge CLK) begin
rRst <= #1 rWideRst[4];
if (RST)
rWideRst <= #1 5'b11111;
else
rWideRst <= (rWideRst<<1);
end
// Pack received data tightly into our FIFOs
fifo_packer_32 mainFifoPacker (
.CLK(CLK),
.RST(rRst),
.DATA_IN(MAIN_DATA),
.DATA_IN_EN(MAIN_DATA_EN),
.DATA_IN_DONE(MAIN_DONE),
.DATA_IN_ERR(MAIN_ERR),
.DATA_IN_FLUSH(wMainFlush),
.PACKED_DATA(wPackedMainData),
.PACKED_WEN(wPackedMainWen),
.PACKED_DATA_DONE(wPackedMainDone),
.PACKED_DATA_ERR(wPackedMainErr),
.PACKED_DATA_FLUSHED(wMainFlushed)
);
fifo_packer_32 sgRxFifoPacker (
.CLK(CLK),
.RST(rRst),
.DATA_IN(SG_RX_DATA),
.DATA_IN_EN(SG_RX_DATA_EN),
.DATA_IN_DONE(SG_RX_DONE),
.DATA_IN_ERR(SG_RX_ERR),
.DATA_IN_FLUSH(wSgRxFlush),
.PACKED_DATA(wPackedSgRxData),
.PACKED_WEN(wPackedSgRxWen),
.PACKED_DATA_DONE(wPackedSgRxDone),
.PACKED_DATA_ERR(wPackedSgRxErr),
.PACKED_DATA_FLUSHED(wSgRxFlushed)
);
fifo_packer_32 sgTxFifoPacker (
.CLK(CLK),
.RST(rRst),
.DATA_IN(SG_TX_DATA),
.DATA_IN_EN(SG_TX_DATA_EN),
.DATA_IN_DONE(SG_TX_DONE),
.DATA_IN_ERR(SG_TX_ERR),
.DATA_IN_FLUSH(wSgTxFlush),
.PACKED_DATA(wPackedSgTxData),
.PACKED_WEN(wPackedSgTxWen),
.PACKED_DATA_DONE(wPackedSgTxDone),
.PACKED_DATA_ERR(wPackedSgTxErr),
.PACKED_DATA_FLUSHED(wSgTxFlushed)
);
// FIFOs for storing received data for the channel.
(* RAM_STYLE="BLOCK" *)
async_fifo_fwft #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_MAIN_FIFO_DEPTH)) mainFifo (
.WR_CLK(CLK),
.WR_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst),
.WR_EN(wPackedMainWen),
.WR_DATA(wPackedMainData),
.WR_FULL(),
.RD_CLK(CHNL_CLK),
.RD_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst),
.RD_EN(wMainDataRen),
.RD_DATA(wMainData),
.RD_EMPTY(wMainDataEmpty)
);
(* RAM_STYLE="BLOCK" *)
sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgRxFifo (
.RST(rRst | wSgRxRst),
.CLK(CLK),
.WR_EN(wPackedSgRxWen),
.WR_DATA(wPackedSgRxData),
.FULL(),
.RD_EN(wSgRxDataRen),
.RD_DATA(wSgRxData),
.EMPTY(wSgRxDataEmpty),
.COUNT(wSgRxFifoCount)
);
(* RAM_STYLE="BLOCK" *)
sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgTxFifo (
.RST(rRst | wSgTxRst),
.CLK(CLK),
.WR_EN(wPackedSgTxWen),
.WR_DATA(wPackedSgTxData),
.FULL(),
.RD_EN(SG_DATA_REN),
.RD_DATA(SG_DATA),
.EMPTY(SG_DATA_EMPTY),
.COUNT(wSgTxFifoCount)
);
// Manage requesting and acknowledging scatter gather data. Note that
// these modules will share the main requestor's RX channel. They will
// take priority over the main logic's use of the RX channel.
sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgRxReq (
.CLK(CLK),
.RST(rRst),
.CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE),
.USER_RST(wSgRst),
.BUF_RECVD(SG_RX_BUF_RECVD),
.BUF_DATA(SG_RX_BUF_DATA),
.BUF_LEN_VALID(SG_RX_BUF_LEN_VALID),
.BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID),
.BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID),
.FIFO_COUNT(wSgRxFifoCount),
.FIFO_FLUSH(wSgRxFlush),
.FIFO_FLUSHED(wSgRxFlushed),
.FIFO_RST(wSgRxRst),
.RX_REQ(wSgRxReq),
.RX_ADDR(wSgRxReqAddr),
.RX_LEN(wSgRxReqLen),
.RX_REQ_ACK(wReqAck & wSgRxReqProc),
.RX_DONE(wPackedSgRxDone)
);
sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgTxReq (
.CLK(CLK),
.RST(rRst),
.CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE),
.USER_RST(SG_RST),
.BUF_RECVD(SG_TX_BUF_RECVD),
.BUF_DATA(SG_TX_BUF_DATA),
.BUF_LEN_VALID(SG_TX_BUF_LEN_VALID),
.BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID),
.BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID),
.FIFO_COUNT(wSgTxFifoCount),
.FIFO_FLUSH(wSgTxFlush),
.FIFO_FLUSHED(wSgTxFlushed),
.FIFO_RST(wSgTxRst),
.RX_REQ(wSgTxReq),
.RX_ADDR(wSgTxReqAddr),
.RX_LEN(wSgTxReqLen),
.RX_REQ_ACK(wReqAck & wSgTxReqProc),
.RX_DONE(wPackedSgTxDone)
);
// A read requester for the channel and scatter gather requesters.
rx_port_requester_mux requesterMux (
.RST(rRst),
.CLK(CLK),
.SG_RX_REQ(wSgRxReq),
.SG_RX_LEN(wSgRxReqLen),
.SG_RX_ADDR(wSgRxReqAddr),
.SG_RX_REQ_PROC(wSgRxReqProc),
.SG_TX_REQ(wSgTxReq),
.SG_TX_LEN(wSgTxReqLen),
.SG_TX_ADDR(wSgTxReqAddr),
.SG_TX_REQ_PROC(wSgTxReqProc),
.MAIN_REQ(wMainReq),
.MAIN_LEN(wMainReqLen),
.MAIN_ADDR(wMainReqAddr),
.MAIN_REQ_PROC(wMainReqProc),
.RX_REQ(RX_REQ),
.RX_REQ_ACK(RX_REQ_ACK),
.RX_REQ_TAG(RX_REQ_TAG),
.RX_REQ_ADDR(RX_REQ_ADDR),
.RX_REQ_LEN(RX_REQ_LEN),
.REQ_ACK(wReqAck)
);
// Read the scatter gather buffer address and length, continuously so that
// we have it ready whenever the next buffer is needed.
sg_list_reader_32 #(.C_DATA_WIDTH(C_DATA_WIDTH)) sgListReader (
.CLK(CLK),
.RST(rRst | wSgRst),
.BUF_DATA(wSgRxData),
.BUF_DATA_EMPTY(wSgRxDataEmpty),
.BUF_DATA_REN(wSgRxDataRen),
.VALID(wSgElemRdy),
.EMPTY(),
.REN(wSgElemRen),
.ADDR(wSgElemAddr),
.LEN(wSgElemLen)
);
// Main port reader logic
rx_port_reader #(.C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_MAIN_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) reader (
.CLK(CLK),
.RST(rRst),
.CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE),
.TXN_DATA(TXN_DATA),
.TXN_LEN_VALID(TXN_LEN_VALID),
.TXN_OFF_LAST_VALID(TXN_OFF_LAST_VALID),
.TXN_DONE_LEN(TXN_DONE_LEN),
.TXN_DONE(TXN_DONE),
.TXN_ERR(wTxnErr),
.TXN_DONE_ACK(TXN_DONE_ACK),
.TXN_DATA_FLUSH(wMainFlush),
.TXN_DATA_FLUSHED(wMainFlushed),
.RX_REQ(wMainReq),
.RX_ADDR(wMainReqAddr),
.RX_LEN(wMainReqLen),
.RX_REQ_ACK(wReqAck & wMainReqProc),
.RX_DATA_EN(MAIN_DATA_EN),
.RX_DONE(wPackedMainDone),
.RX_ERR(wPackedMainErr),
.SG_DONE(wPackedSgRxDone),
.SG_ERR(wPackedSgRxErr),
.SG_ELEM_ADDR(wSgElemAddr),
.SG_ELEM_LEN(wSgElemLen),
.SG_ELEM_RDY(wSgElemRdy),
.SG_ELEM_REN(wSgElemRen),
.SG_RST(wSgRst),
.CHNL_RX(wChnlRx),
.CHNL_RX_LEN(wChnlRxLen),
.CHNL_RX_LAST(wChnlRxLast),
.CHNL_RX_OFF(wChnlRxOff),
.CHNL_RX_RECVD(wChnlRxRecvd),
.CHNL_RX_ACK_RECVD(wChnlRxAckRecvd),
.CHNL_RX_CONSUMED(wChnlRxConsumed)
);
// Manage the CHNL_RX* signals in the CHNL_CLK domain.
rx_port_channel_gate #(.C_DATA_WIDTH(C_DATA_WIDTH)) gate (
.RST(rRst),
.CLK(CLK),
.RX(wChnlRx),
.RX_RECVD(wChnlRxRecvd),
.RX_ACK_RECVD(wChnlRxAckRecvd),
.RX_LAST(wChnlRxLast),
.RX_LEN(wChnlRxLen),
.RX_OFF(wChnlRxOff),
.RX_CONSUMED(wChnlRxConsumed),
.RD_DATA(wMainData),
.RD_EMPTY(wMainDataEmpty),
.RD_EN(wMainDataRen),
.CHNL_CLK(CHNL_CLK),
.CHNL_RX(CHNL_RX),
.CHNL_RX_ACK(CHNL_RX_ACK),
.CHNL_RX_LAST(CHNL_RX_LAST),
.CHNL_RX_LEN(CHNL_RX_LEN),
.CHNL_RX_OFF(CHNL_RX_OFF),
.CHNL_RX_DATA(CHNL_RX_DATA),
.CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID),
.CHNL_RX_DATA_REN(CHNL_RX_DATA_REN)
);
/*
wire [35:0] wControl0;
chipscope_icon_1 cs_icon(
.CONTROL0(wControl0)
);
chipscope_ila_t8_512 a0(
.CLK(CLK),
.CONTROL(wControl0),
.TRIG0({SG_RX_DATA_EN != 0, wSgElemRen, wMainReq | wSgRxReq | wSgTxReq,
RX_REQ, SG_RX_BUF_ADDR_LO_VALID | SG_RX_BUF_ADDR_HI_VALID | SG_RX_BUF_LEN_VALID,
wSgRst, wTxnErr | wPackedSgRxDone | wSgRxFlush | wSgRxFlushed, TXN_OFF_LAST_VALID | TXN_LEN_VALID}),
.DATA({
wPackedSgRxErr, // 1
wPackedSgRxDone, // 1
wPackedSgRxWen, // 1
wPackedSgRxData, // 64
SG_RX_ERR, // 1
SG_RX_DONE, // 1
SG_RX_DATA_EN, // 2
SG_RX_DATA, // 64
wSgRxDataRen, // 1
wSgRxDataEmpty, // 1
wSgRxData, // 64
wSgRst, // 1
SG_RST, // 1
wPackedSgRxDone, // 1
wSgRxRst, // 1
wSgRxFlushed, // 1
wSgRxFlush, // 1
SG_RX_BUF_ADDR_LO_VALID, // 1
SG_RX_BUF_ADDR_HI_VALID, // 1
SG_RX_BUF_LEN_VALID, // 1
SG_RX_BUF_DATA, // 32
RX_REQ_ADDR, // 64
RX_REQ_TAG, // 2
RX_REQ_ACK, // 1
RX_REQ, // 1
wSgTxReqProc, // 1
wSgTxReqAddr, // 64
wSgTxReq, // 1
wSgRxReqProc, // 1
wSgRxReqAddr, // 64
wSgRxReq, // 1
wMainReqProc, // 1
wMainReqAddr, // 64
wMainReq, // 1
wReqAck, // 1
wTxnErr, // 1
TXN_OFF_LAST_VALID, // 1
TXN_LEN_VALID}) // 1
);
*/
endmodule