Xilinx
TM
HLS
Block Preview

Introduction

Per lane, over each block of N samples:

Per lane, with d = x - LEVEL: POS_AREA = sum of d where d > 0, NEG_AREA = sum of d where d < 0 (a NEGATIVE number), ABS_AREA = POS_AREA - NEG_AREA = sum |d|. On-level samples (d = 0) land in neither.

This is the time multiplexed (TM) twin of the scalar Block Area block: TM Factor independent channels packed on one wide bus, each computing the signed areas about a broadcast LEVEL of its own block of N consecutive samples. Nothing is shared between the channels except the frame.

The TM contract

  • IN is TM Factor lanes of input width bits each, lane 0 in the LOW bits (lane 0 is the oldest sample of the clock) - the same packing as every other TM block in the toolchain. Each lane is an independent channel: its own accumulators, its own result.
  • ONE shared EXP pin, ONE IN_DV, one frame: all lanes start and end their blocks on the same accepted clocks. BUSY, INTEGRATING and SAMPLE_COUNT therefore stay scalar - SAMPLE_COUNT counts per-lane samples, which are identical in every lane by construction.
  • Accumulation runs at II=1 on the packed bus, one accumulator per lane. TM Factor times the accumulator registers is the unavoidable cost of TM state.
  • The serial post-processing is ONE shared engine serving the lanes one after the other. It runs once per block, so lane-multiplexing it keeps the tail resources of the SCALAR block - no parallel engines - at the cost of tail latency x TM Factor, which is irrelevant against a whole block of samples.
  • ONE OUT_DV per block, after the LAST lane’s tail completes. All output lanes are staged as each lane finishes and committed together on the OUT_DV clock, so every packed output moves on that clock and no other.

N is a runtime input: the block size is $N = 2^{\mathrm{EXP}}$, EXP clamped to Max Block Exponent and latched on the first accepted sample of a block, so a change takes effect on the NEXT block - for every lane at once. Because N is a power of two, every division by N in this family is an exact shift.

When to use this instead of TM Factor scalar blocks

One TM block and TM Factor scalar blocks compute the same numbers. The TM block pays the per-lane accumulators (unavoidable either way) but shares ONE frame, ONE control FSM and ONE serial tail across all lanes - the more expensive the scalar tail, the more it saves. The price is tail latency (TM Factor times the scalar tail) and the coupling of the frame: all lanes must share the same block length and the same sample cadence. Channels that need different block sizes need scalar blocks.

Pin Description

IN Input (IN_BitsInt + IN_BitsFract) * TMFactor bit TM
Packed TM sample bus: TM Factor lanes of input width bits, lane 0 in the LOW bits. Each lane is an independent channel, accumulated only on the clocks where IN_DV is high.
Default: Must be connected
IN_DV Input 1 bit BIT
Per-sample qualifier for ALL lanes at once, active high, the only qualifier this block has (no CE pin, by family rule - gate this instead). Unconnected defaults to ‘1’.
EXP Input 6 bit BIT VECTOR
Block size exponent, shared by every lane: each lane’s block is 2^EXP samples of THAT lane. 6 bits, clamped to Max Block Exponent, latched on the first accepted sample of a block. Unconnected defaults to 10 (N = 1024).
LEVEL Input IN_BitsInt + IN_BitsFract bit BIT VECTOR
ONE broadcast baseline for every lane, INPUT lane format, latched per block. Unconnected ties to 0.
POS_AREA Output (POS_AREA_BitsInt + POS_AREA_BitsFract) * TMFactor bit TM
Packed per-lane positive areas. Present when Enable POS_AREA = YES.
NEG_AREA Output (NEG_AREA_BitsInt + NEG_AREA_BitsFract) * TMFactor bit TM
Packed per-lane negative areas (each lane is a NEGATIVE number - keep the format SIGNED). Present when Enable NEG_AREA = YES.
OUT_DV Output 1 bit BIT
ONE one-clock pulse per block, L clocks after the N-th sample was accepted - after the LAST lane’s tail completed. Every packed output updates on this clock and on no other.
ABS_AREA (ABS_AREA_BitsInt + ABS_AREA_BitsFract) * TMFactor bit
Packed per-lane rectified areas. Present when Enable ABS_AREA = YES.
CLK 1 bit
Clock.
RESET 1 bit
Synchronous reset: clears every lane, the shared frame and the tail.
BUSY 1 bit
Shared by all lanes: high from the first sample of a block until the LAST lane’s result is out (it covers the whole lane-multiplexed tail); its last high clock is the OUT_DV pulse. Present only when Enable BUSY = YES.
INTEGRATING 1 bit
Shared by all lanes: high only while the block is accumulating. The clock it falls on is the one where SAMPLE_COUNT always reads N. Present only when Enable INTEGRATING = YES.
SAMPLE_COUNT 1 bit
Shared by all lanes (they advance in lockstep): samples accumulated so far in the current block, 1 after the first, N after the N-th. NOT cleared at the block end; on a continuous stream it has already restarted by OUT_DV, so latch it when INTEGRATING falls. 32 bits. Present only when Enable SAMPLE_COUNT = YES.

