Xilinx
HLS
Block Preview

Introduction

The Histogram Analyzer is two engines sharing one memory.

The binner takes one sample per clock, conditions it, and increments one bin. The scanner walks that histogram at the end of every accumulation frame and extracts statistics from it. They are independent: the scanner never sees a sample and the binner never sees a statistic. That separation is the whole design - it is what lets a block accumulate at the full clock rate and still produce a full statistical description of the distribution without a second pass over the data.

Input conditioning: subtract, shift, clamp - in that order

$$ d = x - \mathrm{BASE}, \qquad b = \left\lfloor \frac{d}{2^{\mathrm{SHIFT}}} \right\rfloor, \qquad \mathrm{bin} = \mathrm{clamp}(b,; 0,; \mathrm{MAX_BIN}) $$

The order matters and it is fixed. BASE is subtracted first, so you can aim the histogram at a window of the input range (subtract 1000 and only the region above 1000 is binned). SHIFT then divides by a power of two, which is how you rebin: SHIFT = 3 puts eight input codes into every bin. Only then is the result clamped into $[0, \mathrm{MAX_BIN}]$.

All three are runtime input pins, and so is PERIOD, the number of samples in a frame. They are latched on the first accepted sample of a frame, so changing any of them mid-frame takes effect on the NEXT frame - a histogram is never binned two different ways.

Out-of-range samples are CLAMPED, not discarded

A sample below the base lands in bin 0 and increments UNDERFLOW. A sample above MAX_BIN lands in MAX_BIN and increments OVERFLOW. They are counted, not thrown away, so TOTAL always equals the number of samples the frame accumulated and the quantiles stay well defined. The two counters are what tell you the distribution was clipped: a large UNDERFLOW or OVERFLOW means the mean, the variance and the tail quantiles are all being pulled towards the edge bins and should not be trusted. Fix the BASE and the SHIFT, not the statistics.

The three operating modes

These are genuinely different hardware, not a mode bit.

RAM dead time snapshot needs IN_DV gaps
FREEZE 1x yes, the whole scan consistent no
LIVE 1x none NOT consistent yes
DOUBLE 2x none consistent no

FREEZE accumulates for one frame, stops the binner, scans, and resumes. The statistics are a perfectly consistent snapshot of exactly the samples of that frame. The price is dead time: every sample that arrives during the scan is ignored, and LOST counts them. For a slow control loop reading a detector spectrum every few milliseconds this is usually the right answer, because the scan is a few thousand clocks and the frame is millions.

DOUBLE uses two RAMs, ping-pong: the binner fills one while the scanner walks the other, and they swap at every frame end. Consistent snapshot, no dead time, no stall. It costs twice the block RAM and nothing else. If you have the memory, use this one.

LIVE uses one RAM and never stops the binner: the scanner steals the memory on clocks the binner is not using. It costs you two things, both real, and you should not choose it without understanding them.

What LIVE mode actually costs you

1. The statistics are not a consistent snapshot. The scanner reads bin 0 at the start of the scan and the last bin thousands of clocks later, while the binner keeps writing. The “histogram” the statistics describe was therefore never simultaneously in the memory. Every result is a smear over the scan window:

  • TOTAL is not the count of any one frame - it is the sum of bin contents read at different times.
  • A peak that moves during the scan can be counted twice (once at its old position, once at its new one) or missed entirely.
  • The mean, variance, skewness and kurtosis are the moments of that smear, not of the signal.
  • With Clear on Scan enabled, each bin holds the counts accumulated since that bin was last cleared - one frame ago, but at a different phase for every bin. That is a defensible measurement (it is how a sweeping analyser works) but it is not a snapshot.

Being precise about it, because “the numbers are approximate” is not useful: the scan reads every bin twice, once per pass, and in LIVE mode the two readings differ. The total, the mode and the occupied-bin range come from the first pass; the cumulative count, the occupancies and the central moments come from the second. The moments are divided by the population the second pass saw, so each moment is at least self-consistent. The quantiles cannot be: a quantile needs the total before the pass that resolves it, so it is tested against the first pass’s total while counting the second pass’s bins. In FREEZE and DOUBLE mode the memory is frozen and all of this collapses to one number; in LIVE mode it does not, and that last item is the one irreducible inconsistency of the mode.

If the distribution is stationary over the scan window none of this matters and LIVE mode is free. If it is not - a drifting baseline, a peak moving, a burst - the numbers are wrong in ways no flag can tell you about. Use FREEZE or DOUBLE.

2. The scan needs idle clocks, and can stall for ever. The histogram memory has one read port and one write port. A one-sample-per-clock increment is read the old count on one clock, write the new one on the next, so the binner occupies the read port on every clock a sample is accepted and the write port on the following clock. The scanner therefore advances

one bin per clock on which NO sample was accepted this clock or the previous one.

With IN_DV tied permanently high, the scanner never advances and no result is ever produced: SCANNING stays high and SCAN_POS stops moving, which is exactly how you see it on a scope. LIVE mode is for streams with gaps - roughly, an IN_DV duty cycle below about two thirds.

The two costs compound with the SERIAL moment engine: a bin then needs several such free clocks rather than one, so the duty cycle has to leave proportionally more room. The compiler log warns when both are selected.

That same arbitration rule is what makes the mode safe: because the scanner only moves when the binner is touching neither port, a clear-on-scan can never land between the read and the write of an increment, so no count is ever lost.

Dropped frames

In LIVE and DOUBLE mode a frame that completes while the scanner is still busy has its result dropped: no OUT_DV, no buffer swap. Accumulation is unaffected and the next frame is analysed normally. Keep PERIOD comfortably above the scan length (the compiler log prints it) and this never happens. FREEZE mode cannot drop a frame, because its binner is stopped for the whole scan.

Everything is in BIN units

MIN_BIN, MAX_BIN_OCC, MODE_BIN, MEDIAN, the quantiles, IQR, RANGE, FWHM, FWTM and PEAK_POS are bin indices. MEAN, VARIANCE and STDDEV are in bins and bins squared. SKEWNESS and KURTOSIS are dimensionless.

To convert a bin index back to the input scale:

$$ x ;=; \mathrm{BASE} ;+; \left(\mathrm{bin} + \tfrac{1}{2}\right)\cdot 2^{\mathrm{SHIFT}} $$

The block deliberately does not do this for you: BASE and SHIFT are runtime pins, the conversion is one shift and one add in your own logic or in software, and doing it here would mean a second Q format on every one of a dozen outputs.

How the scan works, and why it is two passes

$$ \textbf{pass 1:}\quad M_0=\sum_k H_k,\qquad M_1=\sum_k k,H_k $$

plus the mode (argmax, first occurrence), the lowest and highest occupied bin, how many bins are non-empty and how many are saturated.

Between the passes one division produces the mean $m = M_1/M_0$, and with it $k_0=\lfloor m\rfloor$, the origin the central moments are taken about.

