Xilinx
HLS
Block Preview

Introduction

The Halfband Decimator (prog) block is the run-time programmable sibling of halfband_decim. It filters a complex baseband stream and decimates by exactly two, but its NumTaps coefficients are supplied live on a top-level COEFS pin rather than computed by the plugin and frozen into the VHDL.

A halfband FIR is a low-pass with its cutoff at Fs/4; at that frequency every second impulse-response tap is zero (except the centre) and the response is symmetric, so a halfband is the cheapest FIR for a 2:1 decimation. See halfband_decim for the full theory.

      IN_I ─┐                ┌── OUT_I   (rate = IN rate / 2)
    IN_Q ─┤  [ halfband ]  ├── OUT_Q
   COEFS ─┘  h[k] live     └── VALID_OUT
  

What “programmable” means here

In the fixed variant the plugin runs ComputeHalfbandCoefs(), packs the quantised taps into a constant and wires that constant to the internal coefs_packed port. In this prog variant that same port is instead exposed as a top-level input pin COEFS (NumTaps * CoefSize bits, packed little-tap-first). You drive it from fabric — a register file, a BRAM, an AXI-lite mapped word, a DMA, or another block — and can change the filter response at run time without re-synthesising.

You are responsible for computing the halfband taps yourself: quantise a unity-DC-gain, Fs/4-cutoff low-pass to signed CoefSize-bit words and concatenate them so that COEFS[(k+1)*CoefSize-1 : k*CoefSize] = signed h[k], for k = 0 .. NumTaps-1.

Pin Description

IN_I Input InputSize bit BIT VECTOR
In-phase (I) input sample at the full (input) rate. Signed, Input Bit Width bits.
Default: Must be connected
IN_Q Input InputSize bit BIT VECTOR
Quadrature (Q) input sample at the full (input) rate. Signed, Input Bit Width bits. Tie to zero to filter a real signal.
Default: Must be connected
COEFS Input NumTaps * CoefSize bit BIT VECTOR
Packed coefficient bus, NumTaps * CoefSize bits. Tap k lives in bits [(k+1)*CoefSize-1 : k*CoefSize] as a signed CoefSize-bit value. Treated as slowly-varying (ap_stable); drive it from a register file, BRAM or DMA. Supply Fs/4-cutoff, unity-DC-gain halfband taps.
Default: Must be connected
CLK Input 1 bit BIT
System clock input (the fast / input-rate clock). Default: Acquisition clock.
Default: Default Board Clock
RESET Input 1 bit BIT
HLS synchronous reset (ap_rst). Clears the delay lines and re-arms the decimation phase; does not affect COEFS. Default: Global reset.
Default: Default Board Reset
OUT_I Output InputSize + CoefSize + 8 bit BIT VECTOR
In-phase (I) decimated output. Signed, InputSize + CoefSize + 8 bits. Valid only when VALID_OUT is high.
OUT_Q Output InputSize + CoefSize + 8 bit BIT VECTOR
Quadrature (Q) decimated output. Signed, InputSize + CoefSize + 8 bits. Valid only when VALID_OUT is high.
VALID_OUT Output 1 bit BIT
Output-valid strobe. Asserted on every second input clock to mark a fresh decimated sample (output rate = input rate / 2).

Properties

Property window

Input Bit Width InputSize

Bit width of each I/Q input sample (signed).

Bit width of each signed I / Q input sample. Range 4 to 32, default 16. Changing it triggers a redesign.

Default: 16

Options: 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

Coefficient Bit Width CoefSize

Bit width of each coefficient (signed). Sets the COEFS bus width together with NumTaps.

Bit width of each signed coefficient. Choices 10, 12, 14, 16, 18, 20, 24; default 16. Sets the COEFS bus width together with NumTaps. Changing it triggers a redesign (COEFS width changes).

Default: 16

Options: 10 12 14 16 18 20 24

Number of Taps NumTaps

Number of taps. Sets the COEFS bus width together with CoefSize.

Number of filter taps (filter order = NumTaps - 1). Choices 7, 11, 15, 19, 23, 27, 31, 39, 47, 63; default 15. Sets the COEFS bus width together with CoefSize. Changing it triggers a redesign. Use a canonical halfband length of the form 4k+3.

Default: 15

Options: 7 11 15 19 23 27 31 39 47 63

Usage

Coefficient bus (COEFS)

COEFS is a single wide std_logic_vector of width NumTaps * CoefSize. Tap k occupies bit range [(k+1)*CoefSize-1 : k*CoefSize] and is a signed two’s-complement CoefSize-bit value. Inside the HLS core the bus carries an ap_stable attribute: it is sampled every clock and treated as slowly varying, so update it only when the datapath is quiescent (or accept a transient during the reload) to avoid a partially-updated tap set.

Because the taps are unknown at synthesis time, Vivado cannot prune the zero taps: the programmable variant instantiates the full NumTaps multipliers per channel. If you never need to change the response, prefer the fixed variant for the DSP saving.

Mathematical model

For each channel c in {I, Q}, at every input sample n

    acc_c[n] = sum_{k=0..NumTaps-1} h[k] * x_c[n-k]
  

and the block keeps one result out of two: y_c[m] = acc_c[2m].

Bit widths

Data is treated as signed two’s complement.

  • IN_I, IN_Q : signed InputSize bits.
  • COEFS : NumTaps * CoefSize bits (packed signed taps).
  • internal product : InputSize + CoefSize bits.
  • OUT_I, OUT_Q : signed InputSize + CoefSize + 8 bits.

The extra 8 accumulator bits (ACC_GROWTH = 8) prevent overflow of the tap sum up to 256 taps.

VALID_OUT / strobe behaviour

Identical to the fixed variant. The core runs at the input rate (II=1, a new pair every clock) and asserts VALID_OUT on every other clock to flag the decimated output samples; the output rate is therefore input rate / 2. The internal keep phase starts true after reset, so the first post-reset output is valid. Gate downstream logic on VALID_OUT.

Latency and reset

  • #pragma HLS PIPELINE II=1 : one input pair per clock.
  • 1-clock reported latency.
  • Data ports use ap_none; COEFS uses ap_stable.
  • RESET (ap_rst) clears the delay lines and re-arms the decimation phase. It does not clear COEFS, which is driven externally.

Typical applications

  • DDC 2:1 stages where the passband must be re-tuned at run time (e.g. switchable channel bandwidths).
  • Adaptive / calibrated filters whose taps are loaded from software.
  • Sharing one bitstream across products that need different responses.

Resources & Timing

  • Latency: 1 clock cycle (reported)

  • Throughput: Accepts 1 input pair per clock (II=1); emits 1 valid output pair every 2 input clocks (output rate = input rate / 2).

Implemented with Vitis HLS. Because the coefficients arrive at run time on COEFS, Vivado cannot prune zero taps: the full NumTaps multipliers per channel are instantiated (more DSPs than the fixed variant). COEFS is ap_stable — update it only when the pipeline is idle or tolerate a brief transient. Fixed 2:1 rate change is built into the block.