Designing and Implementing IIR Filters in MATLAB: A Comprehensive Guide

Digital filtering is a cornerstone of modern signal processing, and Infinite Impulse Response (IIR) filters offer an efficient way to achieve sharp frequency selectivity with low computational overhead. MATLAB provides a rich set of tools for IIR filter design, analysis, and implementation. This guide walks you through the complete workflow—from understanding IIR fundamentals to deploying a working filter on real data. You’ll learn how to choose filter topologies, set specifications, design with built‑in functions, validate performance, and avoid common pitfalls. Whether you are a student, researcher, or engineer, mastering IIR filters in MATLAB will accelerate your signal‑processing projects.

IIR Filters: Core Concepts

An IIR filter uses feedback—its output depends on both current and past inputs as well as past outputs. This recursive structure yields a transfer function with poles and zeros. The presence of poles allows IIR filters to achieve a given magnitude response with far fewer coefficients than an equivalent finite impulse response (FIR) filter. However, the trade‑off is potential instability and non‑linear phase response.

Key IIR Filter Types

  • Butterworth – Maximally flat magnitude response in the passband; monotonic roll‑off. Good for applications where passband ripple is unacceptable.
  • Chebyshev Type I – Allows ripple in the passband but provides a steeper roll‑off than Butterworth for the same filter order.
  • Chebyshev Type II – Ripple in the stopband only; also known as “inverse Chebyshev”.
  • Elliptic (Cauer) – Ripple in both passband and stopband, offering the sharpest transition for a given order. Ideal when minimum order is critical.
  • Bessel – Maximally flat group delay, preserving waveform shape in the time domain. Useful for analog‑like filtering but has a slower roll‑off.

When to Choose an IIR Filter

IIR filters excel when you need a narrow transition band, a high level of stopband attenuation, or low computational cost. They are common in audio equalization, biotelemetry, and real‑time control systems. For applications requiring linear phase (e.g., data communication), FIR filters are typically preferred.

Step 1: Define Filter Specifications

Every filter design begins with a clear set of requirements. Document the following parameters before writing any code:

  1. Filter type: lowpass, highpass, bandpass, or bandstop.
  2. Passband and stopband frequencies. For lowpass, this is the cutoff frequency Fc. For bandpass, provide lower and upper cutoff frequencies F1 and F2.
  3. Sampling frequency (Fs) – must satisfy the Nyquist criterion.
  4. Passband ripple (dB) – maximum allowed variation in the passband (relevant for Chebyshev and elliptic designs).
  5. Stopband attenuation (dB) – minimum attenuation required in the stopband.
  6. Filter order – or maximum allowable order. Higher order gives sharper response but increases computational load and can cause numerical issues.

These specifications directly guide the choice of design function. For example, a Butterworth filter requires only the order and cutoff frequency; a Chebyshev Type I also needs passband ripple; an elliptic filter needs both ripple and stopband attenuation.

Step 2: Design the IIR Filter in MATLAB

MATLAB offers several complementary workflows for IIR design. The most direct way is to use the classical function calls, but there are also interactive tools and the more modern designfilt function.

Using Classic Functions

The classic butter, cheby1, cheby2, and ellip functions return numerator (b) and denominator (a) coefficients in transfer‑function form. These coefficients are suitable for the filter function but can become numerically unstable for high orders. For orders above 10, consider using second‑order sections (SOS).

Example: Lowpass Butterworth, order 4, cutoff 100 Hz, Fs = 1000 Hz

Fs = 1000;          % Sampling frequency
Fc = 100;           % Cutoff frequency
order = 4;          % Filter order

% Normalize cutoff: 0 to 1, where 1 = Fs/2
Wn = Fc / (Fs/2);

% Design filter
[b, a] = butter(order, Wn, 'low');

For a band‑pass filter with cutoff frequencies 50 Hz and 200 Hz:

Wn = [50 200] / (Fs/2);
[b, a] = butter(order, Wn, 'bandpass');

Notice that when Wn is a two‑element vector, the filter type changes automatically.

Using the designfilt Function

The designfilt function provides a single interface for all standard IIR designs. It returns a digitalFilter object that can be used with filtfilt or filter. This approach is preferred for its readability and integrated parameter validation.

