Skip to content
Chapter 22 · Lesson 4 of 4

First, the picture

A 12-tap low-pass that decimates by 4 can filter every input and throw three outputs in four away. Or its taps can be sorted into four short branches that each run at the low rate. Watch the two bars of work per kept output: 48 multiplies against 12, for the same outputs.

Split the taps by phase, run each part slowly

A 12-tap low-pass decimating by M = 4: filter then discard, against four 3-tap branches.

Direct: filter every input sample (12 multiplies each), then keep one output in 4. Per kept output: 48 multiplies, 36 of them thrown away.

multiplies per output
48
thrown away
36
0.00 / 14.00 s
Describe this picture

Two stacked panels for a 12-tap low-pass decimating by M=4M=4. The first shows the taps, nn from 0 to 11, as stems whose heads show their phase n mod 4n\bmod4: a dot for 0, a square for 1, a diamond for 2 and a triangle for 3. Each phase’s name, “E₀” to “E₃”, sits at its first tap. The second, “work per kept output”, is a bar chart from 0 to 50 multiplies with two bars, “filter then discard” and “polyphase”; the part of the first bar that is thrown away is hatched and labelled “thrown away”. The readouts are the multiplies per output and how many are thrown away. There is no control. The clip opens on the direct form: 12 multiplies for every input, then one output kept in 4, so 48 per kept output, 36 of them thrown away. Then the stems slide into four rows, one per phase: E₀ holds taps 0, 4, 8, E₁ taps 1, 5, 9, and so on, and the axis becomes the tap within the branch, 0 to 2. Last the second bar fills: the four branches add up to the same output, sample for sample, at 12 multiplies per output with nothing thrown away.

Split the taps by phase, run each part slowly

In Downsampling and decimation (22.1) a decimator filters every input sample and then keeps one output in MM. The other M−1M-1 outputs are computed and thrown away, so (M−1)/M(M-1)/M of its multiplies are wasted. In Upsampling and interpolation (22.2) the interpolator wastes work the other way: most of its multiplies meet the zeros it inserted.

On this page I move the rate change past the filter, so that nothing is computed for nothing. In block diagrams I draw downsampling by MM as a box marked ↓M, and upsampling by LL as a box marked ↑L.

The noble identity

Take any filter G(z)=∑jg[j] z−jG(z)=\sum_j g[j]\,z^{-j} and replace every zz by zMz^M. Then every delay becomes MM delays:

G(zM)=∑jg[j] z−Mj.G(z^M)=\sum_j g[j]\,z^{-Mj}.

Its taps sit only at multiples of MM, with zeros between. Feed it x[n]x[n] and keep every MM-th output, the one at MnMn:

∑jg[j] x[Mn−Mj]=∑jg[j] x[M(n−j)]=∑jg[j] xd[n−j].\begin{aligned} &\sum_j g[j]\,x[Mn-Mj]\\ &\quad=\sum_j g[j]\,x[M(n-j)]\\ &\quad=\sum_j g[j]\,x_d[n-j]. \end{aligned}

Every sample it touches is one that ↓M keeps, so it acts exactly like G(z)G(z) on the kept samples. This is the noble identity: G(zM)G(z^M) followed by ↓M equals ↓M followed by G(z)G(z). The filter can move after the rate drop, where it runs MM times less often.

A decimation filter h[n]h[n] is not of the form G(zM)G(z^M): its taps sit at every nn. So I split it into MM parts that are. Sort the taps by n mod Mn\bmod M, the remainder when nn is divided by MM. Tap Mj+kMj+k goes to part kk, for k=0,…,M−1k=0,\dots,M-1:

H(z)=∑k=0M−1∑jh[Mj+k] z−(Mj+k)=∑k=0M−1z−kEk(zM).\begin{aligned} H(z)&=\sum_{k=0}^{M-1}\sum_j h[Mj+k]\,z^{-(Mj+k)}\\ &=\sum_{k=0}^{M-1}z^{-k}E_k(z^M). \end{aligned}

Here Ek(z)=∑jh[Mj+k] z−jE_k(z)=\sum_j h[Mj+k]\,z^{-j} is the kk-th polyphase component: the filter whose taps are h[k]h[k], h[M+k]h[M+k], h[2M+k]h[2M+k], and so on. “Phase” here means the remainder kk.

Every branch after the downsampler

Each term z−kEk(zM)z^{-k}E_k(z^M) is a delay of kk followed by a filter in zMz^M. Keeping every MM-th sample of a sum is the sum of the kept samples, so ↓M can go into each branch. By the noble identity it then passes Ek(zM)E_k(z^M), which becomes Ek(z)E_k(z).

