Block Preview

Introduction

Principle of Operation

The MCA block is the classic Sci-Compiler pulse-height analysis chain. A single 16-bit ADC stream goes in, an energy word plus a data-valid strobe come out. Internally it is four stages on one clock, one sample per clock:

  1. Fast trapezoidal trigger — a short trapezoid (TRIG_K, TRIG_M) whose derivative is compared against THRS; the peak of that derivative fires TRIGGER_OUT.
  2. Slow trapezoidal shaper — a long trapezoid (TRAP_K, TRAP_M) with integrated pole-zero deconvolution (DECONV_M) and an output gain (TRAP_GAIN).
  3. Baseline restorer — a moving average of the shaper output over $2^{\mathrm{BL_LEN}}$ samples, frozen for BL_INIB samples after every trigger.
  4. Energy sampler — samples (shaper − baseline) SAMPLE_POS samples after the trigger and raises ENERGY_DV.

What makes this block different from its two siblings

The MCA family in this plugin has three members that do the same job with very different engineering trade-offs. All three are built from the same Vivado/Vitis HLS C sources, but only one of them runs HLS on your machine:

MCA (this page) MCA HLS MCA Short Signal
internal name mcahp mcahp_test MCA_FAST
HLS tool-chain needed to compile no yes no
RTL origin pre-generated Vivado HLS 2017.4 netlist, shipped in the plugin Vitis HLS run per project from psa_trigger.cpp pre-generated netlist (MCAFAST.vhd)
slow-shaper depth 512 / 1024 / 2048 (one property) 128 … 16384 512 fixed
trigger-shaper depth 128, fixed 128 … 16384 64 fixed
baseline depth 2048, fixed 128 … 16384 512 fixed
threshold width 32 bit 32 bit 16 bit
time stamping (TIMETAG / TIMESTAMP) no yes no
pile-up rejection no no yes (PUR_MODE, PUR_INIB, PUR)
trigger inhibit (TR_RESET) no yes no
delayed input monitor no DATA_OUT INPUT_SIGNAL
declared pipeline latency 13 13 17

Pick this block when you want the standard chain and you do not want a Vitis HLS installation in the build path (it also makes remote/cloud builds and rebuilds on a plain Vivado install deterministic — the netlist is already in the plugin, so two builds of the same project give bit-identical logic).

Pick MCA HLS instead when you need shaping longer than 2048 samples, a trigger trapezoid longer than 128 samples, an independently sized baseline buffer, hardware time stamps, or the trigger-inhibit input.

Pick MCA Short Signal instead when the pulses are short, FPGA area is the constraint, or you need pile-up rejection.

Pin Description

