Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20688 Discussions

input to IIR filter in Verilog

Altera_Forum
Honored Contributor II
3,696 Views

Just a quick question regarding implementing an IIR filter in Verilog... 

 

At the moment, I am using the Wolfson ADC on the DE2-70 to convert analogue sound input from Line In to digital bits - that's all working perfectly (with a sample rate of 8000 kHz and 24-bit resolution). 

 

I understand that these 24-bit values from the ADC are in two's complement form - i.e. each sample is represented by a number between -2^23 and (2^23)-1. 

 

My question is, can this two's complement value be fed directly into a fixed-point IIR filter designed in Matlab's FDAtool? 

 

Looking at FDAtool, there are options to set the "Input Word Length" & "Input Fraction Length"... This leads me to believe that I have to convert my 24-bit two's complement value from the ADC to a fixed point value that will be 24 + no. of fraction bits long... 

 

Is this reasoning correct? 

 

It would be much appreciated if someone could point me in the right direction on this one! 

 

Cheers
0 Kudos
14 Replies
Altera_Forum
Honored Contributor II
2,105 Views

Hi, 

 

Firstly, your input of 24 bits looks too much to me unless you have some other reasons for this extra high and expensive resolution.  

 

I am not familiar with using the terms of word length and fraction length but I feel sure it means: 

 

word length = your signal resolution (at input/final output). 

fraction length = the extra bits you want internally for computation before final output is truncated back. You may choose to cover results fully at each stage of computations e.g. 16 bits * 16 bits needs 31 bits(or 32 if you wish), 

31 + 31 + 31... needs 33 bits, this can be termed a fractional width of [33 - 16 = 17], anything more is void. 

 

You can do things manually and this gives you better understanding which is the vital thing taken away from you by tools terminology. 

 

get your coeffs in floating format(fractions of 1), upscale it to your resolution with rounding. make your internal output width wide enough then truncate back to your signal width (with rounding). 

 

In any case if your computation result is > available width you must clip(not recommended).
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

The basic purpose of dividing the total length in an integer and a fraction part is to define a scaling. Without a scaling, filter coefficients have no meaning. I'm not sure about the MATLAB definition of word length, I rather expect, it means total length = integer + fraction. But I think, you have a manual with the tool. 

 

Assuming the real input data represents a range of -1..+1, then the filter must allow some headroom internally, depending on the filter Q and the used structure. Two or three additional bits left of the input range are usually sufficient. The other point has been mentioned by kaz. The filter may require additional fractional bits on the right, particularly if a high Q or a high fs/fc ratio is involved. But I'm confident, that MATLAB has a understandable documentation covering these topics. 

 

In my standard filter model, the input data except for the sign bit would go into the fractional part, having the integer bits for the said overhead. But it depends on how you are scaling the filter coefficients.
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

Hi, 

 

The above replies may sound confusing to beginners. Let me add this. My reply seems to be the hardware perspective while FvM reply seems to be the DSP(software perspective). 

 

The dsp perspective sees the values as 1 and its fractions e.g. a gain of 1 applies to an input that swings between(1, -1 across all fractions). 

 

I find it much more practical to follow the notion of hardware values directly. 

I mean: an input of 16 bits will swing between +32767 and -32767 across all integers(no meaning for fractions). the coeffs will similarly swing across their resolution of say 32767/-32767. 

 

multiplication with full room for bit growth means upscaling to +32767^2, 

additions add further bits, 1 bit per stage assuming room for full bit growth. The final output is then truncated back n bits(divided by 2^n) into 16 bits with optional rounding. 

 

The above computations does not mention filter gain. this can be tackled at coeffs scaling which need not be represented to the roof if you want unitary gain... 

 

It then remains up to you or other's tools to define the terminlogy. 

 

Remember Matlab tool is designed by software engineers with the mindset of +1 and I don't see why they should not try to see the hardware perspective when it comes to hardware deisgn.
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

