Xilinx
Block Preview

Introduction

Averaging $M$ repetitions of the same triggered waveform reduces the standard deviation of uncorrelated noise by $\sqrt{M}$ while leaving the coherent pulse shape untouched:

$$ \bar{x}[k] = \frac{1}{M}\sum_{m=0}^{M-1} x_m[k], \quad k = 0, 1, \ldots, L-1 $$

START opens an acquisition window and DV_IN (gated by ENABLE) marks each valid input sample; sample $k$ of every waveform lands in cell $k$ of the accumulator RAM. When $M$ waveforms have been accumulated, the averaged waveform is streamed out one sample per clock: START_OUT pulses on the first sample, DV_OUT is high for the whole burst, END_OUT pulses on the last sample, and WAVE_COUNT carries $M$ for that burst.

$M$ is always a power of two, so the division is a shift and the average is exact with no divider and no DSP. The exponent comes from the runtime NEXP input (clamped to the compile-time Max averages exponent), and the waveform length comes from the runtime LEN input — LEN does not have to be a power of two, and leaving it unconnected uses the whole compiled depth.

Pin Description

DIN Input 14 bit BIT VECTOR
Input samples, Input bits wide, signed or unsigned per the Input format property. Sampled on every clock where DV_IN and ENABLE are high.
Default: Must be connected
DV_IN Input 1 bit BIT
Input sample valid, active high. Works at interval 1 (one sample per clock) and tolerates gaps. Default when unconnected: ‘1’.
START Input 1 bit BIT
Trigger / waveform marker, active high, level sensitive. Opens an acquisition window when the block is idle; the sample present on the same cycle is sample 0. In deferred mode a rising edge inside an open window marks the waveform as piled up. Default when unconnected: ‘0’ (the block never triggers).
Default: Must be connected
ENABLE Input 1 bit BIT
Global enable, active high: gates DV_IN and START. Low freezes the input side without disturbing the accumulator. Default: ‘1’.
LEN Input 13 bit BIT VECTOR
Runtime waveform length in samples, log2(Max waveform depth)+1 bits. Does NOT have to be a power of two. 0 (the value an unconnected port carries) or any value above the compiled depth means “use the whole compiled depth”. Latched at the start of an epoch.
NEXP Input 5 bit BIT VECTOR
Runtime log2 of the number of waveforms to average (5 bit): 0 = 1 waveform (passthrough) … e.g. 10 = 1024 waveforms. Clamped to Max averages exponent. Latched at the start of an epoch. Default: 0.
CLR Input 1 bit BIT
Synchronous clear, active high: drops the history, the wave counter, the OVERFLOW flag and the overflow halt, aborts any acquisition or burst in progress, and re-latches LEN / NEXP. Default: ‘0’.
CLK Input 1 bit BIT
Clock. Rising edges drive all operations.
Default: Default Board Clock
RESET Input 1 bit BIT
Global reset: same effect as CLR.
Default: Default Board Reset
DOUT Output 14 bit BIT VECTOR
Averaged waveform: sequential burst of LEN samples, one per clock, in acquisition order. Width and scaling per the Output format property.
DV_OUT Output 1 bit BIT
High for the LEN cycles of the output burst.
START_OUT Output 1 bit BIT
One-cycle pulse on the first output sample (k = 0).
END_OUT Output 1 bit BIT
One-cycle pulse on the last output sample (k = LEN-1).
WAVE_COUNT Output 21 bit BIT VECTOR
Number of waveforms contained in the burst being emitted, i.e. the divisor already applied in Averaged mode and the divisor still to apply in the two raw modes. Constant in Clear-history mode, doubling at every burst in Keep-history mode. Width Max averages exponent + 1 bits. Latched at emission and held until the next one.
ACQUIRING Output 1 bit BIT
High while a waveform is being captured, and in deferred mode also while it is being committed to the accumulator.
INTEGRATING Output 1 bit BIT
High while a round is open: at least one waveform has been accumulated and the target count has not been reached yet. Stays high between waveforms, unlike ACQUIRING.
BUSY Output 1 bit BIT
High from the last accumulated sample of a round through the last DV_OUT of its burst. Triggers arriving while BUSY is high are ignored.
OVERFLOW Output 1 bit BIT
Latched high as soon as any single accumulator cell overflows 36 bit. Cleared by CLR or RESET. With “Stop averaging and flag” the block also halts.
PRETRIG
Number of pre-trigger samples, log2(Max pre-trigger)+1 bits. Only exists when Max pre-trigger is non-zero. Counted in VALID SAMPLES, so DV_IN gaps do not shift the alignment; clamped to the compiled buffer depth and to LEN, and latched at the start of an epoch. It also sets the span the pile-up veto protects. Default when unconnected: 0.
DISCARD_PILEUP
Deferred mode only. Active high: a waveform contaminated by a second trigger inside its window is thrown away and does not count towards the average. 0 accumulates it anyway (PILEUP still pulses). Default: ‘1’.
PILEUP
Deferred mode only. One-cycle pulse at the end of every window in which a second trigger was seen, whether or not the waveform was discarded.