$$ \textbf{pass 2:}\quad C_n=\sum_k (k-k_0)^n H_k \quad (n=2,3,4) $$

plus the running cumulative count (median, quantiles, IQR), the threshold occupancies, the half- and tenth-maximum crossings either side of the mode, the three bins around the mode for the parabolic interpolation - and the clear, if it is enabled.

Why the quantiles force two passes: a quantile is the first bin whose cumulative count reaches $q$ of the total, and the total is only known once the whole histogram has been added up. The alternative - predicting the total from the sample counter - breaks the moment a bin saturates or the histogram is cumulative, so the block does the honest thing and reads the bins twice.

Why the moments are taken about $k_0$ and not about zero: the exact integer numerators for the third and fourth moments about zero carry factors of $M_0^3$ and $M_0^4$ and reach $8\cdot\text{ADDR_BITS}+4\cdot\text{BIN_BITS}$ bits, which is not buildable. About $k_0$ every central sum is bounded by $M_0\cdot\text{range}^n$ instead, and the leftover fractional offset $e = m - k_0 < 1$ is folded back in afterwards with the exact identities

$$ \mu_2 = a_2 - e^2,\qquad \mu_3 = a_3 - 3ea_2 + 2e^3,\qquad \mu_4 = a_4 - 4ea_3 + 6e^2a_2 - 3e^4 $$

with $a_n = C_n/M_0$. That is what the two-pass structure buys.

No divider in the per-bin path

The quantile test is

$$ \text{cum} \times 100 ;\ge; \text{PCT} \times M_0 $$

with PCT a compile-time constant, so both sides are constant multiplies (shift-adds) and there is no divider anywhere in the loop that runs once per bin. The powers of the bin offset are built incrementally ($d_2=d\cdot d$, $d_3=d_2\cdot d$, $d_4=d_2\cdot d_2$) - there is no general power either. Every division in the block lives in the tail, happens once per frame, and shares one serial restoring stage; the square root shares one digit-recurrence stage the same way. Skewness and kurtosis are computed as chained divisions,

$$ \text{skew} = \frac{\mu_3/\mu_2}{\sigma},\qquad \text{kurt} = \frac{\mu_4/\mu_2}{\mu_2} $$

rather than one division by $\mu_2^{3/2}$ or $\mu_2^2$: two narrow divisions instead of one very wide one, which costs clocks we have and saves bits we do not.

The per-bin multipliers: SERIAL or PIPELINED

There is no divider in the per-bin path, but with SKEWNESS or KURTOSIS enabled there are six multiplies on every bin of pass 2:

$$ d_2 = d\cdot d,\quad C_2 \mathrel{+}= d_2 H,\quad d_3 = d_2 d,\quad C_3 \mathrel{+}= d_3 H,\quad d_4 = d_2 d_2,\quad C_4 \mathrel{+}= d_4 H $$

and they are wide: $d_4$ alone is $4\log_2 N_{\rm bins}+4$ bits, so at 1024 bins $d_4\cdot H$ is a 44 x BitsPerBin product. Running one bin per clock means all six exist at the same time, which is of order 10 to 15 DSP48 slices on a part that may only have 80 - and it grows with the bin count.

Moment Implementation chooses which way to pay:

  • SERIAL (default) - spend several clocks per bin and drive one shared multiplier through the six products. Typically three to four times fewer DSP48s. Pass 2 becomes 4 clocks per bin with one of the two shape moments enabled, 6 with both.
  • PIPELINED - six parallel multipliers, one bin per clock, shortest scan.

The two produce bit-identical results. The serial engine changes only when each exact integer product is formed, never how; the regression suite runs matched SERIAL/PIPELINED pairs and requires every output of every frame to agree to the bit. Only the latency differs, and the formula below carries it.

The scan happens once per frame and PERIOD is normally far larger than the scan, so SERIAL is almost always the right trade: at 1024 bins it moves the scan from roughly 2500 to roughly 8000 clocks, which matters only if PERIOD is close to the scan length in the first place. Choose PIPELINED when you are deliberately running short frames back to back and have DSPs to spare.

The setting does nothing unless SKEWNESS or KURTOSIS is enabled: with MEAN / VARIANCE / STDDEV alone the per-bin path is $d_2 = d\cdot d$ and $C_2 \mathrel{+}= d_2 H$, two multiplies, and there is nothing worth folding. SERIAL then costs exactly nothing - same schedule, same latency, same logic.

Latency

With $n_b = \mathrm{MAX_BIN}+1$ bins actually scanned, the clocks from the last accepted sample of a frame to its OUT_DV pulse are

$$ L(n_b) = n_b + 5 + ,\text{mean}, + ,\text{pass 2},,P + N_{\rm div}(D+1) + ,\sigma, $$

where $D$ is the serial divider width, $R$ the square-root width, $N_{\rm div}$ the number of tail divisions, and $P$ the clocks pass 2 spends on one bin - $P=1$ except with the SERIAL moment engine active (see above), where it is 4 with one shape moment enabled and 6 with both. The compiler log prints the actual number for your configuration. In LIVE mode this is a lower bound: the two pass terms stretch by one clock for every clock the scanner is denied the memory, so a SERIAL scan there needs $P$ free clocks per bin rather than one.

The practical consequence: MAX_BIN is the knob that controls latency. The RAM is sized by Max Bins (exponent), but only bins $0\ldots$MAX_BIN are scanned, so a 4096-bin RAM run with MAX_BIN = 255 scans in a quarter of the time. Size the RAM for the worst case and use MAX_BIN for everything else.

Bin saturation - read this one

A bin counts up to $2^{\text{BitsPerBin}}-1$ and then stops. From that moment the histogram understates the peak, and therefore so do the mode count, the mean, the variance, every quantile and every moment - silently. BIN_SATURATED goes high for the frame in which an increment was actually dropped, and SAT_BINS says how many bins are sitting at the maximum. They are on by default and they should stay on. If they fire, either shorten the frame (lower PERIOD), widen the bins (raise SHIFT), or raise Bits per Bin.

Typical uses

  • Multichannel analyser / pulse-height spectrum. Feed pulse heights, disable Clear on Scan, and the histogram is the spectrum. MODE_BIN and PEAK_POS locate the photopeak, FWHM and FWTM measure the energy resolution and the tailing, and OCC0..3 with runtime THR pins are region-of-interest counters.
  • Baseline and noise monitoring. MEDIAN is a baseline estimate that a few outliers cannot move; IQR is a robust noise width that needs no square root at all.
  • ADC health. NONEMPTY_BINS on a raw ADC stream finds stuck bits and missing codes instantly; UNDERFLOW and OVERFLOW find clipping.
  • Distribution shape. SKEWNESS and KURTOSIS discriminate a Gaussian noise floor from pile-up or from a bimodal distribution.
  • Threshold scanning. Sweep THR0 from software and read OCC0 for an S-curve, without re-running the acquisition.