I agree, that there are many possible number representations. When going to filters, it's necessary however to be clear about coefficient scaling. Using fractional numbers is one of several ways to achieve this. For several reasons, I assumed that the MATLAB fixed point tool is using a fractional number representation, but I didn't verify. The said "Input Word Length" & "Input Fraction Length" specification also suggests this understanding.

0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

Thanks for both of your replies! Cleared a few things up! :) 

 

I really should explain what I'm trying to do: 

 

All I want to do is implement a simple low-pass filter to attenuate all harmonics (except the 1st - the fundamental) from an guitar audio signal when a string is plucked - i.e. I'm making a digital guitar tuner. 

 

I've designed all the other components of the circuit and am now just trying to get the filter working. 

 

A low order IIR low-pass should be fine and shouldn't be too hard to implement... 

 

I'm just trying to figure out what to do with the fractions! 

 

For example: 

 

module test_filter(clk,filter_in,filter_out); parameter W=7; // bit width - 1 parameter signed a=0.7; input clk; input signed filter_in; output signed filter_out; reg signed x,y; initial begin x=0; y=0; end always@(posedge clk) begin x <= filter_in; y <= (1-a)*x + a*y; end assign filter_out=y; endmodule // test_filter 

This is just a test IIR filter I wrote - my question is: 

 

How would Verilog treat the 0.7 in the above code? 

Would the value of y be rounded? 

Do I need to add extra code if I want to multiply by fractions? 

 

