Xilinx
HLS
Block Preview

Introduction

The CIC Interpolator (fixed rate) raises the sample rate of a complex baseband stream by an integer factor R using the Hogenauer cascaded-integrator-comb structure run “backwards” relative to the decimator. Like the decimator it uses no multipliers - only adders, subtractors and registers.

The block runs entirely at the fast (output) rate Fs_out = R * Fs_in. The datapath is (I and Q processed independently):

    x[m] ─► [ N combs @ Fs_out/R ] ─► ( ↑R, zero-stuff ) ─► [ N integrators @ Fs_out ] ─► y[n]
           (1 - z^-M) each                                   1/(1 - z^-1) each
  
  • N comb stages update only when a new low-rate input is consumed (once every R output clocks).
  • The zero-stuffing up-sampler feeds the comb output into the integrator chain on the consume tick and feeds zero on all other clocks - this is what raises the rate.
  • N integrators run every output clock at Fs_out, interpolating between the stuffed samples.

The transfer function (referred to the output rate) is the same raised sinc as the decimator:

    H(z)   = [ (1 - z^-(R*M)) / (1 - z^-1) ]^N
  |H(f)| = | sin(pi*R*M*f/Fs_out) / sin(pi*f/Fs_out) |^N
  

For a run-time programmable rate see Component_CICInterpolatorProgrammable (cic_interp_prog).

Pin Description

IN_I Input InputSize bit BIT VECTOR
In-phase (I) low-rate input sample. Signed, Input Bit Width bits. Latched by the block on each SAMPLE_IN strobe; hold it stable until then.
Default: Must be connected
IN_Q Input InputSize bit BIT VECTOR
Quadrature (Q) low-rate input sample. Signed, Input Bit Width bits. Tie to zero for a real-only signal.
Default: Must be connected
CLK Input 1 bit BIT
System clock input, running at the fast output rate Fs_out = R * Fs_in. Default: Acquisition clock.
Default: Default Board Clock
RESET Input 1 bit BIT
HLS synchronous reset (ap_rst). Clears comb delay lines, integrator accumulators and the rate counter. Default: Global reset.
Default: Default Board Reset
OUT_I Output InputSize + NStages*ceil(log2(Rate*DiffDelay)) bit BIT VECTOR

In-phase (I) interpolated output at the fast rate. Signed, **InputSize

  • Nceil(log2(RM))** bits. Valid on every clock. Carries the (R*M)^N DC gain.
OUT_Q Output InputSize + NStages*ceil(log2(Rate*DiffDelay)) bit BIT VECTOR

Quadrature (Q) interpolated output at the fast rate. Signed, **InputSize

  • Nceil(log2(RM))** bits. Valid on every clock.
SAMPLE_IN Output 1 bit BIT
One-clock-wide input-request strobe, asserted once every R output clocks on the cycle where the block consumes IN_I/IN_Q. Use it to pace the upstream producer (advance to the next low-rate sample after each strobe). This is not an output-valid flag - the output is valid every clock.

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. Redesign on change.

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

Number of Stages NStages

Filter order N.

Number of comb/integrator stages N (CIC order). Choices 1..6, default 3. Higher N deepens image rejection but adds ceil(log2(R*M)) bits of growth per stage and more passband droop.

Default: 3

Options: 1 2 3 4 5 6

Interpolation Rate R Rate

Up-sampling ratio. Output rate = input rate * R.

Interpolation factor R (Fs_out = R * Fs_in). Baked into the netlist as a constant. Choices 2, 4, 8, 16, 32, 64, 128, 256, default 8.

Default: 8

Options: 2 4 8 16 32 64 128 256

Comb Differential Delay M DiffDelay

Differential delay (usually 1).

Comb differential delay M (low-rate samples). Almost always 1; M=2 widens the stop-band notches. Choices 1, 2, default 1.

Default: 1

Options: 1 2

Usage

The SAMPLE_IN handshake (this is not VALID_OUT)

Unlike the decimator, the interpolator’s rate strobe is an input-request flag, not an output-valid flag. Because the block runs at the fast rate but the producer only supplies a new low-rate sample every R clocks, the block must tell the producer when it has consumed the current IN_I/IN_Q.

SAMPLE_IN is a one-clock-wide strobe asserted once every R output clocks. On the clock where SAMPLE_IN is high, the block latches IN_I/IN_Q into the comb chain (zero-stuffs on the other R-1 clocks). Upstream logic should hold the current input sample until it sees SAMPLE_IN, then advance its producer so a new low-rate sample is present by the next SAMPLE_IN tick.

    CLK        _|‾|_|‾|_ ... (R output clocks) ... _|‾|_
  SAMPLE_IN  __|‾|____ ...   consume x[m]      ...__|‾|_  consume x[m+1]
  OUT        (interpolated samples every clock, all R of them valid)
  

Note: every output clock carries a valid interpolated OUT_I/OUT_Q sample - there is no output strobe because the output is full-rate. Only the input side needs the SAMPLE_IN request.

Passband droop and image attenuation

As an interpolator the CIC’s job is to suppress the images created by zero-stuffing (replicas of the baseband at multiples of Fs_in). The sinc^N response places nulls on those images, but shallow ones for small N, and it droops across the wanted passband exactly as the decimator does:

    worst-case passband droop at band edge ~= -3.92 * N   dB   (M=1, large R)
  

So a DUC usually places a short compensation / interpolation FIR before the CIC (running at the low rate) to pre-emphasise the passband and knock down the near-in images, then lets the CIC do the cheap high-rate up-sampling.

Bit growth, gain and accumulator width

    GROWTH   = N * ceil(log2(R * M))
  OUT_SIZE = INPUT_SIZE + GROWTH
  DC gain  = (R * M)^N            (referred to the low-rate input)
  

The plugin sizes all integrator/comb registers and the output ports to OUT_SIZE so the datapath is bit-true. As with the decimator the DC gain (R*M)^N is not divided out; scale downstream if you need unity gain.

Worked example (defaults N=3, R=8, M=1, InputSize=16):

    GROWTH   = 3 * ceil(log2(8)) = 9 bits
  OUT_SIZE = 16 + 9            = 25 bits
  DC gain  = 8^3              = 512
  

Timing, interface and reset

  • #pragma HLS PIPELINE II=1 : one output sample pair per clock, at the fast rate Fs_out.
  • All data ports use ap_none; RATE is tied to an internal compile-time constant (no top-level pin).
  • RESET (ap_rst) clears the comb delay lines, the integrator accumulators and the rate counter.

Typical applications

  • DUC output stage : FIR (pre-comp) -> cic_interp -> Mixer -> DAC. The CIC does the cheap high-rate up-sampling to the DAC clock.
  • Sample-rate matching from a low-rate DSP core to a fast converter.
  • Test-vector up-sampling for hardware-in-the-loop stimulus.

Resources & Timing

  • Latency: Symbol/scheduling latency 1 clock; the interpolated stream is valid every output clock. Group delay through the comb+integrator cascade is ~NRM/2 output samples.

  • Throughput: 1 output sample pair per clock (II=1) at the fast rate Fs_out; one new low-rate input consumed every R clocks, paced by SAMPLE_IN.

Implemented with Vitis HLS. Multiplier-free: 2N comb subtractors + 2N integrator adders (I and Q), all OUT_SIZE = InputSize + N*ceil(log2(R*M)) bits wide, plus one rate counter. The integrators run every clock (the costly high-rate part), the combs only on the consume tick. Output carries the full (R*M)^N gain - scale downstream, and pre-compensate droop with an interpolation FIR ahead of the CIC.