Pin Description

IN Input IN_BitsInt + IN_BitsFract bit BIT VECTOR
Input samples, fixed point in the IN Q format. Binned on clocks where IN_DV is high and the block is accepting (see the mode notes: FREEZE ignores samples during its scan).
Default: Must be connected
IN_DV Input 1 bit BIT
Per-sample qualifier, active high, and the only qualifier this block has. Unconnected defaults to '1', so the block free-runs out of the box. In LIVE mode this must have gaps or the scan never completes.
BASE Input IN_BitsInt + IN_BitsFract bit BIT VECTOR
Value subtracted from every sample before the shift, in the input Q format. Use it to aim the histogram at a window of the input range. Latched on the first accepted sample of a frame. Unconnected defaults to 0. Samples below it land in bin 0 and increment UNDERFLOW.
SHIFT Input 5 bit BIT VECTOR
Rebin factor: after the base is subtracted the value is divided by $2^{\text{SHIFT}}$, so SHIFT = 3 puts eight input codes into every bin. 5 bits, 0..31. Latched per frame. Unconnected defaults to 0 (one bin per input LSB).
MAX_BIN Input MaxBinsExponent bit BIT VECTOR
Highest bin index used, at run time: only bins $0\ldots$MAX_BIN are binned into and scanned. This is the latency knob - the scan is proportional to MAX_BIN + 1, so a large RAM run with a small MAX_BIN is fast. Latched per frame. Unconnected defaults to all ones (the whole RAM). Samples above it land in MAX_BIN and increment OVERFLOW.
PERIOD Input 32 bit BIT VECTOR
Number of accepted samples in one accumulation frame; the scan starts when the count is reached. 32 bits; 0 is treated as 1. Latched per frame. Unconnected defaults to 65536. Keep it comfortably above the scan length or frames will be dropped (LIVE and DOUBLE) or the duty cycle will suffer (FREEZE).
TOTAL Output MaxBinsExponent + BitsPerBin bit BIT VECTOR
$\sum_k H_k$ over the scanned histogram - how many counts it holds. With Clear on Scan on this is the number of samples of the frame; without it, the number since the last clear. Valid on OUT_DV.
MIN_BIN Output MaxBinsExponent bit BIT VECTOR
Lowest bin with a non-zero count. 0 if the histogram is empty.
MAX_BIN_OCC Output MaxBinsExponent bit BIT VECTOR
Highest bin with a non-zero count. 0 if the histogram is empty.
MODE_BIN Output MaxBinsExponent bit BIT VECTOR
The bin with the largest count. If the maximum is tied, the first (lowest-index) one wins - the comparison is strict.
MODE_COUNT Output BitsPerBin bit BIT VECTOR
The count in MODE_BIN. Compare it against the saturation limit implied by Bits per Bin.
MEDIAN Output MaxBinsExponent bit BIT VECTOR
The first bin whose cumulative count reaches half the total, i.e. the 50 % quantile. A baseline estimate a few outliers cannot move.
MEAN Output MEAN_BitsInt + MEAN_BitsFract bit BIT VECTOR
$M_1/M_0$, the centroid, in BIN units and in the MEAN Q format. Convert with $x = \text{BASE} + (\text{MEAN}+\tfrac12)2^{\text{SHIFT}}$.
VARIANCE Output VARIANCE_BitsInt + VARIANCE_BitsFract bit BIT VECTOR
The second central moment, in BIN², in the VARIANCE Q format. 0 for a single occupied bin.
STDDEV Output STDDEV_BitsInt + STDDEV_BitsFract bit BIT VECTOR
$\sqrt{\text{VARIANCE}}$, in BIN units. It reuses the same serial digit-recurrence root the skewness needs, so the two together cost one engine.
BIN_SATURATED Output 1 bit BIT
High for the frame in which a bin reached its maximum count and an increment was actually dropped. Once this fires every other statistic understates the peak. On by default; leave it on.
UNDERFLOW Output 32 bit BIT VECTOR
How many samples of the frame fell below the BASE and were clamped into bin 0. 32 bits.
OVERFLOW Output 32 bit BIT VECTOR
How many samples of the frame fell above MAX_BIN and were clamped into it. 32 bits.
OUT_DV Output 1 bit BIT
One clock high when a scan has finished and every enabled output carries that frame’s result. Latch everything on this edge. A frame whose scan could not start (LIVE and DOUBLE, scanner still busy) produces no pulse.
THR0 MaxBinsExponent bit
Bin index for the OCC0 occupancy: OCC0 counts everything at or above it. Present only when Enable OCC0 = YES. Latched when the scan starts, so it is a scan parameter and not a per-sample one. Unconnected defaults to the THR0 default bin property, which is what makes a swept software-controlled threshold work without re-synthesis.
THR1 MaxBinsExponent bit
As THR0, for OCC1. Present only when Enable OCC1 = YES.
THR2 MaxBinsExponent bit
As THR0, for OCC2. Present only when Enable OCC2 = YES.
THR3 MaxBinsExponent bit
As THR0, for OCC3. Present only when Enable OCC3 = YES.
RD_ADDR MaxBinsExponent bit
Bin index to read out through the read bus. Present only when Enable Read Bus = YES. The answer appears on RD_DATA one clock later, flagged by RD_DV - which is low whenever the memory was busy, so poll it.
CLK 1 bit
Clock.
RESET 1 bit
Synchronous reset: clears the counters, the frame state and the scanner, and starts the cold clear that zeroes every bin of the histogram RAM ($2^{\text{Max Bins (exponent)}}$ clocks) before anything is accepted.
RD_DATA BitsPerBin bit
The content of bin RD_ADDR, one clock after it was presented. Present only when Enable Read Bus = YES. Valid only on the clocks RD_DV is high; it holds otherwise.
RD_DV 1 bit
High on the clock RD_DATA carries the answer for the address presented on the previous clock. Low whenever the scanner (or, outside DOUBLE mode, the binner) had the memory.
RANGE MaxBinsExponent bit
MAX_BIN_OCC - MIN_BIN, the support width in bins. One subtract.
QUANT0 MaxBinsExponent bit
The first bin whose cumulative count reaches Quantile0 percent of the total. Present only when Enable QUANT0 = YES.
QUANT1 MaxBinsExponent bit
As QUANT0, at Quantile1 percent.
QUANT2 MaxBinsExponent bit
As QUANT0, at Quantile2 percent.
QUANT3 MaxBinsExponent bit
As QUANT0, at Quantile3 percent.
IQR MaxBinsExponent bit
The interquartile range, $P_{75}-P_{25}$, in bins - a robust width that needs no square root. It builds its own 25 % and 75 % trackers, so it does not care how the four QUANT slots are configured. 0 if the two quartiles land in the same bin.
SKEWNESS SKEWNESS_BitsInt + SKEWNESS_BitsFract bit
$\mu_3/\sigma^3$, dimensionless. Negative means a tail to the left (towards lower bins), positive a tail to the right. 0 when the spread is zero. Use a SIGNED Q format.
KURTOSIS KURTOSIS_BitsInt + KURTOSIS_BitsFract bit
$\mu_4/\sigma^4$, dimensionless, minus 3 if Kurtosis Definition is EXCESS (the default), in which case a Gaussian reads 0, a flatter distribution reads negative and a heavy-tailed one positive. 0 when the spread is zero.
OCC0 MaxBinsExponent + BitsPerBin bit
How many counts sit at or above bin THR0: the numerator of the threshold occupancy. The denominator is TOTAL, which is a pin of its own - the block deliberately exposes both instead of paying for a divider so that software can form the ratio for free.
OCC1 MaxBinsExponent + BitsPerBin bit
As OCC0, for THR1.
OCC2 MaxBinsExponent + BitsPerBin bit
As OCC0, for THR2.
OCC3 MaxBinsExponent + BitsPerBin bit
As OCC0, for THR3.
NONEMPTY_BINS MaxBinsExponent + 1 bit
How many bins are non-zero - the support size. One comparator, and it tells you instantly whether the binning is sensible: a handful means the SHIFT is too large, nearly all of them that it is too small. On a raw ADC stream it finds stuck bits and missing codes.
SAT_BINS MaxBinsExponent + 1 bit
How many bins are sitting AT the maximum count. Non-zero means the histogram is clipped from above.
LOST 32 bit
Running count of samples the block refused: the FREEZE dead time, and the cold clear after reset. In LIVE and DOUBLE mode it can only ever count the cold clear. 32 bits, never cleared except by reset.
FWHM MaxBinsExponent + 1 bit
Full width at half maximum, in bins: the distance between the first bin below MODE_COUNT/2 on each side of the mode. Two threshold crossings, no interpolation. If there is no crossing on a side, the histogram edge is used.
FWTM MaxBinsExponent + 1 bit
Full width at tenth maximum, in bins. Same two comparators with a different constant; FWTM/FWHM is the standard peak-tailing figure and a value far above 1.83 means a non-Gaussian tail.
PEAK_POS PEAK_POS_BitsInt + PEAK_POS_BitsFract bit
Sub-bin peak position by parabolic interpolation on $(m-1, m, m+1)$: $;\text{PEAK_POS}=m+\tfrac12\frac{H_{m-1}-H_{m+1}}{H_{m-1}-2H_m+H_{m+1}}$, an absolute bin index with a fraction, in the PEAK_POS Q format. The offset is clamped to $\pm\tfrac12$ bin, and falls back to plain MODE_BIN on an edge bin or a flat top. Its integer part must be wide enough to hold the largest bin index - the property validator enforces it.
BUSY 1 bit
Accumulating, or scanning, or clearing after reset. Its last high clock is the OUT_DV pulse, so the two fall together.
ACCUMULATING 1 bit
High while a frame is open and taking samples.
SCANNING 1 bit
High while the analyser is walking the histogram or finishing its arithmetic. In LIVE mode, SCANNING high with SCAN_POS not moving is a stalled scan - feed the input some gaps.
SCAN_POS MaxBinsExponent bit
The bin the scanner is on: scan progress, 0..MAX_BIN.
SAMPLE_COUNT 32 bit
Samples accumulated so far in the current frame, 32 bits. It holds the final count through the scan and past OUT_DV, so latch it with the results.

