cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Newbie
Newbie
214 Views
Registered: ‎07-21-2020

HLS Interval 1 logic unable to receive/send data from stream on every clock cycle

The HLS logic below has an Interval of 1, however, the HLS and Vivado wave-forms show that it cannot receive and send data on every clock cycle. You can see from the waveform that write, read, and empty lines go low for one clock cycle every two clock cycles where it is high.

The logic is designed to receive Ethernet packets, modify some bytes in the packet, and then send the packet out a 10 gigabit Ethernet mac. The mac we are using requires input data on every clock-cycle, it cannot be starved.

If I remove the state-machine that handles switching the bytes from the "connectTX_0" function, then it still has an interval of 1 but the waveform look correct where the write, read, and empty lines are always high.

Why is the HLS unable receive and send data on every clock cycle? I thought "Interval = 1" indicated that it could receive and send data on every clock cycle.

 

#include "top.hpp"

void connectTXandRX(hls::stream<hostTxData> &hostTX_0, hls::stream<netTxData> &netTX_0,
hls::stream<hostTxData> &hostTX_1, hls::stream<netTxData> &netTX_1,
hls::stream<netRxData> &netRX_0,
hls::stream<hostRxData> &hostRX_1, hls::stream<netRxData> &netRX_1)
{
#pragma HLS INTERFACE ap_fifo port=hostTX_0
#pragma HLS INTERFACE ap_fifo port=netTX_0
#pragma HLS INTERFACE ap_fifo port=hostTX_1
#pragma HLS INTERFACE ap_fifo port=netTX_1
#pragma HLS INTERFACE ap_fifo port=netRX_0
#pragma HLS INTERFACE ap_fifo port=hostRX_1
#pragma HLS INTERFACE ap_fifo port=netRX_1

#pragma HLS DATAFLOW
connectTX_1(hostTX_1, netTX_1);
connectRX_0(netRX_0);
connectRX_1(hostRX_1, netRX_1);
connectTX_0(hostTX_0, netTX_0);
}


void connectTX_0(hls::stream<hostTxData> &hostTX, hls::stream<netTxData> &netTX)
{
#pragma HLS PIPELINE enable_flush

static ap_uint<4> tcpConnectionNumber;
static tcpSessionInfo sessionInfo[16];
static ap_uint<48> macAddress = 0;
static bool storeMAC = false;
static bool switchMAC = false;

#pragma HLS RESET variable=tcpConnectionNumber
#pragma HLS RESET variable=sessionInfo
#pragma HLS ARRAY_PARTITION variable=sessionInfo complete
#pragma HLS RESET variable=macAddress
#pragma HLS RESET variable=storeMAC
#pragma HLS RESET variable=switchMAC

static enum states {START = 0, SWITCH, STORE, STREAM} currentState;

hostTxData readData;
netTxData newData;

switch(currentState){
case START:
if(!hostTX.empty())
{
hostTX.read(readData);
if(readData.sof == 1)
{
newData.len = readData.len;
newData.sof = readData.sof;
newData.eof = readData.eof;
newData.data = readData.data;
newData.error = 0;
if(readData.data.range(63, 48) != 0xFFFF)
{
macAddress.range(47, 32) = readData.data.range(63, 48);
currentState = STORE;
}
else
{
newData.data.range(63, 48) = macAddress.range(47, 32);
currentState = SWITCH;
}
netTX.write(newData);
}
}
break;
case SWITCH:
if(!hostTX.empty())
{
hostTX.read(readData);
newData.len = readData.len;
newData.sof = readData.sof;
newData.eof = readData.eof;
newData.data.range(31, 0) = macAddress.range(31,0);
newData.data.range(63, 32) = readData.data.range(63, 32);
newData.error = 0;
currentState = STREAM;
netTX.write(newData);
}
break;
case STORE:
if(!hostTX.empty())
{
hostTX.read(readData);
newData.data = readData.data;
newData.len = readData.len;
newData.sof = readData.sof;
newData.eof = readData.eof;
newData.error = 0;
macAddress.range(31, 0) = readData.data.range(31,0);
currentState = STREAM;
netTX.write(newData);
}
break;
case STREAM:
if(!hostTX.empty())
{
hostTX.read(readData);
newData.data = readData.data;
newData.len = readData.len;
newData.sof = readData.sof;
newData.eof = readData.eof;
newData.error = 0;
netTX.write(newData);
if(readData.eof == 1)
currentState = START;
else
currentState = STREAM;
}
break;
}


}


void connectTX_1(hls::stream<hostTxData> &hostTX, hls::stream<netTxData> &netTX)
{
#pragma HLS PIPELINE enable_flush
//connect hostTX values to netRX values
if(!hostTX.empty())
{
hostTxData readTxData;
hostTX.read(readTxData);
netTxData writeTxData;
writeTxData.data = readTxData.data;
writeTxData.len = readTxData.len;
writeTxData.sof = readTxData.sof;
writeTxData.eof = readTxData.eof;
writeTxData.error = 0;
netTX.write(writeTxData);
}
}


void connectRX_0(hls::stream<netRxData> &netRX)
{
#pragma HLS PIPELINE enable_flush

if(!netRX.empty())
{
netRxData readRxData;
netRX.read(readRxData);
hostRxData writeRxData;
writeRxData.data = readRxData.data;
writeRxData.len = readRxData.len;
writeRxData.timeStamp = readRxData.timeStamp;
writeRxData.sof = readRxData.sof;
writeRxData.eof = readRxData.eof;
writeRxData.error = readRxData.error;
writeRxData.CRCFail = readRxData.CRCFail;
writeRxData.matchTag = 0;
writeRxData.buffer = 0;
}
}

void connectRX_1(hls::stream<hostRxData> &hostRX, hls::stream<netRxData> &netRX)
{
#pragma HLS PIPELINE enable_flush

if(!netRX.empty())
{
netRxData readRxData;
netRX.read(readRxData);
hostRxData writeRxData;
writeRxData.data = readRxData.data;
writeRxData.len = readRxData.len;
writeRxData.timeStamp = readRxData.timeStamp;
writeRxData.sof = readRxData.sof;
writeRxData.eof = readRxData.eof;
writeRxData.error = readRxData.error;
writeRxData.CRCFail = readRxData.CRCFail;
writeRxData.matchTag = 0;
writeRxData.buffer = 0;
hostRX.write(writeRxData);
}
}

 

HLS_waveform.png
vivado_waveform.png
CosimulationTiming.png
SynthesisTiming.png
0 Kudos
0 Replies