Properties

Property window

Max waveform depth MaxLength

Maximum number of samples per waveform, power of two. Sizes the accumulator RAM (this depth x 36 bit) and the width of the LEN input. The waveform length actually accumulated is taken at run time from the LEN pin and does NOT have to be a power of two.

Maximum number of samples per waveform (64 .. 65536, power of 2). Sizes the accumulator RAM (this depth x 36 bit) and the width of the LEN input; in deferred mode it also sizes the scratch RAM. The length actually accumulated comes from the LEN pin at runtime and does not have to be a power of two. Keep this as small as your application needs.

Default: 4096

Options: 64 128 256 512 1024 2048 4096 8192 16384 32768 65536

Max pre-trigger MaxPreTrigger

Depth of the internal pre-trigger buffer, in samples, power of two. 0 removes the buffer (and the PRETRIG pin) entirely: the waveform then starts exactly on the trigger. Anything else adds a circular memory of this depth x Input bits that continuously records the input, so the waveform can start up to this many samples BEFORE the trigger with no external delay line. The number of pre-trigger samples actually used is taken at run time from the PRETRIG pin.

Depth of the internal pre-trigger buffer in samples, power of two, or 0 to leave it out entirely (which also removes the PRETRIG pin). Costs one circular memory of this depth x InputBits. The number of pre-trigger samples actually used comes from the PRETRIG pin at run time. Keeping the buffer inside the block is what lets the pile-up veto cover the pre-trigger region – an external Delay block cannot.

Default: 0

Options: 0 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768

Input bits InputBits

Width of the DIN samples, up to 24 bit. The accumulator is always 36 bit, so up to 2**(36-InputBits) full-scale waveforms can be summed before the cells overflow.

Width of DIN (1 .. 24). The accumulator is always 36 bit, so up to 2**(36-InputBits) full-scale waveforms can be summed before the cells can overflow.

Default: 14

Range: 1 – 24

Input format InputFormat

Interpretation of DIN. Drives the accumulator arithmetic, the overflow test, the rounding of the averaged output and the saturation of the raw output modes.

Signed or Unsigned interpretation of DIN. Drives the accumulator arithmetic, the overflow test, the rounding of the averaged output and the saturation of the raw output modes.

Default: Signed

Options: Signed Unsigned

Max averages exponent MaxExp

Largest exponent the runtime NEXP input can request (NEXP is clamped to it). Also sizes the WAVE_COUNT output, and in Keep-history mode it is the exponent at which the epoch is closed and the accumulator restarted.

Largest exponent the runtime NEXP input can request, 1 .. 31 (NEXP is clamped to it). Also sizes the WAVE_COUNT output, and in Keep-history mode it is the total count at which the epoch is closed and the accumulator restarted.

Default: 20

Range: 1 – 31

History History

Clear history after each output: after every output burst the accumulator is dropped, so each burst is the mean of its own 2NEXP waveforms. Keep history (cumulative): the accumulator is never dropped and a new burst is emitted every time the TOTAL waveform count reaches the next power of two (2NEXP, 2**(NEXP+1), …), so the divisor stays a shift and the mean stays exact. WAVE_COUNT always reports how many waveforms the burst being emitted contains.

  • Clear history after each output: the accumulator is dropped after every burst; each burst is the mean of its own 2**NEXP waveforms.
  • Keep history (cumulative): the accumulator is never dropped and a burst is emitted every time the total count reaches the next power of two, so the mean stays exact with no divider. WAVE_COUNT reports the running total.

Default: Clear history after each output

Options: Clear history after each output Keep history (cumulative)

Output format OutputFormat

Averaged, input width: DOUT is InputBits wide and carries the accumulator divided by WAVE_COUNT, rounded half-up. Accumulator raw, 32 bit (saturated): DOUT is 32 bit and carries the raw accumulator, saturated. Accumulator raw, 36 bit: DOUT is 36 bit and carries the raw accumulator, exact. In the two raw modes WAVE_COUNT is the divisor the downstream logic has to apply.

  • Averaged, input width: DOUT is InputBits wide, the accumulator divided by WAVE_COUNT and rounded half-up.
  • Accumulator raw, 32 bit (saturated): DOUT is 32 bit, raw sum.
  • Accumulator raw, 36 bit: DOUT is the full accumulator, exact. In the raw modes WAVE_COUNT is the divisor to apply downstream.

Default: Averaged, input width

Options: Averaged input width Accumulator raw 32 bit (saturated) Accumulator raw 36 bit

On accumulator overflow OverflowMode

