I'm trying to design a "double-buffer" structure similar to that used in UARTs (for receiving). In my case, it is for samples from an ADC. I shift them in, and at some point my logic detects a condition that tells me that I want to "save" the block I currently have; thus, a second buffer of type PISO works (serial-out is fine, since the microprocessor can always read the samples from the FPGA sequentially).

A pure HDL solution (using PFUs/LUTs) does not work, because the buffer is too large (I get the "Design does not fit in device selected" error at the mapping stage. Even with the XO2-7000, my required size is slightly larger).

EDIT: I will need 512 elements × 16-bits per element (times two, if we're talking double-buffer). Notice that the ADC has parallel output; the analogy with the UART is not at the bit-level (in the analogy, each bit in a serial transmission would be like each sampled value of the ADC)

IPExpress only offers FIFO (including dual-clock) and RAMs (including dual-port). But ideally, I would need to copy in parallel to the second buffer.

Any suggestions, or pointers to any additional IPs that could do the trick? (doesn't have to be free). The IPs I see through Lattice's website don't seem to match .

  • 2
    \$\begingroup\$ You do not tell us how big your 'double buffer' is. A double buffer in a UART requires 8 bits. For an ADC (lets say 16 bits) that would be 16 bits The XO2-7000 has >6800 LUTS. I suspect your idea of a 'double buffer' might be slightly out of kilter. \$\endgroup\$ – Oldfart Sep 13 '19 at 15:24
  • 1
    \$\begingroup\$ How big a buffer do you need? The XO2-7000 has almost 240 kbits of RAM in 26 blocks, which would allow you to double-buffer about 13 kB of data with no problem. \$\endgroup\$ – Dave Tweed Sep 13 '19 at 15:28
  • \$\begingroup\$ @Oldfart -- I'll adjust my post to clarify this. \$\endgroup\$ – Cal-linux Sep 13 '19 at 15:28
  • \$\begingroup\$ @DaveTweed -- yes, with RAM. My comment was that a pure HDL solution does not work, because we have no more than 7 thousand LUTs. And with RAM, the issue is that I'm not finding a PISO structure available as an IP (free or otherwise) \$\endgroup\$ – Cal-linux Sep 13 '19 at 15:40
  • \$\begingroup\$ It can be done using block rams (as Dave Tweed shows below) but I strongly suspect you have an XY problem. Especially as you say "your microprocessor can always read the samples from the FPGA sequentially". \$\endgroup\$ – Oldfart Sep 13 '19 at 15:49

Double-buffering shouldn't require a parallel copy. The normal technique is to have two blocks of RAM, and when you get your "trigger" or whatever criteria you have to switch buffers, you simply switch which block you're writing to.


simulate this circuit – Schematic created using CircuitLab

The switches represent multiplexers. In the current state, U1 is being written and U2 is being read. When your trigger occurs, flip all of the switches, and now you're writing to U2 and reading from U1.

If you're going to do this with FIFOs, the technique is similar, but there's a subtlety. Your problem description says that you essentially want to save the last 512 samples that were taken before the trigger, which implies that you will be throwing away data if the triggers are more than 512 samples apart. With FIFOs, you need to explicitly account for this, by removing data once they fill up. This is shown below with the addition of the AND gates.


simulate this circuit

  • \$\begingroup\$ Ok, this is similar to the plan I had in mind for now. But instead of RAMs, just two FIFO_DCs (I do have independent read and write clocks), and switch between them as you point out (the advantage with FIFOs is I don't need to handle myself the extra logic to generate addresses — since all of my accesses will be naturally sequential, FIFO structures should do) \$\endgroup\$ – Cal-linux Sep 13 '19 at 15:45
  • \$\begingroup\$ Even the XO2-640 device should be big enough to do this -- it has two EBR SRAM blocks, each of which can be configured as a 512x18 FIFO. \$\endgroup\$ – Dave Tweed Sep 13 '19 at 15:48
  • \$\begingroup\$ Awesome, Dave Tweed, thanks! I was precisely unsure about this detail of having to extract when the FIFO buffer fills (I suspected that that was the case, but the documentation does not explicitly say that — I guess they assume it is part of the "standard definition" of a FIFO?) \$\endgroup\$ – Cal-linux Sep 14 '19 at 12:17

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.