Xilinx
HLS
Block Preview

Introduction

The Halfband Decimator (fixed) block filters a complex baseband stream (I and Q share the same real coefficients) and drops the sample rate by a factor of two. It is the workhorse rate-reduction stage of a multistage Digital Down-Converter (DDC).

A halfband FIR is a low-pass whose cutoff is placed exactly at Fs/4 (half of Nyquist). At that special frequency the impulse response has a remarkable property: every second coefficient is zero (except the single centre tap, which equals 0.5). The response is also symmetric. So roughly half of the multiplies are trivially zero and the rest come in symmetric pairs, which makes the halfband the cheapest possible FIR for a 2:1 decimation.

      IN_I ─┐   fc = Fs/4    ┌── OUT_I   (rate = IN rate / 2)
          │  [ halfband ]  │
    IN_Q ─┘  h[even]=0     └── OUT_Q
                           └── VALID_OUT (1 every 2 in-clocks)
  

The coefficients are computed by the plugin at design time (windowed-sinc at fc = 0.25*Fs, Hamming window, DC gain normalised to 1), quantised to CoefSize signed bits and stored as a NumTaps * CoefSize bit constant in the VHDL. They are not exposed to the fabric.

For a run-time programmable-coefficient version see Component_HalfbandDecimatorProgrammable (halfband_decim_prog).

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
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. 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 on cycles where VALID_OUT is high.
OUT_Q Output InputSize + CoefSize + 8 bit BIT VECTOR
Quadrature (Q) decimated output. Signed, InputSize + CoefSize + 8 bits. Valid only on cycles where VALID_OUT is high.
VALID_OUT Output 1 bit BIT
Output-valid strobe. Asserted high on every second input clock to mark the cycles on which OUT_I/OUT_Q carry a fresh decimated sample (output rate = input rate / 2). Low on the intervening clocks.

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).

Bit width of each signed coefficient. Choices 10, 12, 14, 16, 18, 20, 24; default 16. A larger value lowers the stop-band error floor at the cost of DSP width.

Default: 16

Options: 10 12 14 16 18 20 24

Number of Taps NumTaps

Number of taps. For a canonical halfband use lengths of the form 4k+3 (11, 15, 19, 23, 27, 31, …); the plugin will use whatever value you set as a plain FIR + downsample-by-2 anyway.

Number of filter taps (filter order = NumTaps - 1). Choices 7, 11, 15, 19, 23, 27, 31, 39, 47, 63; default 15. Use a canonical halfband length of the form 4k+3 so the even taps fall exactly on the sinc zeros. More taps sharpen the transition band at the Fs/4 edge at the cost of DSPs and delay-line depth.

Default: 15

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

Usage

Why halfbands are the efficient DDC stages

A wideband receiver rarely decimates by a large factor in one FIR. Instead it cascades cheap 2:1 halfband stages (optionally after a CIC) because:

  • The Fs/4 cutoff forces every other tap to zero -> ~half the DSP slices.
  • Symmetry (h[k] = h[N-1-k]) folds the remaining taps into pairs.
  • Each stage only has to reject the half of the band that will alias when the rate halves; successive stages then narrow the band progressively.

This block performs the decimation as a plain direct-form FIR evaluated every input clock, keeping the output only on every second input clock. Because the coefficients are compile-time constants, Vivado prunes the zero (and +/-1) taps automatically, so you get the halfband saving without any special hardware.

Mathematical model

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

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

and outputs y_c[m] = acc_c[2m] — i.e. it keeps one result out of two.

Coefficient generation (fixed variant)

    h_ideal[n] = 2*fc * sinc(2*fc*(n - (N-1)/2)),   fc = 0.25
  w[n]       = 0.54 - 0.46 * cos(2*pi*n / (N-1))   (Hamming)
  h[n]       = h_ideal[n] * w[n]
  

then normalised so sum h[n] = 1 (unity DC gain) and quantised to a signed CoefSize-bit integer (scale 2^(CoefSize-1) - 1). Because sinc(0.5*integer) = 0, the even-offset taps vanish automatically — you do not have to hand them the zeros. For a canonical halfband use a tap count of the form 4k+3 (11, 15, 19, 23, 27, 31, …).

Bit widths

Data is treated as signed two’s complement.

  • IN_I, IN_Q : signed InputSize bits.
  • internal product : InputSize + CoefSize bits.
  • OUT_I, OUT_Q : signed InputSize + CoefSize + 8 bits.

The extra 8 accumulator bits (ACC_GROWTH = 8) absorb the tap sum without overflow up to 256 taps. Truncate downstream if fewer bits are needed.

VALID_OUT / strobe behaviour

The core is pipelined at II=1 and is clocked at the input (fast) rate — a new IN_I/IN_Q pair is accepted every clock. VALID_OUT is an output strobe that is asserted on exactly every other clock to mark the cycles on which OUT_I/OUT_Q carry a fresh, decimated sample; on the intervening clocks the outputs hold their previous value and VALID_OUT is low. After reset the internal keep flag starts true, so the first post-reset output is a valid one. Downstream logic must gate on VALID_OUT to run at the halved rate.

Latency and reset

  • #pragma HLS PIPELINE II=1 : accepts one input pair per clock.
  • 1-clock reported latency (delay-line update + MAC tree + output reg).
  • All data ports use the ap_none interface (no ready/valid handshake); the coefficient bus uses ap_stable.
  • RESET is the HLS synchronous reset (ap_rst); it clears the delay lines and re-arms the keep phase.

Typical applications

  • Final / intermediate 2:1 stage of a multistage DDC, after the CIC and its compensation FIR.
  • Anti-alias + rate halving anywhere a complex stream must be brought down by two before further processing.
  • Cascade several instances back-to-back for /4, /8, /16 … decimation.

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. The delay lines and coefficient array are fully partitioned and the MACC loop is unrolled, so up to NumTaps DSP48 slices per channel are inferred. Because the coefficients are compile-time constants, Vivado optimises away the ~half of taps that are zero (and the +/-1 taps), realising the classic halfband DSP saving with no special structure. Fixed 2:1 rate change is built into the block.