Properties

Property window

IN Integer Bits IN_BitsInt

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

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

Default: 16

Options: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

IN Fractional Bits IN_BitsFract

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

Fractional bits of one lane of the input. 0..64, total lane width 2..64 bits. Default 0.

Default: 0

Options: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

IN Sign IN_Sign

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

SIGNED (two’s complement) or UNSIGNED lanes. Default SIGNED. Applies to every lane.

Default: SIGNED

Options: UNSIGNED SIGNED

TM Factor TMFactor

Number of INDEPENDENT time-multiplexed channels packed on the IN bus and on every result bus. Lane 0 occupies the LOW bits (lane 0 = the oldest sample of the clock), the same packing as every other TM block. All lanes share one EXP / IN_DV / frame; each lane gets its own accumulators, but the serial post-processing is ONE engine serving the lanes one after the other, so the tail latency (and the minimum usable EXP) grows with this factor.

Number of independent channels packed on the buses, 2..16. Default 4. Multiplies the IN width, every packed output width AND the serial tail length (the shared tail serves the lanes one after the other), so it also raises the minimum usable EXP.

Default: 4

Options: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Max Block Exponent MaxBlockExponent

Largest block-size exponent the accumulators are sized for: the block can be up to 2^MaxBlockExponent samples long. The EXP input is clamped to this value at run time. Raising it widens the internal accumulators, and ON THE BLOCKS WHOSE SERIAL ENGINES ARE SIZED FROM THOSE ACCUMULATORS (Coefficient of Variation, SNR, Skewness, Kurtosis, Correlation, Autocorrelation, Linear Regression) it also LENGTHENS THE SERIAL TAIL – even when the runtime EXP is small. Keep it at the largest block you actually use. The default of 20 covers blocks of up to 1048576 samples.

Largest block-size exponent the per-lane accumulators are sized for; the EXP input is clamped to it at run time. Raising it widens every lane’s accumulator. 1..31, default 20.

Default: 20

Options: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

Enable POS_AREA EnablePosArea

YES: the POS_AREA per lane (sum of the deviations above LEVEL, packed) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it.

YES: the packed POS_AREA bus exists. Default YES.

Default: YES

Options: NO YES

POS_AREA Integer Bits POS_AREA_BitsInt

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

Integer bits of ONE LANE. Default 24.

Default: 24

Options: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

POS_AREA Fractional Bits POS_AREA_BitsFract

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

Fractional bits of one lane. Default 0.

Default: 0

Options: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

POS_AREA Sign POS_AREA_Sign

Select whether the POS_AREA output (per lane) is signed (two’s complement) or unsigned.

Default UNSIGNED.

Default: UNSIGNED

Options: UNSIGNED SIGNED

Enable NEG_AREA EnableNegArea

YES: the NEG_AREA per lane (sum of the deviations below LEVEL, a NEGATIVE number, packed) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it.

YES: the packed NEG_AREA bus exists. Default YES.

Default: YES

Options: NO YES

NEG_AREA Integer Bits NEG_AREA_BitsInt

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

Integer bits of ONE LANE. Default 24.

Default: 24

Options: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

NEG_AREA Fractional Bits NEG_AREA_BitsFract

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

Fractional bits of one lane. Default 0.

Default: 0

Options: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

NEG_AREA Sign NEG_AREA_Sign

Select whether the NEG_AREA output (per lane) is signed (two’s complement) or unsigned.

Default SIGNED - each lane holds a negative number.

Default: SIGNED

Options: UNSIGNED SIGNED

Enable ABS_AREA EnableAbsArea

YES: the ABS_AREA per lane (sum |x - LEVEL|, packed) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it.

YES: the packed ABS_AREA bus exists. Default NO.

Default: NO

Options: NO YES

ABS_AREA Integer Bits ABS_AREA_BitsInt

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

