Xilinx
HLS
Block Preview

Introduction

The Halfband Interpolator (prog) block is the run-time programmable sibling of halfband_interp. It doubles the sample rate of a complex baseband stream by zero-stuffing and low-pass filtering, but its NumTaps coefficients are supplied live on a top-level COEFS pin rather than computed by the plugin and frozen into the VHDL.

The anti-image filter is a halfband — cutoff at Fs/4, every second tap zero (except the centre), symmetric — which is the cheapest FIR for a 2:1 interpolation. See halfband_interp for the full zero-stuff-and-filter theory.

     slow rate                 fast (output) rate
    IN_I ─┐                ┌── OUT_I
    IN_Q ─┤  [ 0-stuff +   ├── OUT_Q
   COEFS ─┘    halfband ]  └── SAMPLE_IN
  

What “programmable” means here

In the fixed variant the plugin computes the halfband taps, packs the quantised values into a constant and wires it to the internal coefs_packed port. In this prog variant that 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, BRAM, an AXI-lite word, a DMA, or another block — and change the anti-image response at run time without re-synthesising.

You compute the 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 slow (input) rate. Signed, Input Bit Width bits. Present a new word only on clocks where SAMPLE_IN is high.
Default: Must be connected
IN_Q Input InputSize bit BIT VECTOR
Quadrature (Q) input sample at the slow (input) rate. Signed, Input Bit Width bits. Tie to zero to interpolate 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 halfband anti-image taps.
Default: Must be connected
CLK Input 1 bit BIT
System clock input (the fast / output-rate clock — the block runs at the interpolated rate). 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 consume phase; does not affect COEFS. Default: Global reset.
Default: Default Board Reset
OUT_I Output InputSize + CoefSize + 8 bit BIT VECTOR
In-phase (I) interpolated output at the fast rate. Signed, InputSize + CoefSize + 8 bits. Valid every clock.
OUT_Q Output InputSize + CoefSize + 8 bit BIT VECTOR
Quadrature (Q) interpolated output at the fast rate. Signed, InputSize + CoefSize + 8 bits. Valid every clock.
SAMPLE_IN Output 1 bit BIT
Input-consume strobe (output). Asserted on the fast-rate clocks where a new IN_I/IN_Q sample is taken into the filter. Use it as the “advance” enable for the slow-rate producer feeding IN_I/IN_Q.

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

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 bits [(k+1)*CoefSize-1 : k*CoefSize] as a signed two’s-complement CoefSize-bit value. Inside the HLS core the bus is ap_stable (sampled every clock, assumed slowly varying), so update it only when the datapath is quiescent (or accept a transient during reload).

Because the taps are unknown at synthesis time, Vivado cannot prune the zero taps: the programmable variant instantiates the full NumTaps multipliers per channel. Prefer the fixed variant if you never retune.

Zero-stuff-and-filter model

For each channel c in {I, Q}, the block inserts a zero between input samples to form a fast-rate stream and filters it:

    u_c[2m] = x_c[m],  u_c[2m+1] = 0
  y_c[n]  = sum_{k=0..NumTaps-1} h[k] * u_c[n-k]
  

Passband gain note

Supply coefficients with the gain you want. If you quantise a unity-DC-gain halfband, the interpolated envelope comes out at roughly half amplitude because half the fast-rate samples are inserted zeros; scale the taps by 2 (or gain downstream) to preserve level — the usual factor-of-L convention for an interpolate-by-L filter.

Bit widths

Data is treated as signed two’s complement.

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

The extra 8 accumulator bits (ACC_GROWTH = 8) prevent overflow.

SAMPLE_IN / strobe behaviour

Identical to the fixed variant. The block runs at the fast (output) clock and produces a valid OUT_I/OUT_Q every clock. SAMPLE_IN is an output asserted on the clocks where a new IN_I/IN_Q sample is consumed (a zero is inserted on the others); use it as the “advance now” enable for the slow-rate producer. The internal consume phase starts true after reset.

Latency and reset

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

Typical applications

  • DUC 2:1 up-sampling stages whose anti-image response must be re-tuned at run time.
  • Adaptive / calibrated interpolation with taps loaded from software.
  • One bitstream serving products that need different responses.

Resources & Timing

  • Latency: 1 clock cycle (reported)

  • Throughput: Runs at the fast (output) rate: 1 output pair per clock (II=1). A new input sample is consumed on every second clock (input rate = output rate / 2), flagged by SAMPLE_IN.

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. Output level depends on the taps you load (a unity-DC-gain halfband yields ~half amplitude on zero-stuffed data; scale by 2 to compensate). Fixed 2:1 rate change is built into the block.