Created
September 7, 2018 06:47
-
-
Save buttercutter/c786802f336f648ce573b90c141936e3 to your computer and use it in GitHub Desktop.
Modified full duplex tx_port_writer.v
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ---------------------------------------------------------------------- | |
// Copyright (c) 2016, 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_port_writer.v | |
// Version: 1.00.a | |
// Verilog Standard: Verilog-2001 | |
// Description: Handles receiving new transaction events and data, and | |
// making requests to tx engine. | |
// for the RIFFA channel. | |
// Author: Matt Jacobsen | |
// History: @mattj: Version 2.0 | |
//----------------------------------------------------------------------------- | |
`define S_TXPORTWR_MAIN_IDLE 8'b0000_0001 | |
`define S_TXPORTWR_MAIN_CHECK 8'b0000_0010 | |
`define S_TXPORTWR_MAIN_SIG_NEW 8'b0000_0100 | |
`define S_TXPORTWR_MAIN_NEW_ACK 8'b0000_1000 | |
`define S_TXPORTWR_MAIN_WRITE 8'b0001_0000 | |
`define S_TXPORTWR_MAIN_DONE 8'b0010_0000 | |
`define S_TXPORTWR_MAIN_SIG_DONE 8'b0100_0000 | |
`define S_TXPORTWR_MAIN_RESET 8'b1000_0000 | |
`define S_TXPORTWR_TX_IDLE 8'b0000_0001 | |
`define S_TXPORTWR_TX_BUF 8'b0000_0010 | |
`define S_TXPORTWR_TX_ADJ_0 8'b0000_0100 | |
`define S_TXPORTWR_TX_ADJ_1 8'b0000_1000 | |
`define S_TXPORTWR_TX_ADJ_2 8'b0001_0000 | |
`define S_TXPORTWR_TX_CHECK_DATA 8'b0010_0000 | |
`define S_TXPORTWR_TX_WRITE 8'b0100_0000 | |
`define S_TXPORTWR_TX_WRITE_REM 8'b1000_0000 | |
`timescale 1ns/1ns | |
module tx_port_writer ( | |
input CLK, | |
input RST, | |
input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B | |
output TXN, // Write transaction notification | |
input TXN_ACK, // Write transaction acknowledged | |
output [31:0] TXN_LEN, // Write transaction length | |
output [31:0] TXN_OFF_LAST, // Write transaction offset/last | |
output [31:0] TXN_DONE_LEN, // Write transaction actual transfer length | |
output TXN_DONE, // Write transaction done | |
output TXN_ERR, // Write transaction encountered an error | |
input TXN_DONE_ACK, // Write transaction actual transfer length read | |
output TXN_STARTING, // Write transaction is just about to start | |
input NEW_TXN, // Transaction parameters are valid | |
output NEW_TXN_ACK, // Transaction parameter read, continue | |
input NEW_TXN_LAST, // Channel last write | |
input [31:0] NEW_TXN_LEN, // Channel write length (in 32 bit words) | |
input [30:0] NEW_TXN_OFF, // Channel write offset | |
input [31:0] NEW_TXN_WORDS_RECVD, // Count of data words received in transaction | |
input NEW_TXN_DONE, // Transaction is closed | |
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 | |
input SG_ELEM_EMPTY, // Scatter gather elements empty | |
output SG_ELEM_REN, // Scatter gather element read enable | |
output SG_RST, // Scatter gather data reset | |
input SG_ERR, // Scatter gather read encountered an error | |
output TX_REQ, // Outgoing write request | |
input TX_REQ_ACK, // Outgoing write request acknowledged | |
output [63:0] TX_ADDR, // Outgoing write high address | |
output [9:0] TX_LEN, // Outgoing write length (in 32 bit words) | |
output TX_LAST, // Outgoing write is last request for transaction | |
input TX_SENT // Outgoing write complete | |
); | |
`include "functions.vh" | |
(* syn_encoding = "user" *) | |
(* fsm_encoding = "user" *) | |
reg [7:0] rMainState=`S_TXPORTWR_MAIN_IDLE, _rMainState=`S_TXPORTWR_MAIN_IDLE; | |
reg [31:0] rOffLast=0, _rOffLast=0; | |
reg rWordsEQ0=0, _rWordsEQ0=0; | |
reg rStarted=0, _rStarted=0; | |
reg [31:0] rDoneLen=0, _rDoneLen=0; | |
reg rSgErr=0, _rSgErr=0; | |
reg rTxErrd=0, _rTxErrd=0; | |
reg rTxnAck=0, _rTxnAck=0; | |
(* syn_encoding = "user" *) | |
(* fsm_encoding = "user" *) | |
reg [7:0] rTxState=`S_TXPORTWR_TX_IDLE, _rTxState=`S_TXPORTWR_TX_IDLE; | |
reg [31:0] rSentWords=0, _rSentWords=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 [2:0] rCarry=0, _rCarry=0; | |
reg rValsPropagated=0, _rValsPropagated=0; | |
reg [5:0] rValsProp=0, _rValsProp=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] rMaxPayloadSize=0, _rMaxPayloadSize=0; | |
reg [2:0] rMaxPayloadShift=0, _rMaxPayloadShift=0; | |
reg [9:0] rMaxPayload=0, _rMaxPayload=0; | |
reg rPayloadSpill=0, _rPayloadSpill=0; | |
reg rMaxLen=1, _rMaxLen=1; | |
reg [9:0] rLen=0, _rLen=0; | |
reg [31:0] rSendingWords=0, _rSendingWords=0; | |
reg rAvail=0, _rAvail=0; | |
reg [1:0] rTxnDone=0, _rTxnDone=0; | |
reg [9:0] rLastLen=0, _rLastLen=0; | |
reg rLastLenEQ0=0, _rLastLenEQ0=0; | |
reg rLenEQWords=0, _rLenEQWords=0; | |
reg rLenEQBufWords=0, _rLenEQBufWords=0; | |
reg rNotRequesting=1, _rNotRequesting=1; | |
reg [63:0] rReqAddr=64'd0, _rReqAddr=64'd0; | |
reg [9:0] rReqLen=0, _rReqLen=0; | |
reg rReqLast=0, _rReqLast=0; | |
reg rTxReqAck=0, _rTxReqAck=0; | |
reg rDone=0, _rDone=0; | |
reg [9:0] rAckCount=0, _rAckCount=0; | |
reg rTxSent=0, _rTxSent=0; | |
reg rLastDoneRead=1, _rLastDoneRead=1; | |
reg rTxnDoneAck=0, _rTxnDoneAck=0; | |
reg rReqPartialDone=0, _rReqPartialDone=0; | |
reg rPartialDone=0, _rPartialDone=0; | |
assign NEW_TXN_ACK = rMainState[1]; // S_TXPORTWR_MAIN_CHECK | |
assign TXN = rMainState[2]; // S_TXPORTWR_MAIN_SIG_NEW | |
assign TXN_STARTING = (rMainState == `S_TXPORTWR_MAIN_WRITE); | |
assign TXN_DONE = (rMainState[6] | rPartialDone); // S_TXPORTWR_MAIN_SIG_DONE | |
assign TXN_LEN = rWords; | |
assign TXN_OFF_LAST = rOffLast; | |
assign TXN_DONE_LEN = rDoneLen; | |
assign TXN_ERR = rTxErrd; | |
assign SG_ELEM_REN = rTxState[2]; // S_TXPORTWR_TX_ADJ_0 | |
assign SG_RST = rMainState[3]; // S_TXPORTWR_MAIN_NEW_ACK | |
assign TX_REQ = !rNotRequesting; | |
assign TX_ADDR = rReqAddr; | |
assign TX_LEN = rReqLen; | |
assign TX_LAST = rReqLast; | |
// Buffer the input signals that come from outside the tx_port. | |
always @ (posedge CLK) begin | |
if(RST || ((rMainState >= `S_TXPORTWR_MAIN_NEW_ACK) && rTxnAck)) rTxnAck <= #1 1'd0; // second condition avoids assertion of signal 'rPartialDone' | |
// there is code modification on linux driver for full duplex, | |
// Tx software thread is set up first due to loopback timing requirement and kernel code execution speed is way slower compared to FPGA code execution speed, | |
// so extend this ack signal until tx state machine (rMainState) is ready for the actual write, | |
// refer to https://github.com/KastnerRG/riffa/blob/master/driver/linux/riffa_driver.c#L317 | |
else if((rMainState < `S_TXPORTWR_MAIN_NEW_ACK) && _rTxnAck) rTxnAck <= #1 1'd1; // 'rTxnAck' is only a single pulse during `S_TXPORTWR_MAIN_NEW_ACK | |
//rTxnAck <= #1 (RST ? 1'd0 : _rTxnAck); | |
rTxnDoneAck <= #1 (RST ? 1'd0 : _rTxnDoneAck); | |
rSgErr <= #1 (RST ? 1'd0 : _rSgErr); | |
rTxReqAck <= #1 (RST ? 1'd0 : _rTxReqAck); | |
rTxSent <= #1 (RST ? 1'd0 : _rTxSent); | |
end | |
always @ (*) begin | |
_rTxnAck = TXN_ACK; | |
_rTxnDoneAck = TXN_DONE_ACK; | |
_rSgErr = SG_ERR; | |
_rTxReqAck = TX_REQ_ACK; | |
_rTxSent = TX_SENT; | |
end | |
// Wait for a NEW_TXN request. Then request transfers until all the data is sent | |
// or until the specified length is reached. Then signal TXN_DONE. | |
always @ (posedge CLK) begin | |
rMainState <= #1 (RST ? `S_TXPORTWR_MAIN_IDLE : _rMainState); | |
rOffLast <= #1 _rOffLast; | |
rWordsEQ0 <= #1 _rWordsEQ0; | |
rStarted <= #1 _rStarted; | |
rDoneLen <= #1 (RST ? 0 : _rDoneLen); | |
rTxErrd <= #1 (RST ? 1'd0 : _rTxErrd); | |
end | |
always @ (*) begin | |
_rMainState = rMainState; | |
_rOffLast = rOffLast; | |
_rWordsEQ0 = rWordsEQ0; | |
_rStarted = rStarted; | |
_rDoneLen = rDoneLen; | |
_rTxErrd = rTxErrd; | |
case (rMainState) | |
`S_TXPORTWR_MAIN_IDLE: begin // Wait for channel write request | |
_rStarted = 0; | |
_rWordsEQ0 = (NEW_TXN_LEN == 0); | |
_rOffLast = {NEW_TXN_OFF, NEW_TXN_LAST}; | |
if (NEW_TXN) | |
_rMainState = `S_TXPORTWR_MAIN_CHECK; | |
end | |
`S_TXPORTWR_MAIN_CHECK: begin // Continue with transaction? | |
if (rOffLast[0] | !rWordsEQ0) | |
_rMainState = `S_TXPORTWR_MAIN_SIG_NEW; | |
else | |
_rMainState = `S_TXPORTWR_MAIN_RESET; | |
end | |
`S_TXPORTWR_MAIN_SIG_NEW: begin // Signal new write | |
_rMainState = `S_TXPORTWR_MAIN_NEW_ACK; | |
end | |
`S_TXPORTWR_MAIN_NEW_ACK: begin // Wait for acknowledgement | |
if (rTxnAck) // ACK'd on PC read of TXN length | |
_rMainState = (rWordsEQ0 ? `S_TXPORTWR_MAIN_SIG_DONE : `S_TXPORTWR_MAIN_WRITE); | |
end | |
`S_TXPORTWR_MAIN_WRITE: begin // Start writing and wait for all writes to complete | |
_rStarted = (rStarted | rTxState[1]); // S_TXPORTWR_TX_BUF | |
_rTxErrd = (rTxErrd | rSgErr); | |
if (rTxState[0] & rStarted) // S_TXPORTWR_TX_IDLE | |
_rMainState = `S_TXPORTWR_MAIN_DONE; | |
end | |
`S_TXPORTWR_MAIN_DONE: begin // Wait for the last transaction to complete | |
if (rDone & rLastDoneRead) begin | |
_rDoneLen = rSentWords; | |
_rMainState = `S_TXPORTWR_MAIN_SIG_DONE; | |
end | |
end | |
`S_TXPORTWR_MAIN_SIG_DONE: begin // Signal the done port | |
_rTxErrd = 0; | |
_rMainState = `S_TXPORTWR_MAIN_RESET; | |
end | |
`S_TXPORTWR_MAIN_RESET: begin // Wait for the channel tx to drop | |
if (NEW_TXN_DONE) | |
_rMainState = `S_TXPORTWR_MAIN_IDLE; | |
end | |
default: begin | |
_rMainState = `S_TXPORTWR_MAIN_IDLE; | |
end | |
endcase | |
end | |
// Manage sending TX requests to the TX engine. Transfers will be limited | |
// by each scatter gather buffer's size, max payload size, and must not | |
// cross a (4KB) page boundary. The request is only made if there is sufficient | |
// data already written to the buffer. | |
wire [9:0] wLastLen = (NEW_TXN_WORDS_RECVD - rSentWords); | |
wire [9:0] wAddrLoInv = ~rAddr[11:2]; | |
wire [10:0] wPageRem = (wAddrLoInv + 1'd1); | |
always @ (posedge CLK) begin | |
rTxState <= #1 (RST | rSgErr ? `S_TXPORTWR_TX_IDLE : _rTxState); | |
rSentWords <= #1 (rMainState[0] ? 0 : _rSentWords); | |
rWords <= #1 _rWords; | |
rBufWords <= #1 _rBufWords; | |
rBufWordsInit <= #1 _rBufWordsInit; | |
rAddr <= #1 _rAddr; | |
rCarry <= #1 _rCarry; | |
rValsPropagated <= #1 _rValsPropagated; | |
rValsProp <= #1 _rValsProp; | |
rLargeBuf <= #1 _rLargeBuf; | |
rPageRem <= #1 _rPageRem; | |
rPageSpill <= #1 _rPageSpill; | |
rPageSpillInit <= #1 _rPageSpillInit; | |
rCopyBufWords <= #1 _rCopyBufWords; | |
rUseInit <= #1 _rUseInit; | |
rPreLen <= #1 _rPreLen; | |
rMaxPayloadSize <= #1 _rMaxPayloadSize; | |
rMaxPayloadShift <= #1 _rMaxPayloadShift; | |
rMaxPayload <= #1 _rMaxPayload; | |
rPayloadSpill <= #1 _rPayloadSpill; | |
rMaxLen <= #1 (RST ? 1'd1 : _rMaxLen); | |
rLen <= #1 _rLen; | |
rSendingWords <= #1 _rSendingWords; | |
rAvail <= #1 _rAvail; | |
rTxnDone <= #1 _rTxnDone; | |
rLastLen <= #1 _rLastLen; | |
rLastLenEQ0 <= #1 _rLastLenEQ0; | |
rLenEQWords <= #1 _rLenEQWords; | |
rLenEQBufWords <= #1 _rLenEQBufWords; | |
end | |
always @ (*) begin | |
_rTxState = rTxState; | |
_rCopyBufWords = rCopyBufWords; | |
_rUseInit = rUseInit; | |
_rValsProp = ((rValsProp<<1) | rTxState[3]); // S_TXPORTWR_TX_ADJ_1 | |
_rValsPropagated = (rValsProp == 6'd0); | |
_rLargeBuf = (SG_ELEM_LEN > rWords); | |
{_rCarry[0], _rAddr[15:0]} = (rTxState[1] ? SG_ELEM_ADDR[15:0] : (rAddr[15:0] + ({12{rTxState[6]}} & {rLen, 2'd0}))); // S_TXPORTWR_TX_WRITE | |
{_rCarry[1], _rAddr[31:16]} = (rTxState[1] ? SG_ELEM_ADDR[31:16] : (rAddr[31:16] + rCarry[0])); | |
{_rCarry[2], _rAddr[47:32]} = (rTxState[1] ? SG_ELEM_ADDR[47:32] : (rAddr[47:32] + rCarry[1])); | |
_rAddr[63:48] = (rTxState[1] ? SG_ELEM_ADDR[63:48] : (rAddr[63:48] + rCarry[2])); | |
_rSentWords = (rTxState[7] ? NEW_TXN_WORDS_RECVD : rSentWords) + ({10{rTxState[6]}} & rLen); // S_TXPORTWR_TX_WRITE | |
_rWords = (NEW_TXN_ACK ? NEW_TXN_LEN : (rWords - ({10{rTxState[6]}} & rLen))); // S_TXPORTWR_TX_WRITE | |
_rBufWordsInit = (rLargeBuf ? rWords : SG_ELEM_LEN); | |
_rBufWords = (rCopyBufWords ? rBufWordsInit : rBufWords) - ({10{rTxState[6]}} & rLen); // S_TXPORTWR_TX_WRITE | |
_rPageRem = wPageRem; | |
_rPageSpillInit = (rBufWordsInit > wPageRem); | |
_rPageSpill = (rBufWords > wPageRem); | |
_rPreLen = ((rPageSpillInit & rUseInit) | (rPageSpill & !rUseInit) ? rPageRem : rBufWords[10:0]); | |
_rMaxPayloadSize = CONFIG_MAX_PAYLOAD_SIZE; | |
_rMaxPayloadShift = (rMaxPayloadSize > 3'd4 ? 3'd4 : rMaxPayloadSize); | |
_rMaxPayload = (6'd32<<rMaxPayloadShift); | |
_rPayloadSpill = (rPreLen > rMaxPayload); | |
_rMaxLen = ((rMaxLen & !rValsProp[1]) | rTxState[6]); // S_TXPORTWR_TX_WRITE | |
_rLen = (rPayloadSpill | rMaxLen ? rMaxPayload : rPreLen[9:0]); | |
_rSendingWords = rSentWords + rLen; | |
_rAvail = (NEW_TXN_WORDS_RECVD >= rSendingWords); | |
_rTxnDone = ((rTxnDone<<1) | NEW_TXN_DONE); | |
_rLastLen = wLastLen; | |
_rLastLenEQ0 = (rLastLen == 10'd0); | |
_rLenEQWords = (rLen == rWords); | |
_rLenEQBufWords = (rLen == rBufWords); | |
case (rTxState) | |
`S_TXPORTWR_TX_IDLE: begin // Wait for channel write request | |
if (rMainState[4] & !rStarted) // S_TXPORTWR_MAIN_WRITE | |
_rTxState = `S_TXPORTWR_TX_BUF; | |
end | |
`S_TXPORTWR_TX_BUF: begin // Wait for buffer length and address | |
if (SG_ELEM_RDY) | |
_rTxState = `S_TXPORTWR_TX_ADJ_0; | |
end | |
`S_TXPORTWR_TX_ADJ_0: begin // Fix for large buffer | |
_rCopyBufWords = 1; | |
_rTxState = `S_TXPORTWR_TX_ADJ_1; | |
end | |
`S_TXPORTWR_TX_ADJ_1: begin // Check for page boundary crossing | |
_rCopyBufWords = 0; | |
_rUseInit = rCopyBufWords; | |
_rTxState = `S_TXPORTWR_TX_ADJ_2; | |
end | |
`S_TXPORTWR_TX_ADJ_2: begin // Wait for values to propagate | |
// Fix for page boundary crossing | |
// Check for max payload | |
// Fix for max payload | |
_rUseInit = 0; | |
if (rValsProp[2]) | |
_rTxState = `S_TXPORTWR_TX_CHECK_DATA; | |
end | |
`S_TXPORTWR_TX_CHECK_DATA: begin // Wait for available data | |
if (rNotRequesting) begin | |
if (rAvail) | |
_rTxState = `S_TXPORTWR_TX_WRITE; | |
else if (rValsPropagated & rTxnDone[1]) | |
_rTxState = (rLastLenEQ0 ? `S_TXPORTWR_TX_IDLE : `S_TXPORTWR_TX_WRITE_REM); | |
end | |
end | |
`S_TXPORTWR_TX_WRITE: begin // Send len and repeat or finish? | |
if (rLenEQWords) | |
_rTxState = `S_TXPORTWR_TX_IDLE; | |
else if (rLenEQBufWords) | |
_rTxState = `S_TXPORTWR_TX_BUF; | |
else | |
_rTxState = `S_TXPORTWR_TX_ADJ_1; | |
end | |
`S_TXPORTWR_TX_WRITE_REM: begin // Send remaining data and finish | |
_rTxState = `S_TXPORTWR_TX_IDLE; | |
end | |
default: begin | |
_rTxState = `S_TXPORTWR_TX_IDLE; | |
end | |
endcase | |
end | |
// Request TX transfers separately so that the TX FSM can continue calculating | |
// the next set of request parameters without having to wait for the TX_REQ_ACK. | |
always @ (posedge CLK) begin | |
rAckCount <= #1 (RST ? 10'd0 : _rAckCount); | |
rNotRequesting <= #1 (RST ? 1'd1 : _rNotRequesting); | |
rReqAddr <= #1 _rReqAddr; | |
rReqLen <= #1 _rReqLen; | |
rReqLast <= #1 _rReqLast; | |
rDone <= #1 _rDone; | |
rLastDoneRead <= #1 (RST ? 1'd1 : _rLastDoneRead); | |
end | |
always @ (*) begin | |
// Start signaling when the TX FSM is ready. | |
if (rTxState[6] | rTxState[7]) // S_TXPORTWR_TX_WRITE | |
_rNotRequesting = 0; | |
else | |
_rNotRequesting = (rNotRequesting | rTxReqAck); | |
// Pass off the rAddr & rLen when ready and wait for TX_REQ_ACK. | |
if (rTxState[6]) begin // S_TXPORTWR_TX_WRITE | |
_rReqAddr = rAddr; | |
_rReqLen = rLen; | |
_rReqLast = rLenEQWords; | |
end | |
else if (rTxState[7]) begin // S_TXPORTWR_TX_WRITE_REM | |
_rReqAddr = rAddr; | |
_rReqLen = rLastLen; | |
_rReqLast = 1; | |
end | |
else begin | |
_rReqAddr = rReqAddr; | |
_rReqLen = rReqLen; | |
_rReqLast = rReqLast; | |
end | |
// Track TX_REQ_ACK and TX_SENT to determine when the transaction is over. | |
_rDone = (rAckCount == 10'd0); | |
if (rMainState[0]) // S_TXPORTWR_MAIN_IDLE | |
_rAckCount = 0; | |
else | |
_rAckCount = rAckCount + rTxState[6] + rTxState[7] - rTxSent; // S_TXPORTWR_TX_WRITE, S_TXPORTWR_TX_WRITE_REM | |
// Track when the user reads the actual transfer amount. | |
_rLastDoneRead = (rMainState[6] ? 1'd0 : (rLastDoneRead | rTxnDoneAck)); // S_TXPORTWR_MAIN_SIG_DONE | |
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, | |
// we have no outstanding transfer requests, we're not currently requesting a | |
// transfer, and there are no more scatter gather elements. | |
_rPartialDone = (rReqPartialDone & rDone & rNotRequesting & SG_ELEM_EMPTY & rTxState[1]); // S_TXPORTWR_TX_BUF | |
// Keep track of (seemingly superfluous) TXN_ACK requests. | |
if ((rReqPartialDone & rDone & rNotRequesting & SG_ELEM_EMPTY & rTxState[1]) | rMainState[0]) // S_TXPORTWR_MAIN_IDLE | |
_rReqPartialDone = 0; | |
else | |
//_rReqPartialDone = (rReqPartialDone | (rTxnAck & !rMainState[3])); // !S_TXPORTWR_MAIN_NEW_ACK | |
// Added by cheng fei: | |
// Second condition implies: linux driver issues read_reg(sc, CHNL_REG(chnl, TX_LEN_REG_OFF) during the current Tx actual write transaction | |
_rReqPartialDone = (rReqPartialDone | (TXN_ACK && (rMainState > `S_TXPORTWR_MAIN_NEW_ACK))); | |
end | |
/* | |
wire [35:0] wControl0; | |
chipscope_icon_1 cs_icon( | |
.CONTROL0(wControl0) | |
); | |
chipscope_ila_t8_512 a0( | |
.CLK(CLK), | |
.CONTROL(wControl0), | |
.TRIG0({rTxState[6] | rTxState[7] | rTxSent, rAckCount[6:0]}), | |
.DATA({280'd0, | |
NEW_TXN_WORDS_RECVD, // 32 | |
rSendingWords, // 32 | |
rAvail, // 1 | |
rNotRequesting, // 1 | |
NEW_TXN_LAST, // 1 | |
NEW_TXN_LEN, // 32 | |
NEW_TXN_OFF, // 31 | |
NEW_TXN, // 1 | |
rAckCount, // 10 | |
rLastDoneRead, // 1 | |
rWords, // 32 | |
rBufWords, // 32 | |
rLen, // 10 | |
rTxState, // 8 | |
rMainState}) // 8 | |
); | |
*/ | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment