Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Scaling of IIR filter coefficients for Fixed-Point FPGA implementation of filter

Status
Not open for further replies.

nkinar

Member level 2
Joined
Jul 25, 2009
Messages
44
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,675
I've designed a biquad IIR filter, and I would like to quantize the filter coefficients so that the difference equation can be used in a fixed-point FPGA code written in Verilog. The filter input ranges between 0 and ((2^12) -1) fixed-point values. The difference equation is Direct Form I (https://en.wikipedia.org/wiki/Digital_biquad_filter), and consists of additions, subtractions, and weighting values (coefficients).

The filter coefficients have been designed in Matlab as floating point values. How do I convert these floating point values to fixed-point that can be used in the Verilog code? Here is an example of the SOS matrix (https://www.mathworks.com/help/toolbox/signal/ref/sos2tf.html) with the filter coefficients.

Code:
1.0000    2.0302    1.0305    1.0000   -1.7596    0.7749
1.0000    2.0002    1.0005    1.0000   -1.8143    0.8301
1.0000    1.9696    0.9700    1.0000   -1.9175    0.9343

Here are the filter coefficients in [a,b] format:

Code:
a =

    1.0000   -5.4914   12.5848  -15.4051   10.6225   -3.9118    0.6010

b =

    1.0000    6.0000   15.0000   20.0000   15.0000    6.0000    1.0000

The [a,b] coefficients serve as the weights (https://en.wikipedia.org/wiki/Digital_biquad_filter), and the y(n) is the output value.
 

Converting float to fixed is fairly well known process. Some time on google will help.

But FDATool will do this for you :) Probably will save you some time (though you won't learn how to do it).
 

first, look at the spread of the values. Its around 6b for the integer portion (20 to -15). If you want 10b of fractional precision, then you have round((2**10) * k) for each of the values. This will give you a 16b value, where 1.0 = 1024 Keep in mind that "round" must be done carefully, as the implementation may result in the quantized coefficients giving an undesirable or even unstable impulse response. It is possible that you will need to round a 1.3 up to 2.0, or a 2.9 down to 2.0. Likewise, you might find that you'll want more fractional bits in order to allow the poles to be placed closer to the desired locations. In the hardware, you might have 12x16 multiplications. After the multiplication, you will need to (eventually) round the value by removing the lower bits. eg, a multiply by 1 would be x * 1024. the result would be 28b, and the lower 10b would be removed. This doesn't need to occur immediately though. you might have a 12x16 multiply (28b) followed by a 16b multiply (34b -- 20 fractional bits at this point). Eventually, you'll need to remove some fractional bits, as this is a recursive system.
 
  • Like
Reactions: nkinar

    nkinar

    Points: 2
    Helpful Answer Positive Rating
Thanks, permute; this is exactly what I was looking for.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top