High Speed ADC Pre/Post Trigger Window Concepts - Page 1
Forum section: electronics / general

author: nickolas
author_rank: Newbie
timestamp: October 23, 2018, 11:42:25 pm
content: Hello All,New user here. This isn't really a question about the Lattice MachXO2 (targeted FPGA) or VHDL programming (targeted language), but about technical details regarding traditional designs sampling high speed ADCs.I want to sample data from an ADC at 100 MSPS, and store the data immediately in a circular buffer (traditionally done). I also send this data into a trigger block which checks if the sampled value is below a value stored in a user configurable register or a trigger comes in on an input pin. Upon triggering, I will load a down counter with the size of the window of data stored in a user configurable register to begin transferring data from an initial FIFO to a secondary FIFO (down counter counts to 0, when not 0, use it as an enable to read from first FIFO and write into second FIFO). When this down counter reaches 0, it will wait until the next trigger to count down. The secondary FIFO will then be read into a read-out register 1 at a time until all desired data is transferred.I am struggling with how to define a pre-trigger window so that the desired size encompasses the right data in terms of pre-trigger and post-trigger. I have designed my VHDL modules to be modular, and wanted to reuse the FIFO concept for the input buffer and the output buffer, but was thinking to force the first FIFO buffers read pointer to follow the write pointer when it is a pre-trigger distance away (Pre-trigger distance would be read from a user-configurable register).Can somebody tell me if the first paragraph is the right way of implementing such a system? Is the second paragraph the solution that is typically done in high speed ADC systems?Thank you for your help!

author: NorthGuy
author_rank: Super Contributor
timestamp: October 24, 2018, 01:38:19 am
content: FIFO refers to first-in-first-out scheme, but IMHO it is confusing here because you do not read everything you acquire, but only the window. So, it's better to stick with the term (circular) buffer.You have already answered your question. Say, you determined that your trigger point is stored at address X. Then you start reading from buffer[X-pre_trigger] to buffer[X+post_trigger], which is (1+pre_trigger+post_trigger) = (window_size) times. It'll wrap around automatically, just make sure your buffer has power of 2 size, such as 1024. You also need to make sure that your buffer size is at least (pre_trigger+1+trigger_detection_latency), otherwise ADC will overwrite the buffer before you read it.I don't understand why you need a second FIFO unless you want to switch between clock domains. You can process the data immediately as you read it. While you're doing this, ADC continues to acquire, so your buffer needs dual access - writes by ADC and reads at desired addresses.

author: nickolas
author_rank: Newbie
timestamp: October 24, 2018, 04:01:47 am
content: Quote from: NorthGuy on October 24, 2018, 01:38:19 amI think this gets to the heart of my question, is there any way to keep the read/write pointers internal to the circular buffer (so I don't need to add extra ports and clutter a top level module)? If I wanted to compute exactly X-pre_trigger and X+post_trigger, I would need to register the write address at trigger external to the circular buffer. Then I would need to advance the read pointer until it equals X-pre_trigger and then store up till read pointer equals X+post_trigger. I thought it would be more optimal, and easier to have a circular buffer with read pointer always following the write pointer by pre_trigger (of course a little more than pre_trigger to account for latency) and when trigger, have a down counter activate the read and write for the transfer from one FIFO to another.Quote from: NorthGuy on October 24, 2018, 01:38:19 amYes, I probably explained this poorly. I can't readout from the circular buffer at 100 MHz off the board. The current revision of the board has a DIN connector to a 64 bit backplane, which I plan to control by a Raspberry Pi with an 8 bit address bus, 8 bit data bus, and control lines. Of course, I'm in debugging stages on the FPGA, so the trigger will fully be controlled by the Raspberry Pi so I have all the time in the world to readout from the secondary buffer, but want the circular buffer to continue acquiring from the ADC so I have access to the pre_trigger information. I've tested the read/write interface to 64 registers (2 bits of address reference 1 of 4 boards on the backplane, so 2^6 = 64 total registers on each board), so now I'm working out the kinks of moving the circular buffer data into another buffer, and then getting that into the raspberry pi through this interface.

author: NorthGuy
author_rank: Super Contributor
timestamp: October 24, 2018, 04:47:25 am
content: Quote from: nickolas on October 24, 2018, 04:01:47 amIf the latency is the same for all kinds of triggers you certainly can do this. Or, you can build all your triggers so that the latency is always the same. This way, you may not even need memory. You can use shift registers - ADC writes, then n cycles later you read it from the other end. It depends on how long the pre_trigger is.