2
\$\begingroup\$

I am working on a FPGA project where a host CPU writes a 10,240 x 16-bit look up table into FPGA logic. To implement this, I've utilized on-chip memory to store the values and read them out when ready.

An external trigger/go pulse kicks off a processing cycle which lasts several hundred thousand clock cycles. Once we get this trigger, the state of the 10,240x16 LUT needs to be frozen or latched, so it can be utilized during the processing cycle. Unfortunately, the data needs to be available fairly soon after this "GO" pulse, so there is not enough time to do a complete buffer copy.

The host also needs to be able to continually update some values of the look up table while the current cycle is being executed, in order to setup for the next processing cycle. To allow for both cases (latching the state of the lookup table, but also letting the host update it whenever), I think that double-buffering ping/pong style is the way to go: The host writes to one buffer until we get to "GO" command, then the host writes to the other. The FPGA logic always reads out of the buffer not being written to.

However, since the host is not rewriting all 10,240x16 values when it does its sporadic updates, the buffer that is not being written to is essentially "dropping" the updates while it's frozen.

Is there a novel way to handle this scenario? I'm thinking there needs to be some kind of buffer resynchronization process once the buffer is unfrozen.

\$\endgroup\$
  • \$\begingroup\$ Are there power reasons as to why you cannot have a dedicated "configure" buffer which is latched in to the "processing" buffer on the GO pulse? \$\endgroup\$ – DonFusili Jul 3 '18 at 7:10
2
\$\begingroup\$

One possible strategy could be to use stale bits. Dunno if that's standard terminology, but it's similar to a dirty bit. Writing a new entry will clear the corresponding stale bit in the unlocked buffer and set the bit in the locked buffer. After switching buffers, have an internal copy routine transfer every entry marked stale in the unlocked buffer from the locked buffer to the unlocked buffer. In this way, new data written while the copy is in progress will not be overwritten, and all the old updates should be retained. The only thing you need to do is ensure that there is enough time for the copy operation to complete between buffer switches, or you need some sort of optimization to keep track of which entries are stale so you don't have to iterate over all of them, making the copy operation faster.

Another possible strategy could be to store the updated entries while a single buffer is locked, then apply only those updates when it is unlocked. If only a handful of entries are updated, then this might be more efficient. The updates could be stored as a linked list or similar data structure so that the list can be traversed efficiently while multiple updates to the same location can be coalesced.

\$\endgroup\$
1
\$\begingroup\$

Unless there are power reasons not to do this, I would go for this:

  • Have two buffers of 10240*16 bits
  • Fill in one of them using the CPU, call this the "configure" buffer
  • On the Go Pulse, copy the "configure" buffer into the "processing" buffer, there's no reason this cannot be done in one clock cycle (except for aforementioned possible power issues). If you can send your GO pulse one cycle before the processing of the data actually starts, you can even avoid extra muxing where the configure buffer is used for the first cycle of the data processing. This would also allow back to back updating and processing (Would probably require some work in the kernel space of the CPU, though).
\$\endgroup\$
  • \$\begingroup\$ That would only work if the buffers were in distributed ram where you could have fully parallel transfers to make it work in one clock, possible, but it is a LOT of area and will likely choke on routing. \$\endgroup\$ – Dan Mills Jul 3 '18 at 15:58
  • \$\begingroup\$ @DanMills Sure, but assuming distributed RAM, this is less area than having two full fledged buffers where every bit has to be muxed. \$\endgroup\$ – DonFusili Jul 4 '18 at 7:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.