Every accumulation is checked at 37 bit and the cell always SATURATES, never wraps. Stop averaging and flag: the block also halts as soon as a single cell overflows – no further waveform is accepted and no further burst is emitted until RESET or CLR. Saturate and flag, keep running: the OVERFLOW output is raised but averaging continues on saturated cells.

Cells always saturate rather than wrap, and OVERFLOW always latches. This property only decides whether the block additionally HALTS (accepting no further waveform until CLR / RESET) or keeps averaging on saturated cells.

Default: Stop averaging and flag

Options: Stop averaging and flag Saturate and flag keep running

Acquisition mode AcquisitionMode

Direct (accumulate while acquiring): the trigger starts the recording and every sample is summed into the accumulator straight away. Deferred (accumulate at end, pile-up aware): the waveform is first captured into a scratch RAM (an extra MaxLength x InputBits memory) and it is added to the accumulator only at the END of the window; a second trigger inside the window marks it as piled up, and the DISCARD_PILEUP input then decides whether it is thrown away. Use this to build clean pulse templates. The commit pass costs one extra waveform length of dead time.

  • Direct: the trigger starts the recording and samples are accumulated immediately.
  • Deferred (pile-up aware): the waveform is captured into a scratch RAM and committed only at the end of the window; a second trigger inside the window marks it as piled up and DISCARD_PILEUP decides whether it is thrown away. Adds the DISCARD_PILEUP and PILEUP pins, one scratch RAM and one waveform length of dead time. Use it to build clean pulse templates.

Default: Direct (accumulate while acquiring)

Options: Direct (accumulate while acquiring) Deferred (accumulate at end pile-up aware)

Acquisition modes

Direct — the trigger starts the recording and every sample is summed into the accumulator straight away. Lowest latency and lowest resource use. A START arriving while a window is already open is ignored; the window always runs for exactly LEN valid samples.

Deferred (pile-up aware) — the waveform is first captured into a scratch RAM and is added to the accumulator only at the end of the window. If a second trigger arrives inside the window the waveform is marked as piled up and the DISCARD_PILEUP input decides its fate: 1 throws it away (it does not count towards $M$), 0 accumulates it anyway. PILEUP pulses for one clock at the end of every contaminated window either way, so pile-up can be counted. This is the mode to use when building a clean pulse template. It costs one extra scratch RAM (Max waveform depth × Input bits) and one extra waveform length of dead time per acquisition.

Pre-trigger

Set Max pre-trigger to a non-zero depth and the block allocates a circular buffer that continuously records the input, plus a PRETRIG input that picks how many samples to actually use. The waveform then spans x[T-PRETRIG .. T-PRETRIG+LEN), so the rising edge sits PRETRIG samples into the burst and you get the baseline in front of it.

Do not build the pre-trigger with an external Delay block. It looks equivalent and it is not. Pile-up is vetoed by comparing trigger times, so if you delay DIN outside the block the data window moves and the veto window does not: the two end up offset by the delay, the pre-trigger region becomes a blind spot, and a second pulse landing in it is averaged in — it shows up as a small extra pulse in front of the real one. With the internal buffer the block knows PRETRIG and vetoes the whole captured span, which is why the buffer lives inside the IP.

The veto is exact on both edges:

  • a trigger in the pre-trigger region [T-PRETRIG, T) vetoes the waveform, including a trigger the block itself had to refuse because it was busy committing or streaming out. That case is the common one: the deferred dead time is 2xLEN per accepted waveform, so every accepted waveform is by construction the first trigger after the block freed up, and an event refused a few clocks earlier is sitting right in its pre-trigger.
  • a trigger past the end of the captured data, i.e. later than T+LEN-PRETRIG, does not veto: it never made it into the waveform, and throwing the waveform away for it would only cost efficiency.

PRETRIG is counted in valid samples, not clocks, so gaps on DV_IN do not shift the alignment. It is clamped to the compiled buffer depth and to LEN (a pre-trigger cannot be longer than the waveform), and it is latched with LEN and NEXP at the start of an epoch. Leaving the pin unconnected gives 0, i.e. the waveform starts on the trigger. The buffer needs PRETRIG samples of history to be meaningful, so the first waveform after RESET reads whatever the memory was initialised to if it arrives sooner than that.

History modes

Clear history after each output — the accumulator is dropped after every burst, so each burst is the mean of its own $2^{NEXP}$ waveforms and consecutive bursts are statistically independent. WAVE_COUNT is constant.

Keep history (cumulative) — the accumulator is never dropped and a new burst is emitted every time the total count reaches the next power of two: $2^{NEXP}$, $2^{NEXP+1}$, $2^{NEXP+2}$, … Each burst is the exact mean of every waveform seen so far and WAVE_COUNT reports that total, so the estimate keeps improving without the block ever needing a divider. Emissions naturally become rarer as the average deepens. When the total reaches $2^{MaxExp}$ the epoch is closed: the history is dropped and a new one starts from $2^{NEXP}$ (this is also when LEN and NEXP are re-latched).