DATA_IN Input 16 bit BIT VECTOR
ADC samples, 16 bit, one per clock. This is the raw preamplifier waveform. The core is fixed at 16 bit: a narrower ADC must be left-aligned or zero/sign-extended upstream.
Default: Must be connected
POLARITY Input 1 bit BIT
Pulse polarity. 1 = positive-going pulses, 0 = negative-going. Unconnected it is driven to '1'.
Default: 1
OFFSET Input 16 bit BIT VECTOR
Digital offset added to the input before shaping, 16 bit. Use it to bring a pedestal to zero.
THRS Input 32 bit BIT VECTOR
Trigger threshold, 32 bit, compared against the derivative of the fast trapezoid — not against the raw signal, so it is insensitive to baseline drift. Unconnected it is driven to x"00000100".
Default: 256
TRIG_K Input 16 bit BIT VECTOR
Fast (trigger) trapezoid rise, in samples. Must stay below 128 in every Shaping Size variant — the trigger delay RAMs are 128 words deep in all three netlists. Unconnected it is driven to x"0006".
Default: 6
TRIG_M Input 16 bit BIT VECTOR
Fast (trigger) trapezoid second delay, in samples; the trigger flat top is |TRIG_M − TRIG_K|. Same 128-sample ceiling as TRIG_K. Unconnected it is driven to x"0008".
Default: 8
TRAP_K Input 16 bit BIT VECTOR
Slow (energy) trapezoid rise, in samples. Longer = better noise filtering and worse rate capability. Must stay below Shaping Size. Unconnected it is driven to x"0100" (256).
Default: 256
TRAP_M Input 16 bit BIT VECTOR
Slow trapezoid second delay, in samples. Flat top = |TRAP_M − TRAP_K|; make it long enough to cover the charge-collection spread of the detector. Must stay below Shaping Size. Unconnected it is driven to x"010A" (266).
Default: 266
DECONV_M Input 24 bit BIT VECTOR
Pole-zero (deconvolution) coefficient, 24 bit, scaled by 256: M = 256 / (exp(Ts/tau) − 1). 0 disables the deconvolution. Unconnected it is driven to x"007C80".
Default: 31872
TRAP_GAIN Input 24 bit BIT VECTOR
Energy output gain, Q8.16 (0x010000 = ×1.0), 24 bit. Use it to map the energy range onto the number of spectrum bins you want. Unconnected it is driven to x"010000".
Default: 65536
BL_LEN Input 4 bit BIT VECTOR
Baseline averaging exponent: the moving average runs over $2^{\rm BL_LEN}$ samples. The baseline buffer is 2048 words deep in all three variants, so values above 11 exceed the buffer. Unconnected it is driven to x"8" (256-sample average).
Default: 8
BL_INIB Input 16 bit BIT VECTOR
Baseline inhibit, in samples: after every trigger the moving average is frozen for this many samples (and BL HOLD is high). Must be longer than the whole trapezoid, otherwise pulse tails pollute the baseline and the peak position moves with count rate. Unconnected it is driven to x"1000".
Default: 4096
SAMPLE_POS Input 16 bit BIT VECTOR
Energy sampling position, in samples after the trigger. Aim for the middle of the flat top. Unconnected it is driven to x"0108" (264).
Default: 264
TRG_GAIN Input 16 bit BIT VECTOR
Gain of the core’s second deconvolution stage (e_G2_V). That stage’s coefficient input has no pin on this symbol and is permanently 0, so the effect of this pin alone is not determined from the sources. Leave it unconnected; it then defaults to x"0000".
Default: 0
RUN_CFG Input 1 bit BIT
Run (1) / configure (0). Low holds the whole chain in reset: pointers, accumulators and delay lines cleared, no energy produced. Set every parameter pin first, then raise it, then allow the delay lines to fill before trusting the spectrum.
EXT_TRIGGER Input 1 bit BIT
External trigger input, combined with the internal trigger according to EXT_TRIGGER_SELECTOR.
EXT_TRIGGER_SELECTOR Input 4 bit BIT VECTOR
Trigger source selector, 4 bit, driving the core’s GIN_SELECT_V port. 0 selects the internal trigger; the other codes combine it with EXT_TRIGGER. The exact coding of values above 0 was not established from the sources shipped with this block.
CLK Input 1 bit BIT
Clock. Defaults to the project acquisition clock when left unconnected. The whole chain is synchronous to it and consumes exactly one DATA_IN sample per rising edge.
Default: Default Board Clock
RESET Input 1 bit BIT
Reset. Defaults to the project global reset when left unconnected.
Default: Default Board Reset
ENERGY Output 32 bit BIT VECTOR
Energy word, 32 bit signed: (shaper − baseline) captured SAMPLE_POS samples after the trigger, scaled by TRAP_GAIN. Latch it on ENERGY DV.
ENERGY_STROBE Output 1 bit BIT
Energy data valid (ENERGY DV on the canvas). One clock high per accepted event. Wire it to the DV of a Spectrum or List endpoint.
TRIGGER_OUT Output 1 bit BIT
Trigger, one clock high when the fast filter fires. Useful for rate counters and coincidence logic; it fires even when the event is later discarded.
BASELINE_HOLD Output 1 bit BIT
High while the baseline average is frozen (BL_INIB window after a trigger). A permanently high BL HOLD means BL_INIB is too long for the current rate and the baseline has stopped updating.
TRIGGER_DELTA_MON Output 32 bit BIT VECTOR
Monitor: the derivative signal the trigger compares to THRS. Scope this pin to pick a threshold.
TRIGGER_TRAP_MON Output 32 bit BIT VECTOR
Monitor: the fast (trigger) trapezoid output.
TRAP_MON Output 32 bit BIT VECTOR
Monitor: the slow (energy) trapezoid output, before baseline subtraction. Scope this to verify the pole-zero setting — a correct DECONV_M gives a flat top with no undershoot after it.
TRAP_BL_MON Output 32 bit BIT VECTOR
Monitor: (slow trapezoid − baseline), i.e. exactly the quantity the energy sampler captures. Scope this together with TRIGGER to place SAMPLE_POS.
BL_MON Output 32 bit BIT VECTOR
Monitor: the current baseline value.

