USB Packet Loss

I am using this Opal Kelly board to timestamp event based data and transmitt the timestamps to software, where a statistical analysis is performed. However, i am constantly loosing packets which is having a significant impact on my data recordings. Does the OKI have function calls to enable a more secure transfer of data from FPGA to PC. The events are not particularily fast (~30Hz) so time is not really an issue here.

Tom

Our XEM/FrontPanel products use USB bulk transfers which, by design, are guaranteed to transfer without error.

Depending on how you have written your HDL, however, your design may be overflowing or underflowing buffers and losing data at the FPGA end.

How are you applying the endpoints in your design to transfer data?

Thanks for the swift reply,

I am using a standard Xininx FIFO core (Using the generator V4.2). This is connected directly to the blocktransfer endpoint. The FIFO is large compared to the amount of data that is being sent, and the data is visiable within the fifo as i have hardwired the Read_Data_Count to the LEDs on the board. It doesn’t get near to over flowing. The Read_Data_Count signal is also used to determine if there is enough data to send using the following line of code (VHDL).

NeuralOutReady  64 else '0';

At the other end i am using the C# interface, using the following managed C code.

cli::array^ OutputDataBlock = gcnew cli::array(64);

while(!mbSTOP)
{
int Size = OKI->ReadFromBlockPipeOut(0xA3,64,64,OutputDataBlock);
if(0 < Size)
{
//Do Stuff with extracted timestamps
}
}

This gets the majority of the data, but every so often (it seems randomly) packets are dropped. If i increase the size of the packet then the drop is much more visable as the graphical representation of event rate has massive holes in it, as large sections of times stamped data is lost.

Thanks

Tom

Tom–

I would suggest doing some further investigation to see exactly where the packet loss is occurring. Xilinx’s ChipScope is an excellent tool for this type of thing. The alternative would be to bring out several lines to external test equipment such as a scope or logic analyzer.

If you are experiencing packet loss at the USB level, there is something more significantly wrong – either the host controller on your PC or its drivers are at fault. USB bulk transfers are not susceptible to packet loss.

I have just finished implementing functionality that keeps track of the number of events sent. Essentially i have given each timestamp a count which is also transmitted as the upper 8 bits of each 32-bit timestamp so:

|—8 bit event counter—|---24 bit time stamp----------------------|

when using this i have found that i am consistantly dropping 17 time stamps at random intervals. This makes sence in terms of packet loss, as i am requesting 64bytes at a time which corrisponds to 16 time stamps. Though i am not sure where the last one goes either.

Ok, so that kinda makes sence, i just can’t find the cause, but now things get really weird…To explain, i need to first describe a bit about the rest of the FPGA usage.

The FPGA is split into two sections which are independantly controlled through the endpoints. The first is the recording mechanism which time stamps incomming asynchronous pulses and then sends these timestamps to the PC via a FIFO buffer and your endpoint. The second section is a computational model that produces pulses 1ms wide at semi-random intervals of between 0 > 40 Hz.

To test both parts at the same time, i have connected the output from the second section into the input from the first. And it is in this configuration that i miss data. The data is produced from the second part, as is seen by a logic analyser that i am using. Additionally, because of the new code i have implemented, it is possible to see when data is being lost.

However, if i connect up a signal generator to the input instead of shorting the output to the input by a single wirel, no data is lost. Do you have any ideas why this is?

Tom

Could this be a power issue? I am using pretty much the entire FPGA all the time plus using over half of the FPGA I/Os. Not enough to disrupt the FPGA itself, but enough to mess with the USB controller?

Also, its not 17 timestamps missing… its 16, which is exactly the same size as the requested packet size.

Tom

If the board you’re using is the XEM3001 (this is a post in the XEM3001 forum), then how are you powering the board? By default, the board will be powered by USB which is limited to 500mA. It’s certainly feasible that your FPGA design has violated this limit.

What are your power estimates from the Xilinx tools?

The measured peak current consumption is only 185mA. Which kills that theory…

Yes, i am using XEM3001v2.

Tom

I think that the error must be to do with the way i am configuring the FIFO, such that if some stimulus happens at the wrong time, it looses data. Currently i have a simple comparitor that determines if the amount of data stored is above a certain level. If this is the case then the EP_READY flag is set high. Is this the correct way to implement this?

I have noticed that with this method, only 1 block may be transfered at a time, as the FIFO will set EP_READY low as soon as the first block begins transfer and the FIFO level drops below the defined level.

Should i be impelmenting this differently? I should also point out that i don’t know what the BlockStrobe is for. I have left it dangling in my implementation. Could this be the problem?

Tom

Tom–

The BLOCKSTROBE is not required. It is asserted to your logic as advance notice that data readout is going to happen in a couple cycles. It basically just predicts the assertion of EP_WRITE.

In some implementations, BLOCKSTROBE could be used to reset your EP_READY output. Once you have received BLOCKSTROBE, the host interface has acknowledged your EP_READY.

While it is true that only one block is transferred per BLOCKSTROBE, I’m not sure why you are concerned about this. As the FIFO empties, your EP_READY deasserts to indicate that a full block is no longer available. This is good because otherwise you would encounter an underflow.

If you haven’t used ChipScope before, I encourage you to download the trial version. It really is an incredible time saver. The initial setup may be a bit costly – you have to build the cores and install them in your code. But once you have that done, you have great visibility into your design as it runs.

You could also try setting up simulations with ModelSim, but often for situations like this, getting your simulation to reflect the problem may be difficult – and probably no quicker than diving into ChipScope.

After a long period of debugging i think i have found a solution, and it is nothing to do with the FPGA implementation, but instead a driver/C# issue.

I was using a manged C loop as shown below


cli::array^ OutputDataBlock = gcnew cli::array(64);

while(!mbSTOP)
{
int Size = OKI->ReadFromBlockPipeOut(0xA3,64,64,OutputDataBlock);
if(0 < Size)
{
//Do Stuff with extracted timestamps
}
System::Threading::thread::Sleep(1);
}


Notice the sleep(1) at the bottom. This i put in to make sure that this particular thread didn’t hog the processor. I figured you had also implemented one in your OpelKellyInterface, but i added one anyway just in case, then reduced the timeOut delay to 1000ms using the following function.

OKI->SetTimeout(1000);

This is where the problem is. I found that if i paused the program in debug mode at specific times then no packets would be lost. This proves that the problem is on the host side and not the FPGA unless it was a power issue, which i have already disprooved.

In the end i found that the OpalKellyInterface does not play nice with the .NET Sleep() function, and when i removed all instances of it, the program works fine and no data is lost.

Very Strange.

Tom

Tom,

I don’t quite follow. What was the timeout set to previously? How long does it typically take for your design to produce enough data for a full block?

The timeout was previously set to 1000ms, and the sleep was set to 1ms But it takes approximately 1 second to produce enough data for full block/single packet. This is a very slow process that is designed to mimic neuronal cell firing.

I still don’t know why, but your software interface doesn’t like the Sleep(1) i placed in my code. I am currently putting it on an extended test overnight, so i will see if it has broken when i get back in the morning.

Thanks for your swift responses throughout this debug process, it has been much appreciated.

Tom

Just a follow up post to say that i have not had any more problems since i made the pre-mentioned changes.

Tom

Tom–

I have no idea why the Sleep() would have any effect. All API methods are blocking, so there should be nothing going on before or after the call.

I know we use Sleep() within the API and have used Sleep() in other applications that use the API. Though, not with C#.