# [SOLVED]FIR filter with a precision of 3 decimal places

Status
Not open for further replies.

#### deepsetan

Hi guys,

How can I modify my FIR filter to have an input and output that have a precision of 3 decimal places. I already constructed floating point computation but I dont know on how to link it with my filter in verilog. This is my code for FIR filter:

Code Verilog - [expand]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
module FIR_filter
#(parameter STAGES = 4)
(
input   CLK,
input   RST,
input   [7:0] Xin,
output  [7:0] Xin_LED,
output reg [7:0] Xout
);

reg [7:0] STORE [STAGES-1:0];
reg [15:0] ACC;
integer i;

always @(negedge RST, negedge CLK)
begin
if(!RST) for(i = 0; i < STAGES; i = i + 1) STORE[i] <= 0;
else
begin
for(i = 0; i < (STAGES-1); i = i + 1) STORE[i] <= STORE[i+1];
STORE[3] <= Xin;
end
end

always @*
begin
ACC = 0;
for(i = 0; i < STAGES; i = i + 1) ACC = ACC + STORE[i];
Xout = ACC / STAGES;
end

assign Xin_LED = Xin;
endmodule

- - - Updated - - -

This is my block diagram for floating computation system

Last edited by a moderator:

#### KlausST

##### Super Moderator
Staff member
Hi

3 decimal places gives 0....999 it is about equal to 10 bits resolution. (2^10 = 1024)

Therfore a input data width of 8 bit (like input[7:0]) can´t give an output with 10 bits precision.

***
For sure you can use low pass filters or averaging filters to gain some sub-LSBs of resolution.
* But not with a 4 stage FIR filter.
* and while you may gain some bits of resolution you can not improve precision.

To improve resolution i think an IIR filter is the better solution, because you are more flexible to shift cutoff frequency down.

****
From your text above it seems all your filter coefficients are set to 1, so it effectively gives a moving average filter of 4 samples.
That´s a simple form of FIR filter.

****
In your schematic it seems you work with 32 bits of resolution.
but you have to take care about the values in the data bus (how many integer bits / and fractional bits). This is necessary not to loose precision while cutting off frationals nor to get an overflow.

****

Maybe you could tell more about your application and what you wanted to achieve.

Klaus

#### deepsetan

Hi

3 decimal places gives 0....999 it is about equal to 10 bits resolution. (2^10 = 1024)

Therfore a input data width of 8 bit (like input[7:0]) can´t give an output with 10 bits precision.

***
For sure you can use low pass filters or averaging filters to gain some sub-LSBs of resolution.
* But not with a 4 stage FIR filter.
* and while you may gain some bits of resolution you can not improve precision.

To improve resolution i think an IIR filter is the better solution, because you are more flexible to shift cutoff frequency down.

****
From your text above it seems all your filter coefficients are set to 1, so it effectively gives a moving average filter of 4 samples.
That´s a simple form of FIR filter.

****
In your schematic it seems you work with 32 bits of resolution.
but you have to take care about the values in the data bus (how many integer bits / and fractional bits). This is necessary not to loose precision while cutting off frationals nor to get an overflow.

****

Maybe you could tell more about your application and what you wanted to achieve.

Klaus

Hi

Thanks Klaus. Actually, I want to create FIR filter that can handle input and output that have 3 decimal places. How can I assign my input and output to handle that 3 decimal places?

#### KlausST

##### Super Moderator
Staff member
Hi,

Actually, I want to create FIR filter that can handle input and output that have 3 decimal places. How can I assign my input and output to handle that 3 decimal places?

you need at least 10 bit wide input, at least internal 12 bit calculation width..

********
Please tell us more what you want to do.
Were is the input data from?
What do you want to output?

Klaus

#### deepsetan

Sorry because I'm making u confusing. Let say I set up the parameter as 4 stages.The input is gonna be switch SW0-SW7 (8bit) and the output is just LEDG0-LEDG7 (8bit) from FPGA. I also assigned two buttons as CLK and RESET. Let say if I switch on SW3 which is equal to 8, so it will take that 8 and it will be divided with 4 where 4 is my no of stages. So if I press CLK once, the LEDG1 will turn on because 8/4=2 and LEDG1=2. Thats how my filter works. So from all of this, how can I make my input and output to handle a number with 3 decimal places? The input and output are just switch and LED from the FPGA itself. Let say if I want to handle input like 8.432 so it will be 8.201/4 =2.050.

