Reputation: 222
I'm programming a Xilinx Spartan-6 on an OpalKelly implementation for my master thesis at university. To by precise, this is the FPGA I'm working on (XEM6010-LX45): https://www.opalkelly.com/products/xem6010/
It is mounted on a board that has to acquire multiple signals (8+), process them and generate multiple ones (16+) to close some feedback loops based on the settings.
It is controlled by a User Interface built in C# that I'm also programming myself and that must be able to change the feedback logic used when needed without restarting the experiment. This means that the USB interface continuosly sends data to update the settings.
I've just encountered the classic (I suppose) problem where I've just run out of WireIns, that are the Opal Kelly implementation for the USB transmission of data from the C# program to the FPGA.
They are limited to 16bits data with addresses from 0x00 - 0x1F (so 32 WireIns). More details here page 41 http://assets00.opalkelly.com/library/FrontPanel-UM.pdf
Here is the question: how can I increase the data I can send to the FPGA?
The first idea that comes in mind is a big multiplexer in the FPGA that just uses two WireIns, one for the data, the other as a selector. Then a trigger activates the FPGA, storing the data into the right addressed register.
Is this really viable or it's incredibly inefficient? Should I use the WireORs (see the FrontPanel manual I linked)? Should I use a PipeIn and in some way manage the required multiplexer?
How FPGA designers overcome this USB communication limit?
Thanks in advance!
Upvotes: 0
Views: 245
Reputation: 16802
If you have lots of data that you can stream, use a Pipe.
If you want to access the data randomly, you'll have to use a multiplexer, controlled by a WireIn.
Regarding efficiency, you'll have to specify what dimension of efficiency you are interested in, and what value is acceptable. For example, bandwidth, latency, LUTs used.
--- Update with some code
If you have an array of vectors to update called regs
and 2 wirein signals called address
and data
then you just need to do:
regs(to_integer(unsigned(address))) <= data when rising_edge(clk);
That will be pretty efficient anyway. If you need to be more careful about glitches on the registers, you might want to use a TriggerIn also, so you can set up the address and data and then trigger the transfer.
regs(to_integer(unsigned(address))) <= data when rising_edge(clk) and trigger_signal = '1';
If your synthesiser won't accept the code above, you'll have to log a bug and convert it into a clocked process with an if
statement inside the clocked part.
Upvotes: 1
Reputation: 3751
The good response would be to use the okRegisterBridge, but as I can see on your board description, it's only available on USB 3.0 :(
Then yes, in your case if you want to increase your address space you have to do a multiplexer with one okWireIn register for address and one for writedata.
Upvotes: 1