Integer bits of ONE LANE. Default 24.

Default: 24

Options: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

ABS_AREA Fractional Bits ABS_AREA_BitsFract

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

Fractional bits of one lane. Default 0.

Default: 0

Options: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

ABS_AREA Sign ABS_AREA_Sign

Select whether the ABS_AREA output (per lane) is signed (two’s complement) or unsigned.

Default UNSIGNED.

Default: UNSIGNED

Options: UNSIGNED SIGNED

Enable BUSY EnableBusy

YES: the BUSY (high from the first sample of a block until its result is out – it COVERS THE SERIAL TAIL, and 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.

YES: the shared BUSY pin exists. Default NO.

Default: NO

Options: NO YES

Enable INTEGRATING EnableIntegrating

YES: the INTEGRATING (high only while the block is ACCUMULATING; it drops as soon as the N-th sample has been taken and the tail starts, so BUSY-and-not-INTEGRATING means ‘computing’) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it.

YES: the shared INTEGRATING pin exists. Default NO.

Default: NO

Options: NO YES

Enable SAMPLE_COUNT EnableSampleCount

YES: the SAMPLE_COUNT (32 bit, how many samples have been accumulated so far in the current block: 1 after the first, N after the N-th. It is NOT cleared at the block end – it holds N until the NEXT block’s first accepted sample takes it back to 1. On a CONTINUOUS stream that happens DURING the serial tail, so at OUT_DV it reads how far into the next block the input has already got, NOT N. To capture the length of the block being presented, latch SAMPLE_COUNT on the clock INTEGRATING falls – that one always reads N) pin is present. NO: the pin AND all of its logic are removed BEFORE synthesis, so nothing is paid for it.

YES: the shared 32 bit SAMPLE_COUNT pin exists. 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 at each lane’s final requantisation. TRUNCATE: drop the bits. Default ROUND.

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 each lane to its output format (symmetric for signed). NO: wrap. Default YES.

Default: YES

Options: NO YES

Accuracy, per lane

Each lane is BIT EXACT. LEVEL is ONE scalar pin, broadcast to every lane and latched per block.

Timing: the TM latency contract

OUT_DV pulses ONCE per block, L clocks after the clock on which the N-th sample was accepted, where

$$ L = 1 + \mathrm{TM} (5 clocks at the default TM Factor of 4) $$

L = 1 + \mathrm{TM} (5 clocks at the default TM Factor of 4).

The family drop rule applies with the TM tail: the tail of one block must finish before the NEXT block completes, $2^{{\mathrm{{EXP}}}} \ge L$, or the completing block’s result is silently DROPPED (no OUT_DV, accumulators unaffected, no error pin). The TM tail makes the minimum usable EXP larger than the scalar twin’s - the compiler prints both the worst-case tail and the minimum EXP in the compilation log, and the property window refuses a configuration whose minimum exceeds Max Block Exponent.

Knowing where the block is: BUSY, INTEGRATING and SAMPLE_COUNT

Identical to the scalar family, and SHARED by all lanes: INTEGRATING is high exactly while the block is accumulating (it dips one clock per block boundary on a continuous stream), BUSY also covers the (TM-long) tail and its last high clock IS the OUT_DV pulse, SAMPLE_COUNT reads 1 after the first accepted sample and N after the N-th.

SAMPLE_COUNT is NOT cleared at the block end - it holds N until the NEXT block’s first accepted sample takes it back to 1. On a CONTINUOUS stream that happens DURING the serial tail (which on a TM block is TM Factor times longer), so at OUT_DV it reads how far into the next block the input has got, NOT N. The clock that always reads N is the one INTEGRATING falls on - latch it there.

Verification

The core is regression tested by a host-side csim harness (tb/block-ops-tm/run_tb_tm.ps1) with per-lane goldens computed by gen_golden_tm.py in exact rational arithmetic ON EACH LANE’S STREAM ALONE (lanes deliberately carry different signals - the generator refuses identical lanes), plus the strongest available lane-independence check: after every run, the SCALAR twin is replayed on each lane’s stream by itself and lane k of every TM result must match it BIT FOR BIT. The status waveform is checked clock by clock, every packed output is checked to move only on OUT_DV, and 18 TM-specific mutants (shared accumulator, lane swaps, wrong-lane tail reads, early commit, drop rule) are all killed. What no host harness can prove - that Vitis accepts and schedules the core at II=1 - is stated in AGENT/block_ops.log, not silently implied.