# Problems implementing IIR filter in VHDL

I am having some difficulty making an IIR filter in VHDL work as expected.

I have implemented it by shifting the coefficients by a certain number of bits (in this case 27 bits). The outputs are then shifted down by 27 bits (divided by 2**27).

I have used this technique before for FIR Filters and I had no problems with this.

The IIR filter I am implementing has

b = [0.00064358, -0.00242575,  0.00292915,  0., -0.00292915, 0.00242575, -0.00064358]

a = [1, -5.63188602,  13.54589678, -17.77915863,  13.42490039, -5.53172386,   0.97344184]


I have stripped the 1 off of a since this is the term multiplying $y[n]$ and results in the output.

so I then have

a = [-5.63188602,  13.54589678, -17.77915863,  13.42490039, -5.53172386,   0.97344184]


So I am left with

$$y[n] = b[0]\cdot x[0] + b[1]\cdot x[1] + ... - a[0]\cdot y[n-1] - a[1]\cdot y[n-2] - \ldots$$

Where $y[n]$ is the output of my IIR filter.

I am simulating the design and getting the following results.

I am seeing the output be MUCH larger than expected (I suspect it is getting so large is is overflowing and therefore wrapping around.)

When I perform a similar filter in python I get much smaller results and end up with a nice filtered sine wave. I am unsure why this is occurring.

The details of the first 20 iterations can be seen below.