#### KlausST

##### Super Moderator
Staff member
Hi,

still some confusions.
* i don´t see how the value from 8.432 goes to 8.201
* where does the 8.432 come from?

it comes into my mind that it is not a filter problem but a problem how to represent non-integer values to a digital system (here FPGA).

****

8.432 has not only 3 digits. It has one integer digit and 3 fractional digits, in total 4 digits. So you need a resolution of more than 13 bits.

****
representation of non_integer values.
* either like an ADC with dig_value = inputvoltage * 2^8 / VRange ; where the "8" is the ADC resolution in bits.
* or you treat it as integers in millivolts..

****

Klaus

##### Super Moderator
Staff member
Code:
always @*
begin
ACC = 0;
for(i = 0; i < STAGES; i = i + 1) ACC = ACC + STORE[i];
Xout = ACC / STAGES;
end

This will synthesize to a huge mess and may not work. The ACC = ACC + STORE requires ACC be stored between itterations of the for loop as it's unrolled, therefore you've just produced a cascade of adds if the synthesis tool is any good. And divides other than 2,4,8,16,...(i.e. binary) can't be implemented using '/'.

This code looks like quasi software Verilog, which is never a good thing.

#### deepsetan

Actually, 8.432 is the input that you can set from the switch. Like I mentioned before, I can set up any input that I want such as 2,3,4,5 etc. If I want the input value is 8, so I will switch on SW3, if I want input value 3, so I need to turn on SW1 and SW0. This is how the input works. For easy understanding, I just can say that this filter code will do averaging process. If my input is 8, so for the output when I press the CLK once, it will take that 8(input value) and divide it by 4(number of stages) and this will make LEDG1=2 turn on. So if I press the CLK for the second time, it will become (8+8)/4 and the LEDG3=4 will turn on. I already changed the #parameter STAGES = 2**(input) so the input will always become 2,4,8 etc. For real number this code will works. The problem is let say if I want to handle input value that involving floating point like 8.432.

- - - Updated - - -

Code:
always @*
begin
ACC = 0;
for(i = 0; i < STAGES; i = i + 1) ACC = ACC + STORE[i];
Xout = ACC / STAGES;
end

This will synthesize to a huge mess and may not work. The ACC = ACC + STORE requires ACC be stored between itterations of the for loop as it's unrolled, therefore you've just produced a cascade of adds if the synthesis tool is any good. And divides other than 2,4,8,16,...(i.e. binary) can't be implemented using '/'.

This code looks like quasi software Verilog, which is never a good thing.

What do you mean by that quasi software verilog?

#### KlausST

##### Super Moderator
Staff member
Hi,

Actually, 8.432 is the input that you can set from the switch.
Ok.
Please tell us the switch setting fot 8.432.
.and the total number of inputs(switches).

Klaus

##### Super Moderator
Staff member
What do you mean by that quasi software verilog?
well for one thing using a for loop to generate an accumulator, is the software way of doing it. In hardware you use a register feed by an adder with one of the adder inputs connected to the register output.

#### deepsetan

Hi,

Ok.
Please tell us the switch setting fot 8.432.
.and the total number of inputs(switches).

Klaus

Hi Klaus. Thanks for reminding me about the 8 bits. Today I changed the 8 bits to 17 bits. So basically I'm just using Q7.10 format to handle the 3 decimal places and it works!

#### KlausST

##### Super Moderator
Staff member
Hi,

well done.

now you have
* no sign (unsigned input value)
* 7 bits of integer value : 0..127
* 10 bits of fractional value: 0...1023 / 1024

if states > 1 then you need an extra integer bit for internal calculations: Q8.10
if states > 3 then you need 2 extra integer bit for internal calculations: Q9.10
if states > 7 then you need 3 extra integer bit for internal calculations: Q10.10
if states > 15 then you need 4 extra integer bit for internal calculations: Q11.10

to prevent from overflow.

Klaus

deepsetan

Points: 2