Clearing the history is free: the first waveform of an epoch is written through (acc = x instead of acc = acc + x) rather than wiping the RAM. A side effect worth knowing is that stale cells left over from a longer previous LEN can never reach the output.

Output formats

With $M$ accumulated waveforms the accumulator holds $\sum x_m[k]$.

  • Averaged, input width — DOUT is Input bits wide and carries $\left\lfloor (\sum x_m + M/2) / M \right\rfloor$ (round half-up). No precision is lost that matters: the mean of $M$ values always fits the input range.
  • Accumulator raw, 32 bit (saturated) — DOUT is 32 bit and carries the raw sum, saturated.
  • Accumulator raw, 36 bit — DOUT is the full 36 bit accumulator, exact.

In the two raw modes WAVE_COUNT is the divisor the downstream logic has to apply; they are the right choice when the normalization is done in software or when the extra $\log_2 M$ bits of resolution are wanted.

Overflow

Every accumulation is checked at 37 bit and the cell always saturates, never wraps, so a single overflowing sample cannot corrupt the whole waveform. OVERFLOW latches high as soon as any one cell overflows, and the On accumulator overflow property decides whether the block also halts:

  • Stop averaging and flag — no further waveform is accepted and no further burst is emitted until RESET or CLR. Use this when a wrong result is worse than no result.
  • Saturate and flag, keep running — averaging continues on saturated cells; OVERFLOW tells you the result is no longer trustworthy.

With Input bits $b$ and a 36 bit accumulator, $2^{36-b}$ full-scale waveforms can be summed before overflow is even possible (e.g. 4096 with 14 bit input). Real signals rarely sit at full scale on every sample, so the practical limit is usually much higher.

Dead time

There is one accumulator RAM, no ping-pong. BUSY is high from the last accumulated sample of a round through the last DV_OUT of its burst, and triggers arriving while BUSY is high are ignored. The dead time is therefore one waveform length every $2^{NEXP}$ waveforms in direct mode (a $1/2^{NEXP}$ duty loss), plus one waveform length per acquisition in deferred mode. Set Max waveform depth no larger than you need — it is what sizes the RAM.

Status flags

  • ACQUIRING — a waveform is being captured (and, in deferred mode, also while it is being committed to the accumulator).
  • INTEGRATING — a round is open: at least one waveform has been accumulated and the target count has not been reached yet. It stays high between waveforms, which is what distinguishes it from ACQUIRING.
  • BUSY — the output burst owns the RAM and triggers are refused.

Timing contract

  • START is level sensitive for triggering: a high START on a cycle where the block is idle opens a window, and the sample present on that same cycle (if DV_IN is high) is sample 0. This is what allows back-to-back waveforms on consecutive clocks; tying START high makes the block free-run.
  • Pile-up detection is edge sensitive, so a START held high for the duration of a pulse does not flag its own window.
  • The block works at DV_IN interval 1 (one sample per clock) and tolerates arbitrary DV_IN gaps inside a window.
  • LEN and NEXP are latched at the start of the first (write-through) waveform of an epoch. Change them together with a CLR pulse.

Resources

One accumulator memory of Max waveform depth × 36 bit, plus a scratch memory of Max waveform depth × Input bits in deferred mode, plus a pre-trigger buffer of Max pre-trigger × Input bits. No DSP, no HLS, no divider and no multiplier: pure VHDL.

All three are written as the standard single-clock simple-dual-port template — synchronous read into a register, one read port, one write port — and none of them is ever reset, which is a hard requirement for block RAM (the contents of a BRAM cannot be cleared; that is also why the first waveform of an epoch is written through instead of wiping the memory). 36 bit is one native RAMB36 word in SDP mode, so the accumulator maps without padding.

Whether they actually land in block RAM is still the synthesiser’s choice, not something this block forces: no ram_style attribute is applied, and Vivado picks block vs distributed on a size heuristic. Small configurations will legitimately become LUTRAM or plain registers, which is the cheaper answer anyway. As an order of magnitude, depth 4096 × 36 bit is 147456 bit ≈ 4 RAMB36; treat that as arithmetic on the bit count, not as a measured utilisation figure. If a specific implementation is required, force it with a ram_style attribute and check the synthesis report.

Verified with a self-checking GHDL regression (15 configurations, 597 checks: both history modes, all three output formats, signed and unsigned, gapless back-to-back rounds, LEN defaulting and clamping, LEN = 1, NEXP = 0, half-up rounding on negative accumulations, overflow saturation and halt, CLR, pile-up discard and override, and the DV_OUT/START_OUT/END_OUT/BUSY/WAVE_COUNT framing). 21 deliberate mutations of the core were all caught.