Properties

Property window

Shaping Size ShapingSize

Set the maximum number of samples supported by the MCA. This will affect the trapezoidal shaper and the baseline restorer

Depth of the slow-shaper and energy-sampler delay memories, and therefore the largest usable TRAP_K / TRAP_M.

value slow shaper / energy sampler trigger shaper baseline
512 512 128 2048
1024 1024 128 2048
2048 2048 128 2048

Changing it swaps the whole pre-generated netlist (mcahp_512/1024/2048), so it rebuilds the symbol and re-runs synthesis. Contrary to the property tooltip it does not change the baseline restorer, which is 2048 words in every variant, and it does not change the trigger trapezoid, which is 128 words in every variant.

All MCA blocks in one project must use the same value — the netlist is always written to pcores/mcahp.vhd.

Default: 2048

Default: 2048

Options: 512 1024 2048

⚙️ Detailed Operation

Where the RTL comes from

CompileHDL does not invoke any synthesis tool. It copies one of three embedded VHDL files into the project’s pcores/ directory and instantiates the matching top entity:

Shaping Size file written to pcores/mcahp.vhd entity instantiated
512 mcahp_512.vhd MCAHP_512
1024 mcahp_1024.vhd MCAHP_1024
2048 mcahp_2048.vhd MCAHP_2048

Each file is RTL emitted by Vivado HLS 2017.4. The generator report is still embedded in the netlist as a CORE_GENERATION_INFO attribute; for the 2048 variant it reads:

  MCAHP_2048,hls_ip_2017_4,{HLS_INPUT_TYPE=cxx, HLS_INPUT_FIXED=1,
  HLS_INPUT_PART=xc7k160tfbg676-3, HLS_INPUT_CLOCK=12.500000,
  HLS_INPUT_ARCH=pipeline, HLS_SYN_CLOCK=10.402286,
  HLS_SYN_LAT=12, HLS_SYN_TPT=1,
  HLS_SYN_MEM=9, HLS_SYN_DSP=6, HLS_SYN_FF=2343, HLS_SYN_LUT=2822}
  

So the core was closed at 12.5 ns (80 MHz) target, 10.4 ns achieved on a Kintex-7 −3, it is fully pipelined at one sample per clock, and it costs roughly 9 BRAM / 6 DSP / 2343 FF / 2822 LUT. Those figures are for the 2048 variant; the 512 and 1024 variants differ only in the depth of two RAMs (see below), so the DSP/FF/LUT cost is essentially the same and only the BRAM count shrinks.

What Shaping Size really changes

The delay memories inside the netlist were read directly from the three files. Only two of them scale:

delay memory 512 variant 1024 variant 2048 variant
slow trapezoid (HLSDPP_trapezio) 512 1024 2048
energy sampler (HLSDPP_energysamp…) 512 1024 2048
baseline restorer (HLSDPP_baseline_ribs) 2048 2048 2048
fast trigger trapezoid — three RAMs 128 128 128
input alignment delay (MCAHP_*_delay1…) 256 256 256

This has three practical consequences that the property text does not mention:

  • TRAP_K and TRAP_M must stay below Shaping Size — they are used as read-pointer offsets into the two scaling RAMs, and an offset larger than the RAM depth aliases onto the wrong sample instead of raising an error.
  • TRIG_K and TRIG_M must stay below 128 in every variant. Choosing Shaping Size = 2048 does not buy you a longer trigger trapezoid. If you need one, use MCA HLS.
  • The baseline ring buffer is always 2048 words, so BL_LEN is usable up to 11 ($2^{11} = 2048$) regardless of Shaping Size — even though the property description claims Shaping Size “will affect the trapezoidal shaper and the baseline restorer”. It does not affect the baseline restorer.

Trapezoidal filter and pole-zero

The slow shaper is the Jordanov–Knoll recursive trapezoid with the deconvolution term folded in:

$$ d^{k}[n] = x[n] - x[n-k] $$ $$ d^{k,m}[n] = d^{k}[n] - d^{k}[n-m] $$ $$ p[n] = p[n-1] + d^{k,m}[n] $$ $$ s[n] = s[n-1] + \bigl(256,p[n] + M,d^{k,m}[n]\bigr) $$

