Skip to content

delhatch/Multi_IIR

Repository files navigation

Multi_IIR

Author

Del Hatch

** Multi-band IIR filter

The purpose of this project is to demonstrate taking a single IIR filter core (in Verilog, in the PL fabric), and time-multiplexing it into a multi-band filter.

In the pictures below, it shows a 27-band filter being implemented with the single IIR filter. Every third band is set to +12 dB, with a Q of one-third octave. The first picture shows just the lower bands, and the second picture shows all bands operating.

screenshot screenshot

The spectrum analyzer I am using has reduced resolution in the lower bands, so the first picture shows that all filters (even the the lower bands that look wonky in the lower picture) are operating properly.


screenshot

All bands set flat.


screenshot

All bands flat except for the 1 kHz band, set to +12 dB, with Q of one-third octave.


** Core

This project builds on my previous project at https://github.com/delhatch/IIR_EQ

The IIR filter is implemented using integer coefficients. (Only fixed-point operations, no floating point.)

** EQ Module

The module called "eq_core_0" receives the incoming signal. To create a multi-band from a single IIR filter core, a few memory instances are required to hold the coefficients for each filter, and to store the intermediate results (IIR filter Z-1 and Z-2 terms).

The module "blk_mem_gen_0" is a standard BRAM IP module, and is used to hold the coefficients for each band. Each IIR filter uses four terms (a1, a2, b1, b2) and each is 32 bits wide. So the width of this memory is 128 bits, and 30 words deep -- one word for each filter band.

The Z-1 and Z-2 terms are stored in block RAM instances in the eq_module itself.

The filter works by calling up a set of coefficients and the Z terms, and calculating a result, and writing back the new Z-1 and Z-2 terms to memory. The entire operation takes 2 clock cycles.

So the 27-band filter implimented in this project takes only 54 clock cycles to execute all filter operations.

** Calculating the Coefficients

Whenever the center frequency or boost/cut amount is changed, the IIR filter needs new coefficients. These are calculated in C code, in floating point format.

The filter operates using fixed-point integer math for efficiency, so the C code converts the coeeficients to a 32-bit fractional integer word, and then sends them to registers in the eq_core_0 module.

** Create Project

In Vivado 2017.4, build the system as shown in the system_diagram.jpg file.

system diagram

It requires three IP cores, in the folders "axi_i2s_transmitter" "eq_core" and "axi_i2s_receiver_1.0" respectively.

To change the filter parameters, edit the C code, compile and run. The new coefficients will be sent to the IIR filter.

** Improvements

This project is mainly a demonstration of how to create a multi-band IIR filter in the PL fabric, and how to implement it using integer math.

The data words are very wide, due to the fact that IIR filters are inefficient at very low frequencies (referenced to the sample rate) causing the intermediate filter values get very large. For example, the audio words are all less than 1.0, and coefficients are never greater that 1.99999, but even so, in the low bands, nodes can see values around 800,000.(!)

So one improvement would be to use a filter and decimate to reduce the sample rate for the low band. This would keep node values to under one hundred, meaning that the word widths could be reduced by ~13 bits, which would reduce the multiplier output width by twice that.

About

Multi-band IIR filter in Verilog. Uses time-domain multiplexing of a single, fixed-point, IIR filter to create a 27-band filter.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published