(Also, my output from the ADC is now 8-bits (two's complement)! ;)) 

 

Cheers, 

 

Nick
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

a of 0.7 need to be scaled up for hardware: 

 

You can set (y) as 20 bits, (a) as 10 bits magnitude. then chop off output back to 8 bits by discarding LSBs of result(after optional rounding) 

 

Then a = round (0.7 * 1024) = 717 

(1-a)*x becomes x*1024 - x*717 

 

the term x*1024 = x*2^10 i.e. just insert 10 zeros infront. 

 

Figured out in a rush, I hope I am correct...
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

Thanks Kaz! 

 

Like this: 

module test_filter(clk,filter_in,filter_out); parameter W=7; // bit width - 1 parameter signed a=10'b0100000000; input clk; input signed filter_in; output signed filter_out; reg signed x,y; initial begin x=0; y=0; end always@(posedge clk) begin x <= filter_in; y <= ({x,10'b0000000000}) - (a*x) + (a*y); // y=(1-a)*x+(a*y) end assign filter_out=y; endmodule // test_filterSee anything that looks wrong there? (think there might be as my audio output is now really noisy!) 

By the way, a=0.25 in this code. 

 

Thanks!
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

 

--- Quote Start ---  

...All I want to do is implement a simple low-pass filter to attenuate all harmonics (except the 1st - the fundamental) from an guitar audio signal when a string is plucked - i.e. I'm making a digital guitar tuner. 

 

I've designed all the other components of the circuit and am now just trying to get the filter working. 

 

A low order IIR low-pass should be fine and shouldn't be too hard to implement... 

 

I'm just trying to figure out what to do with the fractions! 

 

Nick 

--- Quote End ---  

 

Why do you want to implement an IIR filter and not a FIR? If it is to get a minimal latency, then its fine, but simple to do, - NO!.  

IIR filters are deceptively difficult to implement, especially in fixed point arithmetic, as you can get internal oscillations and gross offset errors if you dont apply the proper scaling. In practice you probably find that you need surprisingly much extra internal precision. 

 

I bet this is the reason Altera abandonned their IIR filter design tool kit many years ago. 

So although you need fewer multiplications, additions and storage for an IIR compared to FIR, it is offset by the mentioned implementation difficulty and large internal word width. And be carefull not to slip additional delays into your feedback loop! This can easily happen when using pipelined building blocks, with the result that your filter will work differently than designed, but in a subtle manner. 

 

The FIR filter design tool in Quartus is excellent and your done in minutes, but if you require a filter with low latency, then IIR filter is the right and maybe more fun due to the difficulty:) - depends on your point of view. 

 

Fixed point or integer - its simply a matter of how you map the binary code to a physical value. The hardware is the same. 

Good luck
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

I don't think, that you can't use FIR filters succesfully without some minimal understanding of number representation in HDL or digital logic generally. But this has been the problem so far. A 1st order low-pass, as addressed with the above code, is the most simple filter of the world and doesn't involve issues with coefficient sensitivity or stability. 

 

I won't say: Oops, you don't manage to design a 1st order IIR, it's much easier with FIR... Also the FIR tool requires some basic knowledge of filters, e.g. relation of fs, fc and number of coefficients. Previous Altera forum discussions demonstrate some attempts to ignore these basics.
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

 

--- Quote Start ---  

Thanks Kaz! 

 

Like this: 

module test_filter(clk,filter_in,filter_out); parameter W=7; // bit width - 1 parameter signed a=10'b0100000000; input clk; input signed filter_in; output signed filter_out; reg signed x,y; initial begin x=0; y=0; end always@(posedge clk) begin x <= filter_in; y <= ({x,10'b0000000000}) - (a*x) + (a*y); // y=(1-a)*x+(a*y) end assign filter_out=y; endmodule // test_filterSee anything that looks wrong there? (think there might be as my audio output is now really noisy!) 

By the way, a=0.25 in this code. 

 

Thanks! 

--- Quote End ---  

 

 

 

Basically it looks ok. My mistake was the 20 bit width. we scaled (a) by 2^10 

but scaled (y) by 2^-8 leading to 12 dB gain. 

 

so make y 18 bits and truncate feedback to 8 bits. 

 

also note 1-a can be precomputed and scaled to 1-.25 = .75 = .75*1024 

 

check in matlab your filter cutoff: 

den = [1 -.25]; 

nu = .75; 

freqz(num,den)
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

How's this now: 

 

module test_filter(clk,filter_in,filter_out); parameter W=7; // bit width - 1 parameter signed a=10'b0100000000; //256 parameter signed one_minus_a=10'b1100000000; //768 input clk; input signed filter_in; output signed filter_out; reg signed y; reg signed x; initial begin x=0; y=0; end always@(posedge clk) begin x <= filter_in; y <= (one_minus_a*x) + (a*y); // y=(1-a)*x+(a*y) end assign filter_out=y; endmodule // test_filterThanks again!
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

My only worry is that 1100000000 assumed 768, but you made it negative. 

add sign bit, keep your scaling. 

 

I checked your filter in Matlab. it cuts off at(say .2 FS) and stop band attenuation is 4.5 dB. Is that what you want?
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

Thanks again Kaz! 

 

Basically I want a filter that, for example, can attenuate 160Hz more so than 80Hz (second and first harmonics of E string respectively). 

 

I was planning on expanding on the IIR code above to get an appropriate filter response to acheive this (so those values of "a" are just values to test with at this stage) - however that code is still giving me a VERY noisy output - something is not right. 

 

Interestingly enough, if I set "one_minus_a" to zero, I still have the input passing through the filter to the output - how can this be? 

 

module test_filter(clk,filter_in,filter_out); parameter W=7; // bit width - 1 parameter signed a=10'b0100000000; //256 parameter signed one_minus_a=11'b01100000000; //768 input clk; input signed filter_in; output signed filter_out; reg signed y; reg signed x; initial begin x=0; y=0; end always@(posedge clk) begin x <= filter_in; y <= (one_minus_a*x) + (a*y); // y=(1-a)*x+(a*y) end assign filter_out=y; endmodule // test_filter
0 Kudos
Altera_Forum
Honored Contributor II
2,105 Views

You can't expect anything but "VERY noisy output" with 8 bit data length, particularly, when the ADC input level keeps a headroom. I don't understand the purpose of using such a low resolution. 12 bit would be fair, 16 bit standard CD audio quality. 

 

 

--- Quote Start ---  

if I set "one_minus_a" to zero, I still have the input passing through the filter to the output  

--- Quote End ---  

Doesn't sound reasonable with the shown code. 

 

Regarding the said application, a first order low-pass isn't a very selective filter.
0 Kudos
Reply