% Design a lowpass Chebyshev Type I filter
d = designfilt('lowpassiir', ...
    'FilterOrder', 5, ...
    'PassbandFrequency', 150, ...
    'PassbandRipple', 1, ...
    'SampleRate', 1000);

You can then inspect the object or extract coefficients with d.Coefficients.

Converting to Second‑Order Sections (SOS)

For high‑order filters, direct use of b, a can lead to severe numerical rounding errors when applying the filter. Convert the coefficients to cascaded second‑order sections using tf2sos:

[sos, g] = tf2sos(b, a);

Then use sosfilt for filtering:

outputSignal = sosfilt(sos, g, inputSignal);

This is the industrial‑standard way to implement high‑order IIR filters.

Step 3: Visualize and Validate the Filter Response

Before applying the filter to actual data, verify its frequency and phase response to ensure it meets your specifications.

Using fvtool

The fvtool function opens an interactive GUI for analyzing the filter:

fvtool(b, a);        % for transfer function coefficients
fvtool(d);           % for a digitalFilter object
fvtool(sos, g);      % for second‑order sections

By default, it displays the magnitude response (dB) and phase response. You can also view group delay, impulse response, pole‑zero plot, and check stability.

Using freqs and freqz Commands

For script‑based analysis, use freqz to compute the frequency response:

[H, w] = freqz(b, a, 1024, Fs);
plot(w, 20*log10(abs(H)));
xlabel('Frequency (Hz)'); ylabel('Magnitude (dB)');
grid on;

To check stability, verify that all poles lie inside the unit circle. Use zplane or compute the roots of the denominator:

poles = roots(a);
if all(abs(poles) < 1)
    disp('Filter is stable.');
else
    disp('Warning: Filter is unstable.');
end

Phase and Group Delay

IIR filters introduce non‑linear phase. You can observe group delay using grpdelay:

grpdelay(b, a, 1024, Fs);

If phase linearity is critical, consider using filtfilt (zero‑phase filtering), which applies the filter forward and backward.

Step 4: Apply the Filter to a Signal

Once the filter is validated, apply it to your data using filter (causal) or filtfilt (zero‑phase).

Causal Filtering with filter

inputSignal = randn(1, 1000);   % Example noisy signal
outputSignal = filter(b, a, inputSignal);

This filters the signal in the forward direction, introducing a transient initial condition. To minimize transient effects, you can provide initial conditions from filtic or simply discard the first few samples.

Zero‑Phase Filtering with filtfilt

Use filtfilt when you need to preserve the waveform shape (e.g., for biological signals):

outputSignal = filtfilt(d, inputSignal);   % for digitalFilter object
outputSignal = filtfilt(b, a, inputSignal); % for coefficients

Note: filtfilt doubles the effective filter order and introduces a delay, but it eliminates phase distortion.

Filtering with Second‑Order Sections

outputSignal = sosfilt(sos, g, inputSignal);

If you have a large signal or need real‑time performance, use sosfilt with streaming processing via dsp.IIRFilter.

Step 5: Analyze the Filtered Output

Always compare the original and filtered signals to confirm the filter’s effect.

Time‑Domain Plot

t = (0:length(inputSignal)-1) / Fs;
plot(t, inputSignal, t, outputSignal);
xlabel('Time (s)'); ylabel('Amplitude');
legend('Original', 'Filtered');
title('Time‑Domain Comparison');

Frequency‑Domain Analysis

Use the periodogram or power spectral density to show how the filter shapes the spectrum:

[pxx_orig, f] = periodogram(inputSignal, [], [], Fs);
[pxx_filt, ~] = periodogram(outputSignal, [], [], Fs);
plot(f, 10*log10(pxx_orig), f, 10*log10(pxx_filt));
xlabel('Frequency (Hz)'); ylabel('Power/Frequency (dB/Hz)');
legend('Original', 'Filtered');

Quantifying Performance

Compute metrics like signal‑to‑noise ratio (SNR) improvement or total harmonic distortion (THD) to objectively measure filter quality.

Practical Considerations and Best Practices