So branch kk delays the input by kk, keeps every MM-th sample, x[Mn−k]x[Mn-k], and filters it with EkE_k at the low rate. In the time domain, put m=Mj+km=Mj+k in the decimator’s sum:

y[n]=∑mh[m] x[Mn−m]=∑k=0M−1∑jh[Mj+k]⋅x[M(n−j)−k].\begin{aligned} y[n]&=\sum_m h[m]\,x[Mn-m]\\ &=\sum_{k=0}^{M-1}\sum_j h[Mj+k]\\ &\qquad\cdot x[M(n-j)-k]. \end{aligned}

The inner sum is branch kk. In hardware the delays and downsamplers at the front are often drawn as one switch, the commutator. It deals the input samples round the MM branches, one each, so every branch gets every MM-th sample. Once each branch has its sample, the branch outputs are added into one output.

Think of four cashiers, each serving every fourth customer. The other way is one cashier doing all the work, with supervisors throwing most of it away. The picture at the top of the page does this with a 12-tap low-pass and M=4M=4: four branches of 3 taps.

Notice what its end caption claims: the outputs are the same in both forms. Nothing is approximated. The polyphase form only skips the outputs that the direct form throws away.

The interpolator, the other way round

The interpolator of 22.2 inserts zeros, ↑L, and then filters. There is a second noble identity for it: ↑L followed by G(zL)G(z^L) equals G(z)G(z) followed by ↑L. The taps of G(zL)G(z^L) are LL apart. At the outputs LnLn they meet only original samples, and in between only zeros, so the result is G(z)G(z)‘s output with zeros inserted.

Split H(z)H(z) the same way, with LL in place of MM. Then output number Ln+kLn+k is made by branch kk alone:

y[Ln+k]=∑jh[Lj+k] x[n−j].y[Ln+k]=\sum_j h[Lj+k]\,x[n-j].

For 12 taps and L=4L=4, each output comes from one branch of 12/4=312/4=3 taps, so no multiply ever meets an inserted zero. Here the commutator sits at the output: it collects one sample from each branch in turn.

The table “Multiplies per output” counts the work for the jobs of this chapter.

JobFilterDirect formPolyphase
decimate by 412 taps4812
interpolate by 412 taps12, 9 of them by zero3
decimate by 4 (22.1)75 taps30075
44.1 → 48 kHz (22.3)3201 taps470 54720 or 21

The decimator’s cost per output falls from MNhMN_h to NhN_h, the filter’s length. The interpolator’s falls from NhN_h to Nh/LN_h/L. The 44.1 to 48 kHz converter of Resampling by any factor (22.3) gains both ways at once: it skips the zeros and the discarded outputs. That leaves one branch, 20 or 21 taps, for each output.

The maths behind it · block-Toeplitz matrices

The polyphase split is a permutation of the taps: stack them in an MM-row matrix, row kk holding h[Mn+k]h[Mn+k]. Group the input into blocks of MM samples, and a decimating filter becomes a product with a block-Toeplitz matrix. Each block is one column of the tap matrix, one tap from every branch. Filter banks are analysed in this form (Filter banks, 23.1).

No multiplications: integrators and combs

A decimator at megahertz rates wants something cheaper still, with no multiplier at all. Two pieces built from adders and delays will do it.

The first is the running sum of Operations on amplitude (2.2), s[n]=s[n−1]+x[n]s[n]=s[n-1]+x[n]. By The z-transform (16.1) a delay is z−1z^{-1}, so S(z)=X(z)/(1−z−1)S(z)=X(z)/(1-z^{-1}). I call 1/(1−z−1)1/(1-z^{-1}) an integrator.

The second is the feed-forward comb of Resonators, notches and combs (17.4), y[n]=x[n]−x[n−M]y[n]=x[n]-x[n-M], which is 1−z−M1-z^{-M}. I just call it a comb. Put the two in a row:

1−z−M1−z−1=1+z−1+…+z−(M−1).\begin{aligned} \frac{1-z^{-M}}{1-z^{-1}}&=1+z^{-1}+\dots\\ &\quad+z^{-(M-1)}. \end{aligned}

This is 6.1’s geometric sum, and it is an MM-point running sum. It is MM times the MM-point moving average of Simple smoothing filters (18.2).

Now the noble identity again. The comb 1−z−M1-z^{-M} is G(zM)G(z^M) with G(z)=1−z−1G(z)=1-z^{-1}, so it can move after ↓M and become 1−z−11-z^{-1} at the low rate. The integrator stays at the high rate.