with $k$ = TRAP_K, $m$ = TRAP_M, $M$ = DECONV_M. The rise time of the trapezoid is $\min(k,m)$ samples and the flat top is $|k-m|$ samples, so the usual setting is TRAP_M = TRAP_K + flat-top (the default pair 0x0100 / 0x010A is a 256-sample rise with a 10-sample flat top).

DECONV_M is a fixed-point coefficient scaled by 256, which is why the classic pole-zero formula carries that factor:

$$ M = \frac{256}{e^{T_s/\tau} - 1} $$

where $T_s$ is the sample period and $\tau$ the preamplifier decay constant. Set DECONV_M to 0 to disable pole-zero cancellation.

TRAP_GAIN is a Q8.16 multiplier applied to the shaper output (0x010000 = ×1.0).

Baseline restorer and energy sampling

The baseline is the moving average of the shaper output over $2^{\rm BL_LEN}$ samples. On every trigger the average is frozen and BASELINE_HOLD goes high for BL_INIB samples, so BL_INIB must cover the whole pulse (rise + flat top + fall) or the tail of the pulse will be averaged into the baseline and the spectrum will drift with rate.

SAMPLE_POS is the distance, in samples, from the trigger to the point where (shaper − baseline) is captured. It should land in the middle of the flat top:

$$ \mathrm{SAMPLE_POS} \approx \mathrm{TRAP_K} + \frac{\mathrm{TRAP_M} - \mathrm{TRAP_K}}{2} $$

Configure / run

RUN_CFG is the master enable. With RUN_CFG = 0 the chain is held in its configuration state: accumulators, delay lines and pointers are cleared and no energy is produced. Bring all the parameter pins to their final values first, then raise RUN_CFG. The HLS cores contain a pre-roll counter that discards the first passes through the delay lines after RUN_CFG rises, so the first valid energies appear only after the delay lines have filled — allow a few thousand samples of dead time after every RUN_CFG 0→1 edge before trusting the spectrum.

Software interface

This block declares no memory-mapped registers: CompileMMC and CompileSDK are empty. Everything is controlled through pins. The usual pattern is to drive the parameter pins from Register blocks (so the SciSDK can write them) and to feed ENERGY / ENERGY_DV into a Spectrum, List or Oscilloscope endpoint, which is where the SciSDK-visible registers actually live.

Realistic wiring

  ADC ─► DATA_IN            ENERGY ───► Spectrum / List endpoint
      POLARITY            ENERGY DV ─┘
      OFFSET              TRIGGER ───► counter / coincidence logic
 Reg ─► THRS TRIG_K TRIG_M      BL HOLD ─► (diagnostics)
 Reg ─► TRAP_K TRAP_M DECONV_M TRAP_GAIN
 Reg ─► BL_LEN BL_INIB SAMPLE_POS
 Reg ─► RUN(1) CFG(0)    TRAP MON / TRAP-BL MON / BL MON ─► Oscilloscope
  

The five 32-bit monitor outputs (TRIGGER_DELTA_MON, TRIGGER_TRAP_MON, TRAP_MON, TRAP_BL_MON, BL_MON) exist to be wired into an oscilloscope endpoint while you tune the filter; they can all be left unconnected in production.

Timing

quantity value
throughput 1 sample per clock (HLS_SYN_TPT=1)
pipeline latency declared on the symbol 13 clocks
pipeline latency in the HLS report inside the netlist 12 clocks
trigger → ENERGY_DV SAMPLE_POS samples (plus the pipeline latency)

The symbol latency (13) is what the Sci-Compiler scheduler uses to align this block with parallel paths; the HLS report figure (12) is the core’s own measured latency. Use 13 when you have to compensate a parallel branch by hand.

Resources & Timing

  • Latency: 13 clocks declared on the symbol (the HLS report embedded in the netlist says 12); trigger to ENERGY DV is SAMPLE_POS samples on top of that

  • Throughput: 1 sample per clock (HLS_SYN_TPT = 1)

  • Figures reported by Vivado HLS 2017.4 for the 2048 variant on xc7k160tfbg676-3: 9 BRAM, 6 DSP, 2343 FF, 2822 LUT.
  • Timing was closed at a 12.5 ns target with a 10.4 ns estimate, i.e. the core is comfortable at 80 MHz and was not characterised above ~96 MHz.
  • The 512 and 1024 variants differ only in the depth of two RAMs; expect the same DSP/FF/LUT cost and fewer BRAMs.
  • No memory-mapped registers are generated (CompileMMC / CompileSDK are empty) — the software interface is whatever endpoint you connect ENERGY to.