Electronic – Bus arbiter that can handle multiple concurrent requests vhdl

fpgavhdl

I am working through a weird problem. We are pin constrained on our FPGA and need to control a common bus. This was all fine and good as all the software was sequential, but now some requests will be coming in at the same time for devices, but will now have to be put into a queue.

How should I take care of making sure that everything gets shoved into a FIFO without priority and without dropping data? I've got the outer design complete for controlling everything up until the bottle-neck where everything gets shoved into the pipe before being granted access to our "bus". Some requests will take a long time to come in, but will do so concurrently from an FPGA whereas software commands will come in sequentially, but less predictably. If I don't care about the order in which I grant access to the "bus", what is the best way to pipe all of this information into a single FIFO under the assumption that some commands will be coming in at the same time without knowing how many there will be? I would like to avoid having to request/ack/grant if possible as I would like all of this to be taken care of by a single component that just receives a bunch of data and takes care of the complexity. What is the easiest way to accomplish this?

Best Answer

If you only have one 'sink,' then you have to arbitrate. You'll have to apply backpressure to any source that has yet to receive a grant. If you can't apply backpressure to whatever is generating the requests directly, then the only option is to put in a 'large enough' FIFO on each source and apply backpressure to those FIFOs. The trick is figuring out how big those FIFOs need to be to eliminate drops - maybe some sources can accept backpressure, maybe some send more often and therefore require deeper FIFOs, etc. You can usually make FIFOs of depth 16-128 or so using distributed RAM with 1 LUT per bit.

AXI stream is super simple, it's just a ready and a valid signal that go along with the data. Valid is high when the data is valid, ready indicates that the sink is ready to receive the data, and data is transferred when both valid and ready are high. When you connect a FIFO with a 'traditional' FIFO interface, you can map input_ready, input_valid, output_ready, and output_valid onto read, write, full and empty like so:

read = output_ready && output_valid
write = input_ready && input_valid
input_ready = !full
output_valid = !empty