Use NN integrators, then ↓M, then NN combs. Here NN counts stages, not points: the average has MM points. Moved back in front of ↓M, the combs and integrators make the filter

H(z)=(1−z−M1−z−1)N,H(z)=\left(\frac{1-z^{-M}}{1-z^{-1}}\right)^N,

and it has only adders and delays. It is a CIC filter, short for cascaded integrator–comb.

Its gain is a moving average’s gain, to the power NN. By Frequency response of discrete-time systems (12.4), the MM-point average has gain ∣sin⁡(MΩ/2)∣/∣Msin⁡(Ω/2)∣\lvert\sin(M\Omega/2)\rvert/\lvert M\sin(\Omega/2)\rvert, with zeros at Ω=2πk/M\Omega=2\pi k/M. So the CIC, scaled to 1 at 0 Hz, has

∣H(ejΩ)∣=∣sin⁡(MΩ/2)Msin⁡(Ω/2)∣N.\lvert H(e^{j\Omega})\rvert=\left\lvert\frac{\sin(M\Omega/2)}{M\sin(\Omega/2)}\right\rvert^N.

On a dB scale the power NN becomes a factor NN: each stage adds the same number of dB.

The instrument takes M=8M=8, from 64 kHz to 8 kHz, and keeps 0 to 1 kHz. After ↓8 the rate is 8 kHz, so a component folds onto 0 to 1 kHz if it lies within 1 kHz of 8, 16, 24 or 32 kHz.

The nearest such frequency is 7 kHz, and the gain there is the largest of all those bands. So the gain at 7 kHz is the one number to watch. In Ω\Omega, 7 kHz is 2π⋅7/64=0.21875π2\pi\cdot7/64=0.21875\pi.

Think of stacking identical sieves. Each one catches the same share of what is left. Besides the gain at 7 kHz I watch the droop: the loss inside the kept band, at its top edge.

No multiplications: integrators and combs

CIC decimator, M = 8, from 64 kHz to 8 kHz; keep 0 to 1 kHz.

N = 1: one integrator, one comb: an 8-point moving average. At 7 kHz, −16.95 dB.

stages N
1
at 7 kHz
−16.95 dB
droop at 1 kHz
−0.221 dB
0.00 / 14.00 s
Describe this picture

Two stacked panels for a CIC decimator with M=8M=8, from 64 kHz to 8 kHz, keeping 0 to 1 kHz. The first draws the structure: NN integrator boxes marked “1/(1 − z⁻¹)”, a box “↓8”, then NN comb boxes marked “1 − z⁻¹”; boxes appear as NN grows. The second is the gain, from −120 to 5 dB against frequency from 0 to 32 kHz, a solid curve floored at −120 dB. Hatched bands at 7 to 9, 15 to 17, 23 to 25 and 31 to 32 kHz are labelled “folds onto 0–1 kHz”, and a dotted vertical line marks 7 kHz. The readouts are the number of stages NN, the gain at 7 kHz and the droop at 1 kHz. The clip steps NN from 1 to 4. One stage, one integrator and one comb, is an 8-point moving average: −16.95 dB at 7 kHz and −0.221 dB of droop. Two stages give −33.91 and −0.442 dB, three −50.86 and −0.663 dB, and four −67.82 and −0.884 dB, with no multiplier anywhere. After the clip a slider named “Stages N” sets NN from 1 to 6. At 5 the caption reads “N = 5: −84.77 dB at 7 kHz, droop −1.105 dB.” At 6 it is −101.73 dB and −1.325 dB.

Notice the two readouts as NN grows. Each stage adds another −16.95 dB at 7 kHz, but only −0.221 dB at 1 kHz. The clip’s end caption says why: each stage multiplies the gain by the same moving-average curve, so its dB add.

What it costs

The CIC has no multipliers, but it pays in register size. At 0 Hz the MM-point running sum has gain MM, so the CIC has gain MNM^N: here up to 86=262 1448^6=262\,144. The gain panel divides by this, which is why 0 Hz sits at 0 dB.

The registers must hold numbers MNM^N times bigger than the input. That takes Nlog⁡2MN\log_2M extra bits: 3 per stage here, from 3 bits for one stage to 18 for six.

The integrators are a worry. A running sum of a signal that does not average to zero grows without end, so in fixed point it overflows. In the two’s complement arithmetic of Finite word-length effects (21.3), it wraps round.