Input No: 2  Output: 0
b[0] * : x[n-0] :86380, 0
b[1] * : x[n-1] :-325579, 0
b[2] * : x[n-2] :393144, 0
b[3] * : x[n-3] :0, 0
b[4] * : x[n-4] :-393144, 0
b[5] * : x[n-5] :325579, 0
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, 0
a[1] * : y[n-2] :1818099489, 0
a[2] * : y[n-3] :1908689019, 0
a[3] * : y[n-4] :1801859629, 0
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = 0
Input No: 3  Output: 0
b[0] * : x[n-0] :86380, 992
b[1] * : x[n-1] :-325579, 0
b[2] * : x[n-2] :393144, 0
b[3] * : x[n-3] :0, 0
b[4] * : x[n-4] :-393144, 0
b[5] * : x[n-5] :325579, 0
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, 0
a[1] * : y[n-2] :1818099489, 0
a[2] * : y[n-3] :1908689019, 0
a[3] * : y[n-4] :1801859629, 0
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = 0
Input No: 4  Output: 0
b[0] * : x[n-0] :86380, 1924
b[1] * : x[n-1] :-325579, 992
b[2] * : x[n-2] :393144, 0
b[3] * : x[n-3] :0, 0
b[4] * : x[n-4] :-393144, 0
b[5] * : x[n-5] :325579, 0
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, 0
a[1] * : y[n-2] :1818099489, 0
a[2] * : y[n-3] :1908689019, 0
a[3] * : y[n-4] :1801859629, 0
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = -2
Input No: 5  Output: 0
b[0] * : x[n-0] :86380, 2736
b[1] * : x[n-1] :-325579, 1924
b[2] * : x[n-2] :393144, 992
b[3] * : x[n-3] :0, 0
b[4] * : x[n-4] :-393144, 0
b[5] * : x[n-5] :325579, 0
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, -2
a[1] * : y[n-2] :1818099489, 0
a[2] * : y[n-3] :1908689019, 0
a[3] * : y[n-4] :1801859629, 0
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = -12
Input No: 6  Output: -2
b[0] * : x[n-0] :86380, 3376
b[1] * : x[n-1] :-325579, 2736
b[2] * : x[n-2] :393144, 1924
b[3] * : x[n-3] :0, 992
b[4] * : x[n-4] :-393144, 0
b[5] * : x[n-5] :325579, 0
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, -12
a[1] * : y[n-2] :1818099489, -2
a[2] * : y[n-3] :1908689019, 0
a[3] * : y[n-4] :1801859629, 0
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = -40
Input No: 7  Output: -12
b[0] * : x[n-0] :86380, 3804
b[1] * : x[n-1] :-325579, 3376
b[2] * : x[n-2] :393144, 2736
b[3] * : x[n-3] :0, 1924
b[4] * : x[n-4] :-393144, 992
b[5] * : x[n-5] :325579, 0
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, -40
a[1] * : y[n-2] :1818099489, -12
a[2] * : y[n-3] :1908689019, -2
a[3] * : y[n-4] :1801859629, 0
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = -35
Input No: 8  Output: -40
b[0] * : x[n-0] :86380, 3992
b[1] * : x[n-1] :-325579, 3804
b[2] * : x[n-2] :393144, 3376
b[3] * : x[n-3] :0, 2736
b[4] * : x[n-4] :-393144, 1924
b[5] * : x[n-5] :325579, 992
b[6] * : x[n-6] :-86380, 0
a[0] * : y[n-1] :-755898946, -35
a[1] * : y[n-2] :1818099489, -40
a[2] * : y[n-3] :1908689019, -12
a[3] * : y[n-4] :1801859629, -2
a[4] * : y[n-5] :-742455408, 0
a[5] * : y[n-6] :130653152, 0
y = 542
Input No: 9  Output: -35
b[0] * : x[n-0] :86380, 3928
b[1] * : x[n-1] :-325579, 3992
b[2] * : x[n-2] :393144, 3804
b[3] * : x[n-3] :0, 3376
b[4] * : x[n-4] :-393144, 2736
b[5] * : x[n-5] :325579, 1924
b[6] * : x[n-6] :-86380, 992
a[0] * : y[n-1] :-755898946, 542
a[1] * : y[n-2] :1818099489, -35
a[2] * : y[n-3] :1908689019, -40
a[3] * : y[n-4] :1801859629, -12
a[4] * : y[n-5] :-742455408, -2
a[5] * : y[n-6] :130653152, 0
y = 4245
Input No: 10  Output: 542
b[0] * : x[n-0] :86380, 3616
b[1] * : x[n-1] :-325579, 3928
b[2] * : x[n-2] :393144, 3992
b[3] * : x[n-3] :0, 3804
b[4] * : x[n-4] :-393144, 3376
b[5] * : x[n-5] :325579, 2736
b[6] * : x[n-6] :-86380, 1924
a[0] * : y[n-1] :-755898946, 4245
a[1] * : y[n-2] :1818099489, 542
a[2] * : y[n-3] :1908689019, -35
a[3] * : y[n-4] :1801859629, -40
a[4] * : y[n-5] :-742455408, -12
a[5] * : y[n-6] :130653152, -2
y = 17535
Input No: 11  Output: 4245
b[0] * : x[n-0] :86380, 3080
b[1] * : x[n-1] :-325579, 3616
b[2] * : x[n-2] :393144, 3928
b[3] * : x[n-3] :0, 3992
b[4] * : x[n-4] :-393144, 3804
b[5] * : x[n-5] :325579, 3376
b[6] * : x[n-6] :-86380, 2736
a[0] * : y[n-1] :-755898946, 17535
a[1] * : y[n-2] :1818099489, 4245
a[2] * : y[n-3] :1908689019, 542
a[3] * : y[n-4] :1801859629, -35
a[4] * : y[n-5] :-742455408, -40
a[5] * : y[n-6] :130653152, -12
y = 1037
Input No: 12  Output: 17535
b[0] * : x[n-0] :86380, 2348
b[1] * : x[n-1] :-325579, 3080
b[2] * : x[n-2] :393144, 3616
b[3] * : x[n-3] :0, 3928
b[4] * : x[n-4] :-393144, 3992
b[5] * : x[n-5] :325579, 3804
b[6] * : x[n-6] :-86380, 3376
a[0] * : y[n-1] :-755898946, 1037
a[1] * : y[n-2] :1818099489, 17535
a[2] * : y[n-3] :1908689019, 4245
a[3] * : y[n-4] :1801859629, 542
a[4] * : y[n-5] :-742455408, -35
a[5] * : y[n-6] :130653152, -40
y = -4574
Input No: 13  Output: 1037
b[0] * : x[n-0] :86380, 1472
b[1] * : x[n-1] :-325579, 2348
b[2] * : x[n-2] :393144, 3080
b[3] * : x[n-3] :0, 3616
b[4] * : x[n-4] :-393144, 3928
b[5] * : x[n-5] :325579, 3992
b[6] * : x[n-6] :-86380, 3804
a[0] * : y[n-1] :-755898946, -4574
a[1] * : y[n-2] :1818099489, 1037
a[2] * : y[n-3] :1908689019, 17535
a[3] * : y[n-4] :1801859629, 4245
a[4] * : y[n-5] :-742455408, 542
a[5] * : y[n-6] :130653152, -35
y = -15447
Input No: 14  Output: -4574
b[0] * : x[n-0] :86380, 500
b[1] * : x[n-1] :-325579, 1472
b[2] * : x[n-2] :393144, 2348
b[3] * : x[n-3] :0, 3080
b[4] * : x[n-4] :-393144, 3616
b[5] * : x[n-5] :325579, 3928
b[6] * : x[n-6] :-86380, 3992
a[0] * : y[n-1] :-755898946, -15447
a[1] * : y[n-2] :1818099489, -4574
a[2] * : y[n-3] :1908689019, 1037
a[3] * : y[n-4] :1801859629, 17535
a[4] * : y[n-5] :-742455408, 4245
a[5] * : y[n-6] :130653152, 542
y = -22859
Input No: 15  Output: -15447
b[0] * : x[n-0] :86380, -500
b[1] * : x[n-1] :-325579, 500
b[2] * : x[n-2] :393144, 1472
b[3] * : x[n-3] :0, 2348
b[4] * : x[n-4] :-393144, 3080
b[5] * : x[n-5] :325579, 3616
b[6] * : x[n-6] :-86380, 3928
a[0] * : y[n-1] :-755898946, -22859
a[1] * : y[n-2] :1818099489, -15447
a[2] * : y[n-3] :1908689019, -4574
a[3] * : y[n-4] :1801859629, 1037
a[4] * : y[n-5] :-742455408, 17535
a[5] * : y[n-6] :130653152, 4245
y = 27887
Input No: 16  Output: -22859
b[0] * : x[n-0] :86380, -1472
b[1] * : x[n-1] :-325579, -500
b[2] * : x[n-2] :393144, 500
b[3] * : x[n-3] :0, 1472
b[4] * : x[n-4] :-393144, 2348
b[5] * : x[n-5] :325579, 3080
b[6] * : x[n-6] :-86380, 3616
a[0] * : y[n-1] :-755898946, 27887
a[1] * : y[n-2] :1818099489, -22859
a[2] * : y[n-3] :1908689019, -15447
a[3] * : y[n-4] :1801859629, -4574
a[4] * : y[n-5] :-742455408, 1037
a[5] * : y[n-6] :130653152, 17535
y = 15547
Input No: 17  Output: 27887
b[0] * : x[n-0] :86380, -2348
b[1] * : x[n-1] :-325579, -1472
b[2] * : x[n-2] :393144, -500
b[3] * : x[n-3] :0, 500
b[4] * : x[n-4] :-393144, 1472
b[5] * : x[n-5] :325579, 2348
b[6] * : x[n-6] :-86380, 3080
a[0] * : y[n-1] :-755898946, 15547
a[1] * : y[n-2] :1818099489, 27887
a[2] * : y[n-3] :1908689019, -22859
a[3] * : y[n-4] :1801859629, -15447
a[4] * : y[n-5] :-742455408, -4574
a[5] * : y[n-6] :130653152, 1037
y = 19333
Input No: 18  Output: 15547
b[0] * : x[n-0] :86380, -3080
b[1] * : x[n-1] :-325579, -2348
b[2] * : x[n-2] :393144, -1472
b[3] * : x[n-3] :0, -500
b[4] * : x[n-4] :-393144, 500
b[5] * : x[n-5] :325579, 1472
b[6] * : x[n-6] :-86380, 2348
a[0] * : y[n-1] :-755898946, 19333
a[1] * : y[n-2] :1818099489, 15547
a[2] * : y[n-3] :1908689019, 27887
a[3] * : y[n-4] :1801859629, -22859
a[4] * : y[n-5] :-742455408, -15447
a[5] * : y[n-6] :130653152, -4574
y = -10266
Input No: 19  Output: 19333
b[0] * : x[n-0] :86380, -3616
b[1] * : x[n-1] :-325579, -3080
b[2] * : x[n-2] :393144, -2348
b[3] * : x[n-3] :0, -1472
b[4] * : x[n-4] :-393144, -500
b[5] * : x[n-5] :325579, 500
b[6] * : x[n-6] :-86380, 1472
a[0] * : y[n-1] :-755898946, -10266
a[1] * : y[n-2] :1818099489, 19333
a[2] * : y[n-3] :1908689019, 15547
a[3] * : y[n-4] :1801859629, 27887
a[4] * : y[n-5] :-742455408, -22859
a[5] * : y[n-6] :130653152, -15447
y = -10777
Input No: 20  Output: -10266
b[0] * : x[n-0] :86380, -3928
b[1] * : x[n-1] :-325579, -3616
b[2] * : x[n-2] :393144, -3080
b[3] * : x[n-3] :0, -2348
b[4] * : x[n-4] :-393144, -1472
b[5] * : x[n-5] :325579, -500
b[6] * : x[n-6] :-86380, 500
a[0] * : y[n-1] :-755898946, -10777
a[1] * : y[n-2] :1818099489, -10266
a[2] * : y[n-3] :1908689019, 19333
a[3] * : y[n-4] :1801859629, 15547
a[4] * : y[n-5] :-742455408, 27887
a[5] * : y[n-6] :130653152, -22859
y = -32159
Input No: 21  Output: -10777
b[0] * : x[n-0] :86380, -3992
b[1] * : x[n-1] :-325579, -3928
b[2] * : x[n-2] :393144, -3616
b[3] * : x[n-3] :0, -3080
b[4] * : x[n-4] :-393144, -2348
b[5] * : x[n-5] :325579, -1472
b[6] * : x[n-6] :-86380, -500
a[0] * : y[n-1] :-755898946, -32159
a[1] * : y[n-2] :1818099489, -10777
a[2] * : y[n-3] :1908689019, -10266
a[3] * : y[n-4] :1801859629, 19333
a[4] * : y[n-5] :-742455408, 15547
a[5] * : y[n-6] :130653152, 27887
y = -24293

