RF CIC Interpolator (fixed rate)
Cascaded-Integrator-Comb (CIC) interpolator for a complex I/Q baseband stream. Multiplier-free zero-stuffing up-sampler by a fixed ratio R baked into the netlist. Typical use: the last, highest-rate stage of a Digital Up-Converter (DUC) chain, raising a low-rate baseband signal up to the DAC sample rate before the mixer.
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
SAMPLE_IN strobe; hold it stable until
then.
Fs_out = R * Fs_in. Default: Acquisition clock.
In-phase (I) interpolated output at the fast rate. Signed, **InputSize
- Nceil(log2(RM))** bits. Valid on every clock. Carries the
(R*M)^NDC gain.
Quadrature (Q) interpolated output at the fast rate. Signed, **InputSize
- Nceil(log2(RM))** bits. Valid on every clock.
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
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
Filter order N.
Number of comb/integrator stages N (CIC order). Choices 1..6, default 3. Higher N deepens image rejection but addsceil(log2(R*M)) bits of growth per stage and more passband droop.
Default: 3
Options: 1 2 3 4 5 6
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
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 rateFs_out.- All data ports use
ap_none;RATEis 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.