Properties

Property window

IN Integer Bits IN_BitsInt

Number of INTEGER bits of the input sample (the sign, when present, uses one of them).

Integer bits of the input (the sign, when present, uses one of them). 1..64.

Default: 16

Range: 1 – 64

IN Fractional Bits IN_BitsFract

Number of FRACTIONAL bits of the input sample, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of the input. 0..64. Total input width must be 2..64 bits.

Default: 0

Range: 0 – 64

IN Sign IN_Sign

Select whether the input sample is signed (two’s complement) or unsigned.

SIGNED (two’’s complement) or UNSIGNED input. The subtraction of BASE is done at one bit more than the input width either way, so a signed input minus a positive base cannot wrap.

Default: SIGNED

Options: UNSIGNED SIGNED

Max Bins (exponent) MaxBinsExponent

The histogram RAM has 2^MaxBinsExponent bins: 10 means 1024 bins. This sizes the MEMORY, so it costs block RAM whether or not you use every bin – the MAX_BIN input then chooses how many of them are actually binned into and scanned AT RUN TIME. Keep it at the largest histogram you will ever ask for and use MAX_BIN for everything else, because a shorter scan is also a shorter latency.

The histogram RAM has $2^{\text{MaxBinsExponent}}$ bins: 10 means 1024. 2..16, default 10. This sizes the memory, so it costs block RAM whether or not you use every bin - the MAX_BIN input then chooses how many are actually binned into and scanned at run time. Size this for the largest histogram you will ever ask for and use MAX_BIN for everything else, because a shorter scan is also a shorter latency.

Default: 10

Range: 2 – 16

Bits per Bin BitsPerBin

Counts per bin: 8 (max 255), 16 (max 65535) or 32 (max 4294967295). THE RAM IS SIZED FROM THIS EXACTLY – nothing is padded to a machine word, so 8 bits per bin costs a quarter of what 32 does. When a bin reaches its maximum it STOPS COUNTING and BIN_SATURATED is raised: past that point every statistic understates the peak, so either size this for the longest frame you will run or watch that flag.

Counts per bin: 8 (max 255), 16 (max 65535) or 32 (max 4294967295). The RAM is sized from this exactly - nothing is padded to a machine word, so 8 bits per bin costs a quarter of what 32 does. When a bin reaches its maximum it stops counting and BIN_SATURATED is raised; past that point every statistic understates the peak. Total RAM = $2^{\text{MaxBinsExponent}}\times$ BitsPerBin bits, doubled in DOUBLE mode.

Default: 16

Options: 8 16 32

Operating Mode OperatingMode

FREEZE: accumulate for one frame, STOP, analyse, resume. Perfectly consistent statistics, one RAM, but the block is deaf for the whole scan and LOST counts what it missed. LIVE: never stop accumulating and analyse the same single RAM as the scanner can get at it. No dead time and no second RAM, but (a) the statistics are NOT a consistent snapshot – bin 0 is read at the start of the scan and the last bin thousands of clocks later, so the result describes a histogram that was never simultaneously in the memory – and (b) the scan only advances on clocks where no sample was accepted this clock or the previous one, so with IN_DV tied high it NEVER FINISHES. Use it only for a stationary distribution on a gappy stream. DOUBLE: two RAMs, ping-pong. Consistent snapshot, no dead time, no stall; twice the block RAM. This is the one to pick unless memory is tight.

