Z-Transform and Digital Filters: FIR vs IIR with Worked Examples

The z-transform does for discrete-time signals what the Laplace transform does for continuous ones: it turns difference equations into algebra and reveals stability and frequency response through poles and zeros. It is the language of digital filters running on microcontrollers, DSP chips and FPGAs. This tutorial covers the definition, the region of convergence, the key pairs and properties, an inverse transform by partial fractions, and then designs and compares a simple FIR filter and a simple IIR filter, ending with C code that implements both.

Definition, Pairs and Region of Convergence

X(z) = Σ x[n] z^(-n)      (sum over all n),   z is a complex variable

Key property (delay): x[n - k]  ->  z^(-k) X(z)

The delay property is why z^-1 is drawn as a unit delay block in filter diagrams. The sum converges only for some values of z, called the region of convergence (ROC). The same algebraic X(z) can correspond to different signals with different ROCs, so the ROC is part of the answer.

x[n]X(z)ROC
δ[n]1All z
u[n]z/(z - 1)|z| > 1
a^n u[n]z/(z - a)|z| > |a|
-a^n u[-n - 1]z/(z - a)|z| < |a|
n a^n u[n]az/(z - a)^2|z| > |a|
δ[n - k]z^(-k)All z except 0 (k > 0)

For a causal signal the ROC is outside the outermost pole. An LTI system is stable if its ROC includes the unit circle |z| = 1. Combining the two, a causal system is stable when all poles lie strictly inside the unit circle, the discrete counterpart of the left half-plane rule for Laplace.

Worked Example: Inverse Z-Transform

X(z) = z / ((z - 1)(z - 0.5)),   ROC |z| > 1 (causal)

Expand X(z)/z, not X(z):
X(z)/z = 1/((z - 1)(z - 0.5)) = 2/(z - 1) - 2/(z - 0.5)
X(z)   = 2z/(z - 1) - 2z/(z - 0.5)

x[n] = 2u[n] - 2(0.5)^n u[n]

Check by long division: x[0] = 0, x[1] = 1, x[2] = 1.5
Formula: x[0] = 2 - 2 = 0, x[1] = 2 - 1 = 1, x[2] = 2 - 0.5 = 1.5

Dividing by z first is the standard trick: it makes every partial fraction term become az/(z - p) after multiplying back, which matches the table directly.

Link to the Laplace transform and real frequencies

If a continuous signal is sampled every T seconds, the z-transform is the Laplace transform of the sampled signal with z = e^(sT). This mapping sends the jω axis of the s-plane onto the unit circle and the stable left half-plane into the inside of the circle, which is why the two stability rules match. Points on the unit circle are written z = e^(jω), where the digital frequency ω in radians per sample relates to real frequency f by ω = 2πf/fs. For example, with fs = 1 kHz, ω = π/2 corresponds to 250 Hz and ω = π to the Nyquist frequency of 500 Hz. Keep this conversion handy: filter specifications are given in hertz, but H(z) works in radians per sample.

From Difference Equation to Frequency Response

A digital filter is described by a difference equation that combines current and past inputs, and possibly past outputs. Taking the z-transform of both sides and using the delay property gives the transfer function H(z) = Y(z)/X(z). Setting z = e^(jω), where ω runs from 0 to π (π corresponds to half the sampling rate), gives the frequency response.

FIR example: two-point average

y[n] = 0.5 x[n] + 0.5 x[n - 1]
H(z) = 0.5 (1 + z^(-1))          zero at z = -1, no poles except z = 0

|H| at ω = 0   : 0.5 |1 + 1|              = 1      (DC passes)
|H| at ω = π/2 : 0.5 |1 + e^(-jπ/2)|      = 0.707  (-3 dB at fs/4)
|H| at ω = π   : 0.5 |1 - 1|              = 0      (Nyquist blocked)

IIR example: first-order low-pass (exponential smoother)

y[n] = a y[n - 1] + (1 - a) x[n],   choose a = 0.9
H(z) = (1 - a) / (1 - a z^(-1)) = 0.1 / (1 - 0.9 z^(-1))   pole at z = 0.9

|H| at ω = 0 : 0.1 / (1 - 0.9) = 1
|H| at ω = π : 0.1 / (1 + 0.9) = 0.053
Impulse response h[n] = 0.1 (0.9)^n u[n]  -> never exactly zero

The pole at 0.9 is inside the unit circle, so the filter is stable. Move a closer to 1 and the pole approaches the circle: the filter smooths more heavily but responds more slowly. With a = 1 or greater it becomes unstable. This single line of code is one of the most common filters in embedded firmware, used to smooth ADC readings.

FIR versus IIR

FeatureFIRIIR
Impulse responseFinite lengthInfinite, decays over time
Uses past outputs (feedback)NoYes
PolesOnly at z = 0, always stableAnywhere; must be inside unit circle
PhaseExactly linear if coefficients are symmetricNon-linear in general
Order for a sharp cutoffHigh, many multiplies per sampleLow, few multiplies per sample
Sensitivity to coefficient roundingLowHigher, especially for high order
Typical design methodsWindowing, Parks-McClellanBilinear transform of Butterworth or Chebyshev prototypes

Choose FIR when phase linearity matters, as in audio crossovers, data communication pulse shaping and ECG processing, or when guaranteed stability is important. Choose IIR when computing power is limited and a sharp magnitude response is enough, as in simple sensor smoothing or tone detection. High-order IIR filters are usually implemented as cascaded second-order sections to limit coefficient sensitivity.

Both Filters in C

Two-point FIR average and first-order IIR low-pass, printing their impulse responses
#include <stdio.h>

/* FIR: y[n] = 0.5 x[n] + 0.5 x[n-1] */
typedef struct { float x1; } fir2_t;

float fir2_step(fir2_t *f, float x)
{
    float y = 0.5f * x + 0.5f * f->x1;
    f->x1 = x;                 /* store x[n] for the next call */
    return y;
}

/* IIR: y[n] = a y[n-1] + (1 - a) x[n] */
typedef struct { float a; float y1; } iir1_t;

float iir1_step(iir1_t *f, float x)
{
    float y = f->a * f->y1 + (1.0f - f->a) * x;
    f->y1 = y;                 /* feedback: store y[n] */
    return y;
}

int main(void)
{
    fir2_t fir = { 0.0f };
    iir1_t iir = { 0.9f, 0.0f };

    printf("n    FIR      IIR\n");
    for (int n = 0; n < 6; n++) {
        float x = (n == 0) ? 1.0f : 0.0f;   /* unit impulse */
        printf("%d  %.5f  %.5f\n", n, fir2_step(&fir, x), iir1_step(&iir, x));
    }
    return 0;
}
n    FIR      IIR
0  0.50000  0.10000
1  0.50000  0.09000
2  0.00000  0.08100
3  0.00000  0.07290
4  0.00000  0.06561
5  0.00000  0.05905

The output shows the defining difference: the FIR response ends after two samples, while the IIR response decays geometrically by 0.9 each step and never reaches exactly zero.

Summary

  • The z-transform turns delays into powers of z^-1, so difference equations become rational functions H(z).
  • Always state the ROC; a causal system is stable when every pole is inside the unit circle.
  • Evaluate H(z) on the unit circle, z = e^(jω), to get the frequency response.
  • FIR filters are always stable and can have linear phase; IIR filters achieve sharp responses with far fewer coefficients but need care with stability and phase.