Xilinx
Block Preview

Introduction

The IIR Bessel - II Order block implements a second-order IIR (Infinite Impulse Response) filter operating in real time on FPGA. The component includes automatic filter coefficient calculation based on filter type (low/high pass) and cutoff frequency.

The Bessel filter is named after German mathematician Friedrich Bessel (1784-1846), who developed the mathematical theory on which the filter is based. It is also called Bessel-Thomson filter in recognition of W. E. Thomson, who applied Bessel functions to filter design in 1949.

Pin Description

IN Input 16U/17S bit BIT VECTOR
Fixed-point number input. Supports 16-bit unsigned or 17-bit signed input based on the DataTypeIn property.
Default: Must be connected
CLK Input 1 bit BIT
Input signal used as clock. All filter operations are synchronous to this clock.
Default: Default Board Clock
RESET Input 1 bit BIT
Synchronous reset signal. Clears the filter state and all internal accumulators.
Default: Default Board Reset
OUT Output 16U/17S bit BIT VECTOR
Fixed-point number output. Same format as input (16-bit unsigned or 17-bit signed).

Properties

Property window

Type of filter Type

Select between low pass and high pass filter

Filter type selection. Available values: Low Pass, High Pass, default Low Pass.

Default: Low Pass

Options: Low Pass High Pass

Cutoff (KHz) Cutoff

Set the filter pole/zero position according to the selected bandwidth in KHz

Cutoff frequency in kHz. Must be less than half the sampling frequency (Nyquist limit).

Default: 1000

Input data type DataTypeIn

Select input data type

Input data format selection. Available values: Unsigned 16 bit, Signed 17 bit, default Unsigned 16 bit.

Default: UINT16

Options: UINT16 INT17

Usage

Bessel Filter Characteristics

The Bessel filter has a maximally flat group delay (maximally linear phase response), which preserves the wave shape of filtered signals in the passband. Key characteristics include:

  • Linear Phase Response: Minimizes signal distortion in time domain
  • Low Overshoot: Much less overshoot than Butterworth or Chebyshev filters
  • Gaussian-like Response: Impulse response tends towards Gaussian as filter order increases
  • Smooth Transition: Gentle roll-off between passband and stopband

Bessel frequency response


Digital Implementation Note

The Bessel filter is inherently an analog filter. This implementation generates digital Bessel filters using the bilinear transform, which does not perfectly preserve the phase response of the analog filter. The phase response is only approximately correct at frequencies below about fs/4.


Scattered Lookahead Implementation

To enable real-time FPGA operation at full clock rate, the filter uses the Scattered Lookahead technique. This transforms the recursive IIR structure to allow pipelined parallel processing:

IIR block diagram

The standard IIR equation:

$$ y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] - a_1 y[n-1] - a_2 y[n-2] $$

Is transformed using scattered lookahead to:

Scattered lookahead structure

$$ y[j] = \sum_{k=0}^{6} b’_k x[j-k] - a’_3 y[j-3] - a’_6 y[j-6] $$

Reference: A universal look-ahead algorithm for pipelining IIR filters


Coefficient Calculation

SciCompiler automatically calculates the filter coefficients using the internal filter calculator tool. The following Python code provides a reference implementation for offline simulation:

python
  import numpy as np
from scipy import signal

def scattered_lookahead_transform(a):
    A = np.array([[a[0], 0,    0,    0,      0,   ],
                  [a[1], a[0], 0,    0,      0,   ],
                  [a[2], a[1], a[0], 0,      0,   ],
                  [0,    0,    a[2], a[1], a[0],  ],
                  [0,    0,    0,    a[2], a[1],  ]])
    A_inv = np.linalg.inv(A)
    D = A_inv * [1, 0, 0, 0, 0]
    D1 = D[:,0]
    D = D[:,0].reshape(-1, 1)

    R = np.array([[ 0,   a[2], a[1],  a[0],  0,  ],
                  [0,   0,    0,    0,     a[2]]])

    Qw = np.dot(R, D)

    an = [1, Qw[0][0], Qw[1][0]]
    bn = D1
    return bn, an

N = 2               # Order of the filter
fs = 250*1e6        # Sampling frequency
fc = 5*1e6          # Corner frequency
Wn = fc/(fs/2)

b_z, a_z = signal.bessel(N, Wn, btype='low')

print("original", b_z, a_z)
bn, an = scattered_lookahead_transform(a_z)

bq = np.convolve(bn, b_z)
aq = an

print("scattered", bq, aq)
  

Typical Applications

  • Signal conditioning with minimal pulse distortion
  • Anti-aliasing filters requiring low overshoot
  • Audio and measurement systems requiring linear phase
  • Nuclear pulse processing where pulse shape preservation is critical

Resources & Timing

  • Latency: 8 clock cycles