FREEZE (default): accumulate one frame, stop the binner, analyse, resume. Consistent statistics, one RAM, dead time for the whole scan (counted in LOST).

LIVE: never stop accumulating and analyse the same single RAM. No dead time and no second RAM, but (a) the statistics are not a consistent snapshot - the scan smears over its own duration - and (b) the scan only advances on clocks where no sample was accepted this clock or the previous one, so with IN_DV tied high it never finishes. Only for a stationary distribution on a gappy stream.

DOUBLE: two RAMs, ping-pong. Consistent snapshot, no dead time, no stall; twice the block RAM. Pick this unless memory is tight.

Default: FREEZE

Options: FREEZE LIVE DOUBLE

Clear on Scan ClearOnScan

YES: the scanner zeroes each bin as it reads it on its last pass, so every frame starts from an empty histogram and the statistics describe THAT frame. NO: the histogram is CUMULATIVE and grows for ever, which is what a multichannel analyser wants – and is exactly why BIN_SATURATED exists. In DOUBLE mode this is also what makes a buffer reusable after the swap.

YES (default): the scanner zeroes each bin as it reads it on its last pass, so every frame starts from an empty histogram and the statistics describe that frame. NO: the histogram is cumulative and grows for ever, which is what a multichannel analyser wants - and is exactly why BIN_SATURATED exists. In DOUBLE mode this is also what makes a buffer reusable after the swap.

Default: YES

Options: NO YES

Enable TOTAL EnableTotal

YES: the TOTAL (how many counts the scanned histogram holds) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the TOTAL pin exists. It is the denominator of every occupancy and the flag that says whether anything was measured. Default YES.

Default: YES

Options: NO YES

Enable MIN_BIN EnableMinBin

YES: the MIN_BIN (lowest occupied bin) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the MIN_BIN pin exists. Default YES.

Default: YES

Options: NO YES

Enable MAX_BIN_OCC EnableMaxBin

YES: the MAX_BIN_OCC (highest occupied bin) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the MAX_BIN_OCC pin exists. Default YES.

Default: YES

Options: NO YES

Enable RANGE EnableRange

YES: the RANGE (MAX_BIN_OCC - MIN_BIN, one subtract) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the RANGE pin exists (MAX_BIN_OCC - MIN_BIN, one subtract). It pulls the occupied-bin registers in. Default NO.

Default: NO

Options: NO YES

Enable MODE_BIN EnableMode

YES: the MODE_BIN (argmax; the FIRST bin if the maximum is tied) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the MODE_BIN pin exists. Default YES.

Default: YES

Options: NO YES

Enable MODE_COUNT EnableModeCount

YES: the MODE_COUNT (the count in MODE_BIN) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the MODE_COUNT pin exists. Default YES.

Default: YES

Options: NO YES

Enable MEDIAN EnableMedian

YES: the MEDIAN (the first bin whose cumulative count reaches half the total) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the MEDIAN pin exists. It needs the running cumulative count and therefore the second pass, which roughly doubles the scan length. Default YES.

Default: YES

Options: NO YES

Enable QUANT0 EnableQ0

YES: the QUANT0 pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the QUANT0 pin exists. Needs the second pass. Default NO.

Default: NO

Options: NO YES

QUANT0 percent Quantile0Percent

Which quantile this slot reports, in PERCENT (1..99): the first bin whose cumulative count reaches this fraction of the total. 50 is the median, 25 and 75 the quartiles. It is a COMPILE TIME constant on purpose – the test is cumulative100 >= percenttotal, and with the percentage fixed both sides are constant multiplies, so no divider is needed anywhere in the per-bin path.

Which quantile QUANT0 reports, in percent (1..99): the first bin whose cumulative count reaches this fraction of the total. Compile time on purpose - the test is cumulative x 100 >= percent x total, and with the percentage fixed both sides are constant multiplies, so no divider is needed in the per-bin path. Default 10.

Default: 10

Range: 1 – 99

Enable QUANT1 EnableQ1

YES: the QUANT1 pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the QUANT1 pin exists. Default NO.

Default: NO

Options: NO YES

QUANT1 percent Quantile1Percent

Which quantile this slot reports, in PERCENT (1..99): the first bin whose cumulative count reaches this fraction of the total. 50 is the median, 25 and 75 the quartiles. It is a COMPILE TIME constant on purpose – the test is cumulative100 >= percenttotal, and with the percentage fixed both sides are constant multiplies, so no divider is needed anywhere in the per-bin path.

Percentile for QUANT1, 1..99. Default 25.

Default: 25

Range: 1 – 99

Enable QUANT2 EnableQ2

YES: the QUANT2 pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the QUANT2 pin exists. Default NO.

Default: NO

Options: NO YES

QUANT2 percent Quantile2Percent

Which quantile this slot reports, in PERCENT (1..99): the first bin whose cumulative count reaches this fraction of the total. 50 is the median, 25 and 75 the quartiles. It is a COMPILE TIME constant on purpose – the test is cumulative100 >= percenttotal, and with the percentage fixed both sides are constant multiplies, so no divider is needed anywhere in the per-bin path.

Percentile for QUANT2, 1..99. Default 75.

Default: 75

Range: 1 – 99

Enable QUANT3 EnableQ3

YES: the QUANT3 pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the QUANT3 pin exists. Default NO.

Default: NO

Options: NO YES

QUANT3 percent Quantile3Percent

Which quantile this slot reports, in PERCENT (1..99): the first bin whose cumulative count reaches this fraction of the total. 50 is the median, 25 and 75 the quartiles. It is a COMPILE TIME constant on purpose – the test is cumulative100 >= percenttotal, and with the percentage fixed both sides are constant multiplies, so no divider is needed anywhere in the per-bin path.

Percentile for QUANT3, 1..99. Default 90.

Default: 90

Range: 1 – 99

Enable IQR EnableIQR

YES: the IQR (the interquartile range, P75 - P25). It builds its OWN 25 % and 75 % trackers, so it does not care what the four QUANT slots are set to pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the IQR pin exists. It builds its own 25 % and 75 % trackers, so it is independent of the four QUANT slots and you do not have to spend two of them to get it. Default NO.

Default: NO

Options: NO YES

Enable MEAN EnableMean

YES: the MEAN (the centroid, in BIN units) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the MEAN pin exists. The mean division is built anyway whenever the variance, the standard deviation, the skewness or the kurtosis is enabled, because they all need $k_0=\lfloor\text{mean}\rfloor$. Default YES.

Default: YES

Options: NO YES

MEAN Integer Bits MEAN_BitsInt

Number of INTEGER bits of the MEAN output, in BIN units (the sign, when present, uses one of them).

Integer bits of the MEAN output. It is a BIN INDEX, so it needs at least MaxBinsExponent bits to reach the top of the histogram.

Default: 16

Range: 1 – 64

MEAN Fractional Bits MEAN_BitsFract