Here that does no harm, as long as each register has those Nlog⁡2MN\log_2M extra bits. In a register of BB bits, a wrap changes a value by a whole multiple of 2B2^B. Adds and subtracts carry such an error through unchanged, so the combs’ output is off by a multiple of 2B2^B at most.

The true output fits in BB bits, so the last wrap lands it exactly on the true value. The combs undo the integrators’ wrapping exactly.

The droop grows with NN too, −0.884 dB at 1 kHz for four stages. A short FIR after the CIC, running at the low rate, lifts the top of the kept band back up. It is called a compensation filter.

The maths behind it · the central limit theorem

A CIC with NN stages is NN moving averages in a row. Its impulse response is a box convolved with itself NN times. As NN grows, that shape tends to a Gaussian: the central limit theorem, in filter form.

Worked example

1. Counting multiplies. A decimator with NhN_h taps that filters every input does MNhMN_h multiplies per kept output; in polyphase form it does NhN_h. For 12 taps and M=4M=4 that is 48 against 12, and for 22.1’s 75 taps it is 300 against 75. An interpolator with 12 taps and L=4L=4 does 12 multiplies per output directly, 9 of them by zero, and 3 in polyphase form.

2. The CIC gain at 7 kHz, by hand. With M=8M=8 at 64 kHz, Ω/2=7π/64\Omega/2=7\pi/64 at 7 kHz, and MΩ/2=7π/8M\Omega/2=7\pi/8. One stage gives sin⁡(7π/8)/(8sin⁡(7π/64))=0.38268/(8⋅0.33689)=0.14199\sin(7\pi/8)/(8\sin(7\pi/64))=0.38268/(8\cdot0.33689)=0.14199, which is −16.95 dB. At 1 kHz the top is sin⁡(π/8)\sin(\pi/8), also 0.38268, and the bottom is 8sin⁡(π/64)=0.392548\sin(\pi/64)=0.39254. That gives 0.97489, or −0.221 dB.

3. How many stages for 60 dB? Each stage gives 16.95 dB at 7 kHz, and 60/16.95=3.5460/16.95=3.54. So N=3N=3 gives −50.86 dB, not enough, and N=4N=4 gives −67.82 dB. Take 4 stages: the droop at 1 kHz is −0.884 dB, and the registers need 4⋅3=124\cdot3=12 extra bits.

4. Register width. An 8-bit input through that 4-stage CIC needs registers of 8+12=208+12=20 bits. The largest output is 127⋅84=520 192127\cdot8^4=520\,192, which fits in 20 bits but not in 19.

Where you’ll meet this

Sigma-delta converters (Oversampling and noise shaping, 11.3) sample at megahertz rates, and their first decimation stages are usually CIC filters. So are the first stages of software radios. At those rates a multiplier is expensive and an adder is cheap. A polyphase FIR then does the last, sharper stages at the lower rate.

SciPy’s upfirdn and resample_poly work in polyphase form, which is why 22.3’s 44.1 to 48 kHz job costs about 20 multiplies per output. The Farrow structure of 22.3 is close kin: it works like a polyphase filter with a branch for every fractional position μ\mu, its taps computed from μ\mu rather than stored.

In Filter banks (23.1), the polyphase components of one prototype filter build a whole bank of band filters at once.

Reference card

QuantityFormulaNotes
Noble identity (down)G(zM)G(z^M) then ↓M = ↓M then G(z)G(z)filter after the rate drop
Noble identity (up)↑L then G(zL)G(z^L) = G(z)G(z) then ↑Lfilter before the zeros go in
Polyphase splitH(z)=∑k=0M−1z−kEk(zM)H(z)=\sum_{k=0}^{M-1}z^{-k}E_k(z^M), taps h[Mn+k]h[Mn+k]MM branches at the low rate
Cost per outputNhN_h (decimator), Nh/LN_h/L (interpolator)instead of MNhMN_h, NhN_h
CIC(1−z−M1−z−1)N\big(\frac{1-z^{-M}}{1-z^{-1}}\big)^Nno multipliers; gain MNM^N at 0 Hz
CIC gain re 0 Hz∣sin⁡(MΩ/2)Msin⁡(Ω/2)∣N\left\lvert\frac{\sin(M\Omega/2)}{M\sin(\Omega/2)}\right\rvert^NNN times one stage’s dB
CIC growthNlog⁡2MN\log_2M bitswrap-around is harmless with them

End of lesson 22.4

Where to go next.

Phasorium
LibraryEvery lesson, in order

Parts

About Phasorium
Look