Numerical Stability

High‑order IIR filters (order > 10) are prone to coefficient quantization errors. Always use second‑order sections in production code. In fixed‑point environments, consider using the DSP System Toolbox’s dsp.IIRFilter with automatic scaling.

Choosing the Right Filter Order

Use buttord, cheb1ord, etc., to compute the minimum order required to meet your passband and stopband criteria. This avoids over‑designing.

[n, Wn] = buttord(0.2, 0.3, 1, 20);  % passband edge 0.2, stopband edge 0.3, 1 dB ripple, 20 dB attenuation
[b, a] = butter(n, Wn);

Dealing with Edge Effects

Both filter and filtfilt can introduce artifacts at the signal boundaries. To mitigate this, pad the input signal with mirrored or zero segments, filter, then trim.

Comparison with FIR Filters

For the same cutoff sharpness, an IIR filter typically requires 5–10× fewer coefficients than an FIR filter. However, FIR filters offer linear phase and guaranteed stability. Use IIR when computational resources are limited and phase distortion is acceptable.

Advanced Topics

Custom IIR Architectures

Beyond the standard direct‑form I/II, you can implement IIR filters in cascaded biquad (SOS) or lattice‑ladder form. MATLAB provides tf2sos and tf2latc for conversion. Lattice structures are less sensitive to coefficient quantization.

Designing with the Filter Design and Analysis Tool (FDATool)

Launch fdatool for a graphical interface. You can design, analyze, export coefficients, and generate MATLAB code. This is useful for rapid prototyping and education.

Real‑Time Implementation

For streaming data, use dsp.IIRFilter from the DSP System Toolbox:

hIIR = dsp.IIRFilter('Numerator', sos(:,1:3), 'Denominator', sos(:,4:6));
output = hIIR(input);   % streams sample‑by‑sample or frame‑by‑frame

Multirate Filtering

IIR filters can be used in decimation and interpolation. Use designfilt with 'lowpassiir' and then decimate or interp from the Signal Processing Toolbox.

Common Pitfalls and How to Avoid Them

  • Unstable filters: Always check pole locations. A filter with any pole on or outside the unit circle is unstable.
  • Passband edge confusion: In Butterworth design, the cutoff frequency is the 3‑dB point; in Chebyshev, it is the end of the passband ripple. Choose the right design function accordingly.
  • Overspecifying order: Using a much higher order than needed causes numerical issues without noticeable improvement. Use order‑estimation functions.
  • Ignoring phase response: If your application requires preserving signal shape, use filtfilt or switch to FIR.
  • Normalization errors: Always normalize frequencies to the Nyquist rate (Fs/2). For example, a 100 Hz cutoff at Fs=1000 Hz becomes 0.2.

Real‑World Application Example: ECG Noise Removal

Consider a noisy electrocardiogram (ECG) signal sampled at 250 Hz. You want to remove 60 Hz power‑line interference. Design a band‑stop (notch) IIR filter with a narrow notch at 60 Hz.

Fs = 250;
Wn = [58 62] / (Fs/2);   % 2 Hz notch bandwidth
[b, a] = butter(4, Wn, 'stop');

% Apply zero‑phase filtering to minimize distortion of QRS complexes
ecg_clean = filtfilt(b, a, ecg_raw);

For a sharper notch, use an elliptic design:

[b, a] = ellip(6, 1, 40, Wn, 'stop');  % 1 dB passband ripple, 40 dB stopband attenuation

Using fvtool confirms the notch depth and ensures the filter is stable.

Conclusion

IIR filters in MATLAB provide a powerful, efficient method for shaping signals. By following the systematic workflow—specification, design, validation, application, and analysis—you can create robust filters for a wide range of domains. Leverage built‑in functions like butter, cheby1, ellip, and modern interfaces like designfilt to streamline development. Always prioritize numerical stability by using second‑order sections for high orders. With practice, you’ll be able to quickly implement custom IIR filters that meet exacting requirements while keeping computational cost low.

For further reading, refer to the official MATLAB IIR Filter Design documentation and the DSP System Toolbox IIR Filter object reference. Explore also the practical introduction to digital filter design for more examples.