Number of FRACTIONAL bits of the MEAN output, in BIN units, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of the MEAN output. This is a centroid: the fraction is the useful part, so do not skimp. Total width 2..64.

Default: 8

Range: 0 – 64

MEAN Sign MEAN_Sign

Select whether the MEAN output, in BIN units is signed (two’s complement) or unsigned.

SIGNED or UNSIGNED. A bin index is never negative, so UNSIGNED buys one bit.

Default: UNSIGNED

Options: UNSIGNED SIGNED

Enable VARIANCE EnableVariance

YES: the VARIANCE (in BIN^2) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the VARIANCE pin exists. It needs the second central sum and therefore the second pass and one tail division. Default YES.

Default: YES

Options: NO YES

VARIANCE Integer Bits VARIANCE_BitsInt

Number of INTEGER bits of the VARIANCE output, in BIN^2 (the sign, when present, uses one of them).

Integer bits of the VARIANCE output. It is in BIN SQUARED: allow about twice MaxBinsExponent.

Default: 24

Range: 1 – 64

VARIANCE Fractional Bits VARIANCE_BitsFract

Number of FRACTIONAL bits of the VARIANCE output, in BIN^2, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of the VARIANCE output. Total width 2..64.

Default: 8

Range: 0 – 64

VARIANCE Sign VARIANCE_Sign

Select whether the VARIANCE output, in BIN^2 is signed (two’s complement) or unsigned.

SIGNED or UNSIGNED. The variance is clamped at zero, so UNSIGNED is safe and buys one bit.

Default: UNSIGNED

Options: UNSIGNED SIGNED

Enable STDDEV EnableStdDev

YES: the STDDEV (the square root of the variance, in BIN units). It reuses the same serial digit-recurrence root the skewness needs, so the two together cost only one engine pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the STDDEV pin exists and one square-root run is scheduled in the tail. It pulls in the variance datapath even when the VARIANCE pin is off, and it shares its root with the skewness. Default YES.

Default: YES

Options: NO YES

STDDEV Integer Bits STDDEV_BitsInt

Number of INTEGER bits of the STDDEV output, in BIN units (the sign, when present, uses one of them).

Integer bits of the STDDEV output, in BIN units.

Default: 16

Range: 1 – 64

STDDEV Fractional Bits STDDEV_BitsFract

Number of FRACTIONAL bits of the STDDEV output, in BIN units, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of the STDDEV output. Total width 2..64.

Default: 8

Range: 0 – 64

STDDEV Sign STDDEV_Sign

Select whether the STDDEV output, in BIN units is signed (two’s complement) or unsigned.

SIGNED or UNSIGNED. A standard deviation is never negative, so UNSIGNED buys one bit.

Default: UNSIGNED

Options: UNSIGNED SIGNED

Enable SKEWNESS EnableSkewness

YES: the SKEWNESS (mu3 / sigma^3, dimensionless; negative = a left tail). It pulls in the third central sum and TWO more serial divisions pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the SKEWNESS pin exists. It pulls in the third central sum and two more serial divisions plus the square root, so it lengthens the tail noticeably. It is also one of the two settings that make Moment Implementation mean anything: the third central sum is what puts wide multipliers in the per-bin path. Default NO.

Default: NO

Options: NO YES

SKEWNESS Integer Bits SKEWNESS_BitsInt

Number of INTEGER bits of the SKEWNESS output (the sign, when present, uses one of them).

Integer bits of the SKEWNESS output. Real skewness is small - a few units - so 6 bits is generous.

Default: 6

Range: 1 – 64

SKEWNESS Fractional Bits SKEWNESS_BitsFract

Number of FRACTIONAL bits of the SKEWNESS output, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of the SKEWNESS output. This is where the resolution goes.

Default: 10

Range: 0 – 64

SKEWNESS Sign SKEWNESS_Sign

Select whether the SKEWNESS output is signed (two’s complement) or unsigned.

Use SIGNED: the sign is the whole point (left tail vs right tail).

Default: SIGNED

Options: UNSIGNED SIGNED

Enable KURTOSIS EnableKurtosis

YES: the KURTOSIS (mu4 / sigma^4). It pulls in the FOURTH central sum, which is the widest accumulator in the block, and two more serial divisions pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the KURTOSIS pin exists. It pulls in the fourth central sum - the widest accumulator in the block - and two more serial divisions. It also pulls in the third central sum, which the offset correction $\mu_4 = a_4 - 4ea_3 + 6e^2a_2 - 3e^4$ needs, whether or not SKEWNESS is enabled. Together with SKEWNESS it is what makes Moment Implementation matter. Default NO.

Default: NO

Options: NO YES

Kurtosis Definition KurtosisDefinition

EXCESS: kurtosis - 3, so a Gaussian reads 0 and the sign tells you directly whether the distribution is heavier or lighter tailed than normal. RAW: the plain fourth standardised moment (a Gaussian reads 3).

EXCESS (default): kurtosis - 3, so a Gaussian reads 0 and the sign tells you directly whether the distribution is heavier or lighter tailed than normal. RAW: the plain fourth standardised moment (a Gaussian reads 3).

Default: EXCESS

Options: RAW EXCESS

KURTOSIS Integer Bits KURTOSIS_BitsInt

Number of INTEGER bits of the KURTOSIS output (the sign, when present, uses one of them).

Integer bits of the KURTOSIS output. With EXCESS a Gaussian is 0 and a very peaked distribution a few tens.

Default: 8

Range: 1 – 64

KURTOSIS Fractional Bits KURTOSIS_BitsFract

Number of FRACTIONAL bits of the KURTOSIS output, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of the KURTOSIS output.

Default: 8

Range: 0 – 64

KURTOSIS Sign KURTOSIS_Sign

Select whether the KURTOSIS output is signed (two’s complement) or unsigned.

Use SIGNED with the EXCESS definition, which is negative for a flat distribution.

Default: SIGNED

Options: UNSIGNED SIGNED

Enable OCC0 EnableThreshold0

YES: the OCC0 (how many counts sit at or above threshold bin THR0) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the THR0 input and the OCC0 output exist - a region-of-interest counter with a runtime threshold. Needs the second pass. Default NO.

Default: NO

Options: NO YES

THR0 default bin Threshold0Default

Value the THR0 input takes when it is left unconnected.

Bin the THR0 input takes when left unconnected. Must be within the histogram, i.e. below $2^{\text{MaxBinsExponent}}$.

Default: 0

Range: 0 – 65535

Enable OCC1 EnableThreshold1

YES: the OCC1 (how many counts sit at or above threshold bin THR1) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the THR1 input and the OCC1 output exist. Default NO.

Default: NO

Options: NO YES

THR1 default bin Threshold1Default

Value the THR1 input takes when it is left unconnected.

Bin the THR1 input takes when left unconnected.

Default: 0

Range: 0 – 65535

