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_reader.v

543 lines
18 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_reader.v
// Version: 1.00.a
// Verilog Standard: Verilog-2001
// Description: Handles the RX lifecycle and issuing requests for receiving
// data input.
// for the RIFFA channel.
// Author: Matt Jacobsen
// History: @mattj: Version 2.0
//-----------------------------------------------------------------------------
`define S_RXPORTRD_MAIN_IDLE 6'b00_0001
`define S_RXPORTRD_MAIN_CHECK 6'b00_0010
`define S_RXPORTRD_MAIN_READ 6'b00_0100
`define S_RXPORTRD_MAIN_FLUSH 6'b00_1000
`define S_RXPORTRD_MAIN_DONE 6'b01_0000
`define S_RXPORTRD_MAIN_RESET 6'b10_0000
`define S_RXPORTRD_RX_IDLE 8'b0000_0001
`define S_RXPORTRD_RX_BUF 8'b0000_0010
`define S_RXPORTRD_RX_ADJ_0 8'b0000_0100
`define S_RXPORTRD_RX_ADJ_1 8'b0000_1000
`define S_RXPORTRD_RX_ISSUE 8'b0001_0000
`define S_RXPORTRD_RX_WAIT_0 8'b0010_0000
`define S_RXPORTRD_RX_WAIT_1 8'b0100_0000
`define S_RXPORTRD_RX_DONE 8'b1000_0000
`timescale 1ns/1ns
module rx_port_reader #(
parameter C_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_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1),
parameter C_FIFO_WORDS = (C_DATA_WIDTH/32)*C_FIFO_DEPTH
)
(
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 [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
output TXN_ERR, // Read transaction completed with error
input TXN_DONE_ACK, // Read transaction actual transfer length read
output TXN_DATA_FLUSH, // Request that all data in the packer be flushed
input TXN_DATA_FLUSHED, // All data in the packer has been flushed
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 accepted
input [C_DATA_WORD_WIDTH-1:0] RX_DATA_EN, // Incoming read data enable
input RX_DONE, // Incoming read completed
input RX_ERR, // Incoming read completed with error
input SG_DONE, // Incoming scatter gather read completed
input SG_ERR, // Incoming scatter gather read completed with error
input [63:0] SG_ELEM_ADDR, // Scatter gather element address
input [31:0] SG_ELEM_LEN, // Scatter gather element length (in words)
input SG_ELEM_RDY, // Scatter gather element ready
output SG_ELEM_REN, // Scatter gather element read enable
output SG_RST, // Scatter gather reset
output CHNL_RX, // Signal channel RX
output [31:0] CHNL_RX_LEN, // Channel RX length
output CHNL_RX_LAST, // Channel RX last
output [30:0] CHNL_RX_OFF, // Channel RX offset
input CHNL_RX_RECVD, // Channel RX received
input CHNL_RX_ACK_RECVD, // Channel RX acknowledgment received
input [31:0] CHNL_RX_CONSUMED // Channel words consumed in current RX
);
`include "functions.vh"
reg [31:0] rTxnData=0, _rTxnData=0;
reg rTxnOffLastValid=0, _rTxnOffLastValid=0;
reg rTxnLenValid=0, _rTxnLenValid=0;
reg [C_DATA_WORD_WIDTH-1:0] rRxDataEn=0, _rRxDataEn=0;
(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg [5:0] rMainState=`S_RXPORTRD_MAIN_IDLE, _rMainState=`S_RXPORTRD_MAIN_IDLE;
reg [31:0] rOffLast=0, _rOffLast=0;
reg [31:0] rReadWords=0, _rReadWords=0;
reg rReadWordsZero=0, _rReadWordsZero=0;
reg [0:0] rStart=0, _rStart=0;
reg [3:0] rFlushed=0, _rFlushed=0;
reg [31:0] rDoneLen=0, _rDoneLen=0;
reg rTxnDone=0, _rTxnDone=0;
(* syn_encoding = "user" *)
(* fsm_encoding = "user" *)
reg [7:0] rRxState=`S_RXPORTRD_RX_IDLE, _rRxState=`S_RXPORTRD_RX_IDLE;
reg rSgRen=0, _rSgRen=0;
reg [31:0] rWords=0, _rWords=0;
reg [31:0] rBufWords=0, _rBufWords=0;
reg [31:0] rBufWordsInit=0, _rBufWordsInit=0;
reg rLargeBuf=0, _rLargeBuf=0;
reg [63:0] rAddr=64'd0, _rAddr=64'd0;
reg [3:0] rValsProp=0, _rValsProp=0;
reg [2:0] rCarry=0, _rCarry=0;
reg rCopyBufWords=0, _rCopyBufWords=0;
reg rUseInit=0, _rUseInit=0;
reg [10:0] rPageRem=0, _rPageRem=0;
reg rPageSpill=0, _rPageSpill=0;
reg rPageSpillInit=0, _rPageSpillInit=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 rMaxLen=0, _rMaxLen=0;
reg [9:0] rLen=0, _rLen=0;
reg rLenEQWordsHi=0, _rLenEQWordsHi=0;
reg rLenEQWordsLo=0, _rLenEQWordsLo=0;
reg rLenEQBufWordsHi=0, _rLenEQBufWordsHi=0;
reg rLenEQBufWordsLo=0, _rLenEQBufWordsLo=0;
reg [31:0] rRecvdWords=0, _rRecvdWords=0;
reg [31:0] rReqdWords=0, _rReqdWords=0;
reg [31:0] rRequestingWords=0, _rRequestingWords=0;
reg [31:0] rAvailWords=0, _rAvailWords=0;
reg [31:0] rPartWords=0, _rPartWords=0;
reg [10:0] rAckCount=0, _rAckCount=0;
reg rAckCountEQ0=0, _rAckCountEQ0=0;
reg rLastDoneRead=1, _rLastDoneRead=1;
reg rTxnDoneAck=0, _rTxnDoneAck=0;
reg rPartWordsRecvd=0, _rPartWordsRecvd=0;
reg rCarryInv=0, _rCarryInv=0;
reg rSpaceAvail=0, _rSpaceAvail=0;
reg rPartialDone=0, _rPartialDone=0;
reg rReqPartialDone=0, _rReqPartialDone=0;
reg rErr=0, _rErr=0;
assign TXN_DONE_LEN = rDoneLen;
assign TXN_DONE = (rTxnDone | rPartialDone);
assign TXN_ERR = rErr;
assign TXN_DATA_FLUSH = rMainState[3]; // S_RXPORTRD_MAIN_FLUSH
assign RX_REQ = (rRxState[4] & rSpaceAvail); // S_RXPORTRD_RX_ISSUE
assign RX_ADDR = rAddr;
assign RX_LEN = rLen;
assign SG_ELEM_REN = rSgRen;
assign SG_RST = rMainState[1]; // S_RXPORTRD_MAIN_CHECK
assign CHNL_RX = (rMainState[2] | rMainState[3] | rMainState[4]); // S_RXPORTRD_MAIN_READ | S_RXPORTRD_MAIN_FLUSH | S_RXPORTRD_MAIN_DONE
assign CHNL_RX_LEN = rReadWords;
assign CHNL_RX_LAST = rOffLast[0];
assign CHNL_RX_OFF = rOffLast[31:1];
// Buffer signals that come from outside the rx_port.
always @ (posedge CLK) begin
rTxnData <= #1 _rTxnData;
rTxnOffLastValid <= #1 _rTxnOffLastValid;
rTxnLenValid <= #1 _rTxnLenValid;
rTxnDoneAck <= #1 (RST ? 1'd0 : _rTxnDoneAck);
rRxDataEn <= #1 _rRxDataEn;
end
always @ (*) begin
_rTxnData = TXN_DATA;
_rTxnOffLastValid = TXN_OFF_LAST_VALID;
_rTxnLenValid = TXN_LEN_VALID;
_rTxnDoneAck = TXN_DONE_ACK;
_rRxDataEn = RX_DATA_EN;
end
// Handle RX lifecycle.
always @ (posedge CLK) begin
rMainState <= #1 (RST ? `S_RXPORTRD_MAIN_IDLE : _rMainState);
rOffLast <= #1 _rOffLast;
rReadWords <= #1 _rReadWords;
rReadWordsZero <= #1 _rReadWordsZero;
rStart <= #1 _rStart;
rFlushed <= #1 _rFlushed;
rDoneLen <= #1 (RST ? 0 : _rDoneLen);
rTxnDone <= #1 _rTxnDone;
end
always @ (*) begin
_rMainState = rMainState;
_rDoneLen = rDoneLen;
_rTxnDone = rTxnDone;
_rOffLast = (rTxnOffLastValid ? rTxnData : rOffLast);
_rReadWords = (rMainState[0] & rTxnLenValid ? rTxnData : rReadWords);
_rReadWordsZero = (rReadWords == 0);
_rStart = ((rStart<<1) | rTxnLenValid);
_rFlushed = ((rFlushed<<1) | TXN_DATA_FLUSHED);
case (rMainState)
`S_RXPORTRD_MAIN_IDLE: begin // Wait for new read transaction offset/last & length
_rTxnDone = 0;
if (rStart[0])
_rMainState = `S_RXPORTRD_MAIN_CHECK;
end
`S_RXPORTRD_MAIN_CHECK: begin // See if we should start a transaction
if (!rReadWordsZero)
_rMainState = `S_RXPORTRD_MAIN_READ;
else if (rOffLast[0])
_rMainState = `S_RXPORTRD_MAIN_FLUSH;
else
_rMainState = `S_RXPORTRD_MAIN_IDLE;
end
`S_RXPORTRD_MAIN_READ: begin // Issue read transfers, wait for data to arrive
if (rRxState[7] & rLastDoneRead) begin // S_RXPORTRD_RX_DONE
_rDoneLen = rRecvdWords;
_rMainState = `S_RXPORTRD_MAIN_FLUSH;
end
end
`S_RXPORTRD_MAIN_FLUSH: begin // Wait for data to be flushed
if (rFlushed[3])
_rMainState = `S_RXPORTRD_MAIN_DONE;
end
`S_RXPORTRD_MAIN_DONE: begin // Wait for RX to be received and ackd in the channel
if (CHNL_RX_RECVD & CHNL_RX_ACK_RECVD)
_rMainState = `S_RXPORTRD_MAIN_RESET;
end
`S_RXPORTRD_MAIN_RESET: begin // Wait until RX has dropped in the channel
if (!CHNL_RX_RECVD) begin
_rTxnDone = 1;
_rMainState = `S_RXPORTRD_MAIN_IDLE;
end
end
default: begin
_rMainState = `S_RXPORTRD_MAIN_IDLE;
end
endcase
end
// Issue the read requests at the buffer level. Decrement the amount requested
// after every request. Continue until all words have been requested.
wire [9:0] wAddrLoInv = ~rAddr[11:2];
always @ (posedge CLK) begin
rRxState <= #1 (RST ? `S_RXPORTRD_RX_IDLE : _rRxState);
rSgRen <= #1 (RST ? 1'd0: _rSgRen);
rWords <= #1 _rWords;
rBufWords <= #1 _rBufWords;
rBufWordsInit <= #1 _rBufWordsInit;
rLargeBuf <= #1 _rLargeBuf;
rAddr <= #1 _rAddr;
rCarry <= #1 _rCarry;
rValsProp <= #1 _rValsProp;
rPageRem <= #1 _rPageRem;
rPageSpill <= #1 _rPageSpill;
rPageSpillInit <= #1 _rPageSpillInit;
rCopyBufWords <= #1 _rCopyBufWords;
rUseInit <= #1 _rUseInit;
rPreLen <= #1 _rPreLen;
rMaxPayloadTrain <= #1 _rMaxPayloadTrain;
rMaxPayloadShift <= #1 _rMaxPayloadShift;
rMaxPayload <= #1 _rMaxPayload;
rPayloadSpill <= #1 _rPayloadSpill;
rMaxLen <= #1 _rMaxLen;
rLen <= #1 _rLen;
rLenEQWordsHi <= #1 _rLenEQWordsHi;
rLenEQWordsLo <= #1 _rLenEQWordsLo;
rLenEQBufWordsHi <= #1 _rLenEQBufWordsHi;
rLenEQBufWordsLo <= #1 _rLenEQBufWordsLo;
end
always @ (*) begin
_rRxState = rRxState;
_rCopyBufWords = rCopyBufWords;
_rUseInit = rUseInit;
_rSgRen = rSgRen;
_rValsProp = ((rValsProp<<1) | rRxState[2]); // S_RXPORTRD_RX_ADJ_0
_rLargeBuf = (SG_ELEM_LEN > rWords);
{_rCarry[0], _rAddr[15:0]} = (rRxState[1] ? SG_ELEM_ADDR[15:0] : (rAddr[15:0] + ({12{RX_REQ_ACK}} & {rLen,2'd0})));
{_rCarry[1], _rAddr[31:16]} = (rRxState[1] ? SG_ELEM_ADDR[31:16] : (rAddr[31:16] + rCarry[0]));
{_rCarry[2], _rAddr[47:32]} = (rRxState[1] ? SG_ELEM_ADDR[47:32] : (rAddr[47:32] + rCarry[1]));
_rAddr[63:48] = (rRxState[1] ? SG_ELEM_ADDR[63:48] : (rAddr[63:48] + rCarry[2]));
_rWords = (rRxState[0] ? rReadWords : (rWords - ({10{RX_REQ_ACK}} & rLen)));
_rBufWordsInit = (rLargeBuf ? rWords : SG_ELEM_LEN);
_rBufWords = (rCopyBufWords ? rBufWordsInit : rBufWords) - ({10{RX_REQ_ACK}} & rLen);
_rPageRem = (wAddrLoInv + 1'd1);
_rPageSpillInit = (rBufWordsInit > rPageRem);
_rPageSpill = (rBufWords > rPageRem);
_rPreLen = ((rPageSpillInit & rUseInit) | (rPageSpill & !rUseInit) ? 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);
_rMaxLen = ((rMaxLen & !rValsProp[2]) | RX_REQ_ACK);
_rLen = (rPayloadSpill | rMaxLen ? rMaxPayload : rPreLen[9:0]);
_rLenEQWordsHi = (16'd0 == rWords[31:16]);
_rLenEQWordsLo = ({6'd0, rLen} == rWords[15:0]);
_rLenEQBufWordsHi = (16'd0 == rBufWords[31:16]);
_rLenEQBufWordsLo = ({6'd0, rLen} == rBufWords[15:0]);
case (rRxState)
`S_RXPORTRD_RX_IDLE: begin // Wait for a new read transaction
if (rMainState[2]) // S_RXPORTRD_MAIN_READ
_rRxState = `S_RXPORTRD_RX_BUF;
end
`S_RXPORTRD_RX_BUF: begin // Wait for buffer length and address
if (SG_ELEM_RDY) begin
_rSgRen = 1;
_rRxState = `S_RXPORTRD_RX_ADJ_0;
end
else if (rErr) begin
_rRxState = `S_RXPORTRD_RX_WAIT_0;
end
end
`S_RXPORTRD_RX_ADJ_0: begin // Fix for large buffer
_rSgRen = 0;
_rCopyBufWords = rSgRen;
_rRxState = `S_RXPORTRD_RX_ADJ_1;
end
// (bufwords and pagerem valid here)
`S_RXPORTRD_RX_ADJ_1: begin // Wait for the value to propagate
// Check for page boundary crossing
// Fix for page boundary crossing
// Check for max read payload
// Fix for max read payload
_rCopyBufWords = 0;
_rUseInit = rCopyBufWords;
if (rValsProp[3])
_rRxState = `S_RXPORTRD_RX_ISSUE;
end
`S_RXPORTRD_RX_ISSUE: begin // Wait for the request to be accepted
if (RX_REQ_ACK) begin
if (rErr | (rLenEQWordsHi & rLenEQWordsLo))
_rRxState = `S_RXPORTRD_RX_WAIT_0;
else if (rLenEQBufWordsHi & rLenEQBufWordsLo)
_rRxState = `S_RXPORTRD_RX_BUF;
else
_rRxState = `S_RXPORTRD_RX_ADJ_0;
end
end
`S_RXPORTRD_RX_WAIT_0: begin // Wait for rAckCount to update
_rRxState = `S_RXPORTRD_RX_WAIT_1;
end
`S_RXPORTRD_RX_WAIT_1: begin // Wait for requested data to arrive
if (rAckCountEQ0)
_rRxState = `S_RXPORTRD_RX_DONE;
end
`S_RXPORTRD_RX_DONE: begin // Signal done
if (rMainState[3]) // S_RXPORTRD_MAIN_FLUSH
_rRxState = `S_RXPORTRD_RX_IDLE;
end
default: begin
_rRxState = `S_RXPORTRD_RX_IDLE;
end
endcase
end
// Count the data.
always @ (posedge CLK) begin
rRecvdWords <= #1 _rRecvdWords;
rReqdWords <= #1 _rReqdWords;
rPartWords <= #1 _rPartWords;
rAckCount <= #1 _rAckCount;
rAckCountEQ0 <= #1 _rAckCountEQ0;
rPartWordsRecvd <= #1 _rPartWordsRecvd;
rRequestingWords <= #1 _rRequestingWords;
rAvailWords <= #1 _rAvailWords;
rCarryInv <= #1 _rCarryInv;
rSpaceAvail <= #1 _rSpaceAvail;
rLastDoneRead <= #1 (RST ? 1'd1 : _rLastDoneRead);
end
always @ (*) begin
// Count words as they arrive (words from the rx_engine directly).
if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE
_rRecvdWords = #1 0;
else
_rRecvdWords = #1 rRecvdWords + rRxDataEn;
// Count words as they are requested.
if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE
_rReqdWords = #1 0;
else
_rReqdWords = #1 rReqdWords + ({10{RX_REQ_ACK}} & rLen);
// Track outstanding requests
if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE
_rAckCount = 0;
else
_rAckCount = rAckCount + RX_REQ_ACK - RX_DONE;
_rAckCountEQ0 = (rAckCount == 11'd0);
// Track when the user reads the actual transfer amount.
_rLastDoneRead = (rTxnDone ? 1'd0 : (rLastDoneRead | rTxnDoneAck));
// Track the amount of words that are expected to arrive.
_rPartWords = #1 (rTxnLenValid ? rTxnData : rPartWords);
// Compare counts.
_rPartWordsRecvd = (rRecvdWords >= rPartWords);
_rRequestingWords = rReqdWords + rLen;
{_rCarryInv, _rAvailWords[15:0]} = {1'd1, rRequestingWords[15:0]} - CHNL_RX_CONSUMED[15:0];
_rAvailWords[31:16] = rRequestingWords[31:16] - CHNL_RX_CONSUMED[31:16] - !rCarryInv;
_rSpaceAvail = (rAvailWords <= C_FIFO_WORDS);
end
// Facilitate sending a TXN_DONE when we receive a TXN_ACK after the transaction
// has begun sending. This will happen when the workstation detects that it has
// sent/used all its currently mapped scatter gather elements, but it's not enough
// to complete the transaction. The TXN_DONE will let the workstation know it can
// release the current scatter gather mappings and allocate new ones.
always @ (posedge CLK) begin
rPartialDone <= #1 _rPartialDone;
rReqPartialDone <= #1 (RST ? 1'd0 : _rReqPartialDone);
end
always @ (*) begin
// Signal TXN_DONE after we've recieved the (seemingly superfluous) TXN_ACK
// and received the corresponding amount of words.
_rPartialDone = (rReqPartialDone & rPartWordsRecvd);
// Keep track of (seemingly superfluous) TXN_ACK requests.
if ((rReqPartialDone & rPartWordsRecvd) | rMainState[0]) // S_RXPORTRD_MAIN_IDLE
_rReqPartialDone = 0;
else
_rReqPartialDone = (rReqPartialDone | rTxnLenValid);
end
// Handle errors in the main data or scatter gather data.
always @ (posedge CLK) begin
rErr <= #1 (RST ? 1'd0 : _rErr);
end
always @ (*) begin
// Keep track of errors if we encounter them.
if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE
_rErr = 0;
else
_rErr = (rErr | (RX_DONE & RX_ERR) | (SG_DONE & SG_ERR));
end
/*
wire [35:0] wControl0;
chipscope_icon_1 cs_icon(
.CONTROL0(wControl0)
);
chipscope_ila_t8_512 a0(
.CLK(CLK),
.CONTROL(wControl0),
.TRIG0({TXN_LEN_VALID | TXN_DONE_ACK | TXN_DONE | TXN_ERR, 1'd0, rMainState}),
.DATA({176'd0,
64'd0, // 64
rAddr, // 64
SG_ELEM_RDY, // 1
1'd0, // 1
1'd0, // 1
1'd0, // 1
rSgRen, // 1
1'd0, // 1
rLastDoneRead, // 1
rLen, // 10
rWords, // 32
rAckCount, // 11
rPartWords, // 32
rPartWordsRecvd, // 1
rReqPartialDone, // 1
rPartialDone, // 1
rTxnDone, // 1
rRxState, // 8
rRecvdWords, // 32
rReadWords, // 32
TXN_LEN_VALID, // 1
TXN_DONE_ACK, // 1
rDoneLen, // 32
rMainState}) // 6
);
*/
endmodule