• I did not study this in detail but my suspicion is you are facing issues with finite precision arithmetic. If you implemented this in Python using floating point, then that give further weight to my suspicions. IIR filters are more challenging in that they have poles in their implementation, and it is feasible (and likely as filter order increases) that when quantized, some of these poles can cross over to the right half plane resulting in instability such as what you describe. If this is indeed happening, one common solution is to factor your filter into separate "bi-quad" sections.... – Dan Boschen Feb 14 '17 at 4:10
• Thanks for your answer, I was aware that it was likely due to using fixed point arithmetic but was unaware of the issue of poles crossing over, I'll take a look at how to implement the filter as bi-quad sections. – SomeRandomPhysicist Feb 14 '17 at 7:43
• I ran out of characters to elaborate further, but basically factor the filter into 2nd order polynomials which are the biquad filters: a filter described as a polynomial, with its polynomial multiplied by another polynomial of another filter, is identical in implementation to two filters in cascade: if you cascade two filters you convolve the coefficients to make an equivalent single filter. If you multiply two polynomials, you convolve the coefficients. High order polynomials are very sensitive to small changes due to quantization. See en.wikipedia.org/wiki/Digital_biquad_filter – Dan Boschen Feb 14 '17 at 12:10
• Further, and what be most likely, in actual implementation with high order IIR's delay in the feedback path accumulates, which causes instability (consistent with description above, the poles go to the right half plane, but this effect is due to delay in the FPGA not necessarily quantization). The reduction to bi-quad sections helps with this as well, very much, as it isolates each filter to smaller sections. If you confirm that either of these theories has merit, let me know and I will elaborate in the answer section so that we can close this. – Dan Boschen Feb 14 '17 at 12:13