Enable OCC2 EnableThreshold2

YES: the OCC2 (how many counts sit at or above threshold bin THR2) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the THR2 input and the OCC2 output exist. Default NO.

Default: NO

Options: NO YES

THR2 default bin Threshold2Default

Value the THR2 input takes when it is left unconnected.

Bin the THR2 input takes when left unconnected.

Default: 0

Range: 0 – 65535

Enable OCC3 EnableThreshold3

YES: the OCC3 (how many counts sit at or above threshold bin THR3) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the THR3 input and the OCC3 output exist. Default NO.

Default: NO

Options: NO YES

THR3 default bin Threshold3Default

Value the THR3 input takes when it is left unconnected.

Bin the THR3 input takes when left unconnected.

Default: 0

Range: 0 – 65535

Enable BIN_SATURATED EnableBinSaturated

YES: the BIN_SATURATED (a bin hit its maximum count during this frame and STOPPED counting). WITHOUT THIS EVERY OTHER STATISTIC IS SILENTLY WRONG once a bin saturates – leave it on pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the BIN_SATURATED pin exists. Without it every other statistic is silently wrong once a bin saturates. It costs one flip-flop. Leave it on. Default YES.

Default: YES

Options: NO YES

Enable SAT_BINS EnableSatBins

YES: the SAT_BINS (how many bins are AT the maximum count) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the SAT_BINS pin exists - how many bins are at the maximum count, i.e. how badly the histogram is clipped from above. Default NO.

Default: NO

Options: NO YES

Enable UNDERFLOW EnableUnderflow

YES: the UNDERFLOW (samples that fell below the BASE and were clamped into bin 0) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the UNDERFLOW pin exists - samples clamped into bin 0. Together with OVERFLOW this is what distinguishes a clipped distribution from a real one. Default YES.

Default: YES

Options: NO YES

Enable OVERFLOW EnableOverflow

YES: the OVERFLOW (samples that fell above MAX_BIN and were clamped into it). With UNDERFLOW this is what distinguishes a clipped distribution from a real one pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the OVERFLOW pin exists - samples clamped into MAX_BIN. Default YES.

Default: YES

Options: NO YES

Enable NONEMPTY_BINS EnableNonEmpty

YES: the NONEMPTY_BINS (the support size: how many bins are not zero). One comparator, and it tells you instantly whether the binning is sensible pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the NONEMPTY_BINS pin exists - the support size, one comparator. Default NO.

Default: NO

Options: NO YES

Enable LOST EnableLost

YES: the LOST (samples the block refused: the FREEZE dead time, and the cold clear after reset). Free in LIVE and DOUBLE mode, where it can only count the cold clear pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the LOST pin exists - samples the block refused (the FREEZE dead time, and the cold clear after reset). In LIVE and DOUBLE mode it can only count the cold clear. Default NO.

Default: NO

Options: NO YES

Enable FWHM EnableFWHM

YES: the FWHM (full width at half maximum, in BINS: the distance between the first bin below MODE_COUNT/2 on each side of the mode). Two threshold crossings, no interpolation pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the FWHM pin exists. Two comparators and two registers; it pulls in the mode registers and the second pass. The comparison is $2H_k < \text{MODE_COUNT}$, so there is no division. Default NO.

Default: NO

Options: NO YES

Enable FWTM EnableFWTM

YES: the FWTM (full width at TENTH maximum, in BINS). Same two comparators with a different constant; FWTM/FWHM is the standard peak-tailing figure pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the FWTM pin exists - the same machinery with $10H_k$ instead of $2H_k$. FWTM/FWHM is the standard peak-tailing figure. Default NO.

Default: NO

Options: NO YES

Enable PEAK_POS EnablePeakPos

YES: the PEAK_POS (the sub-bin peak position by parabolic interpolation on MODE_BIN-1, MODE_BIN, MODE_BIN+1). One division, and it removes the bin quantisation from the peak position pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the PEAK_POS pin exists - the sub-bin mode position by parabolic interpolation. One tail division, and it removes the bin quantisation from the peak position, which is usually the dominant error on a narrow peak. Default NO.

Default: NO

Options: NO YES

PEAK_POS Integer Bits PEAK_POS_BitsInt

Number of INTEGER bits of the PEAK_POS output, in BIN units (the sign, when present, uses one of them).

Integer bits of the PEAK_POS output. It is an absolute bin index plus a fraction, so this must hold the largest bin index: at least MaxBinsExponent usable integer bits. The property validator refuses a configuration where it cannot.

Default: 16

Range: 1 – 64

PEAK_POS Fractional Bits PEAK_POS_BitsFract

Number of FRACTIONAL bits of the PEAK_POS output, in BIN units, i.e. the bits to the right of the binary point. Total width = integer + fractional bits, and must not exceed 64.

Fractional bits of PEAK_POS. This is the sub-bin resolution you are paying the division for.

Default: 8

Range: 0 – 64

PEAK_POS Sign PEAK_POS_Sign

Select whether the PEAK_POS output, in BIN units is signed (two’s complement) or unsigned.

SIGNED or UNSIGNED. The position is never negative, so UNSIGNED buys one bit.

Default: UNSIGNED

Options: UNSIGNED SIGNED

Enable Read Bus EnableReadBus

YES: the the RD_ADDR / RD_DATA / RD_DV bus, which reads individual bins from outside. RD_DATA answers one clock after RD_ADDR and RD_DV says so; the bus stands back whenever the scanner or (except in DOUBLE mode) the binner is using the memory, so poll RD_DV rather than assuming a fixed latency pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the RD_ADDR / RD_DATA / RD_DV bus exists, which reads individual bins from outside - this is how you get the whole spectrum out, not just its statistics. The bus shares the histogram read port and stands back when the memory is busy, so poll RD_DV. Default NO.

Default: NO

Options: NO YES

Enable BUSY EnableBusy

YES: the BUSY (accumulating, or scanning, or clearing after reset; its last high clock is the OUT_DV pulse) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the BUSY pin exists. Default NO.

Default: NO

Options: NO YES

Enable ACCUMULATING EnableAccumulating

YES: the ACCUMULATING (a frame is open and taking samples) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the ACCUMULATING pin exists. Default NO.

Default: NO

Options: NO YES

Enable SCANNING EnableScanning

YES: the SCANNING (the analyser is walking the histogram or finishing its arithmetic). In LIVE mode this is how you SEE a stalled scan pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the SCANNING pin exists. In LIVE mode this is how you see a stalled scan. Default NO.

Default: NO

Options: NO YES

Enable SCAN_POS EnableScanPos

YES: the SCAN_POS (which bin the scanner is on – scan progress) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the SCAN_POS pin exists - which bin the scanner is on. Default NO.

Default: NO

Options: NO YES

Enable SAMPLE_COUNT EnableSampleCount

YES: the SAMPLE_COUNT (samples accumulated so far in the current frame; it HOLDS the final count through the scan and past OUT_DV) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it. Note the internal dependencies the core resolves for you: the variance, the standard deviation, the skewness and the kurtosis all need the mean; the skewness needs the standard deviation; FWHM, FWTM and PEAK_POS all need the mode; and any of the quantiles, the occupancies or the moments turns the scan into TWO passes.

YES: the SAMPLE_COUNT pin exists - a fixed 32 bit count that holds the frame length through the scan and past OUT_DV. Default NO.

Default: NO

Options: NO YES

Rounding Rounding

ROUND: round to nearest when a result has to be requantised into a coarser output format. TRUNCATE: drop the bits (cheaper, adds a negative bias).

ROUND: round to nearest when a result has to be requantised into a coarser output format. TRUNCATE: drop the bits (cheaper, adds a negative bias). Only the derived outputs are affected - counts and bin indices are exact either way.

Default: ROUND

Options: TRUNCATE ROUND

Saturation EnableSaturation

YES: clip to the largest representable value of each output format (symmetric for signed formats). NO: wrap around.

YES: clip to the largest representable value of each output format (symmetric bounds for signed formats). NO: wrap around. Only matters when an output format is too narrow for the value.

Default: YES

Options: NO YES

Moment Implementation Implementation

How the per-bin moment products of SKEWNESS and KURTOSIS are built. SERIAL: one shared multiplier driven through the six products over several clocks per bin – typically three to four times fewer DSP48s, at the cost of a longer scan (the scan happens once per frame, so this is almost always the right trade). PIPELINED: six parallel multipliers, one bin per clock, shortest scan. BOTH PRODUCE BIT-IDENTICAL RESULTS – only the latency differs. This setting does NOTHING unless SKEWNESS or KURTOSIS is enabled: with MEAN / VARIANCE / STDDEV alone the per-bin path is two multiplies and there is nothing to fold.

How the per-bin moment products of SKEWNESS and KURTOSIS are built.

SERIAL (default): one shared multiplier is driven through the six products over several clocks per bin - typically three to four times fewer DSP48 slices, at the cost of a longer scan (4 clocks per bin with one shape moment enabled, 6 with both). The scan runs once per frame, so this is almost always the right trade.

PIPELINED: six parallel multipliers, one bin per clock, shortest scan and the most DSPs.

The two are BIT IDENTICAL - only the latency differs, and the compiler log prints the scan length for both. This setting does nothing unless SKEWNESS or KURTOSIS is enabled: with MEAN / VARIANCE / STDDEV alone the per-bin path is only two multiplies and there is nothing to fold.

Default: SERIAL

Options: SERIAL PIPELINED

Reading the results

Every enabled output is written together in the same clock and flagged by a one-clock OUT_DV pulse. Between pulses they hold, so a downstream register can latch them on OUT_DV or a CPU can read them at leisure.

An output that is not enabled has no pin and no logic: it is removed by the preprocessor before synthesis, so the symbol and the generated entity agree by construction. Some outputs pull others in internally, which costs logic but never a pin:

enabling also builds
VARIANCE, STDDEV, SKEWNESS, KURTOSIS the mean division
SKEWNESS the standard deviation (the square root)
FWHM, FWTM, PEAK_POS the mode registers
any quantile, occupancy or moment the second pass (roughly doubles the scan)

The read bus

With Enable Read Bus on, RD_ADDR presents a bin index and RD_DATA answers one clock later with RD_DV high. The bus shares the histogram’s read port, so it stands back whenever the scanner - or, except in DOUBLE mode, the binner - is using the memory. Poll RD_DV; do not assume a fixed latency. In DOUBLE mode the bus reads the buffer that is not being filled, i.e. the one the scanner walks, so it only ever has to wait for the scanner.

This is how you get the whole spectrum out, not just its statistics: sweep RD_ADDR from 0 to MAX_BIN and collect RD_DATA whenever RD_DV is high.

Status outputs and their exact edges

Every output of this core is a register, so each is seen one clock after the event that sets it.

  • ACCUMULATING is high while a frame is open - from the clock after its first sample is accepted to the clock after its last.
  • SCANNING is high from the clock after a frame is handed over until the scan and its arithmetic are finished. In LIVE mode this is how you see a stalled scan: SCANNING stays high while SCAN_POS does not move.
  • BUSY = accumulating, or scanning, or clearing after reset. Its last high clock is the OUT_DV pulse - the two fall together.
  • SCAN_POS is the bin the scanner is working on: scan progress.
  • SAMPLE_COUNT is the number of samples accumulated so far in the current frame. It is not cleared at the frame end: it holds the final count through the whole scan and past OUT_DV, so on the OUT_DV clock it reads the length of the frame whose result is being presented.

Reset and the cold clear

A block RAM comes up undefined, so after reset the block sweeps every bin writing zero before it accepts anything. That takes $2^{\text{Max Bins (exponent)}}$ clocks - 1024 bins is 1024 clocks - and BUSY is high throughout. Samples arriving during the cold clear are counted in LOST. This is not optional housekeeping: without it the first histogram would be whatever was left in the RAM.

Degenerate cases, all forced explicitly

  • A single occupied bin. The variance, the standard deviation, the IQR, the skewness and the kurtosis are all 0 (there is no spread, and a distribution with no spread has no shape). MEDIAN, MODE_BIN, MIN_BIN and MAX_BIN_OCC are that bin, RANGE is 0.
  • A peak with no crossing. If no bin either side of the mode falls below half (or a tenth of) the maximum, FWHM/FWTM use the histogram edges - the honest answer for a peak that fills the whole range.
  • No parabolic vertex. PEAK_POS falls back to the plain MODE_BIN when the mode sits on an edge bin, or when the three-point curvature $2H_m - H_{m-1} - H_{m+1}$ is not strictly positive (a flat top - there is no vertex to find). The offset is clamped to $\pm\tfrac12$ bin, because a parabolic vertex is by construction inside the central bin; a peak leaning left gives a negative offset, one leaning right a positive one.
  • Total zero. Every statistic reads 0, so TOTAL == 0 is the flag that says “nothing was measured”. Note that the frame mechanism cannot actually produce this - a frame ends after PERIOD accepted samples, so it always holds at least PERIOD counts - it is a defensive guard.

Accuracy

Everything that is a count or a bin index is exact: total, min/max bin, range, mode, mode count, median, quantiles, IQR, occupancies, non-empty and saturated bin counts, underflow, overflow, lost, FWHM and FWTM involve nothing but an add and a compare.

The derived quantities - mean, variance, stddev, skewness, kurtosis, peak position - are carried internally with a fractional width derived from the widest output format you asked for, plus four guard bits, and every division and square root floors. In the regression they land within one to a few LSB of the exactly-rounded value, with the bound propagated from that internal precision rather than measured. Give an output a couple of extra fractional bits if you care about its last one.