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] FIR filter with a precision of 3 decimal places

Status
Not open for further replies.

deepsetan

Advanced Member level 4
Joined
May 8, 2013
Messages
119
Helped
6
Reputation
12
Reaction score
5
Trophy points
1,298
Location
Malaysia
Activity points
2,137
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

floating computation.png
 
Last edited by a moderator:

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

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?
 

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
 

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.
 

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).

****
Maybe the 8.432 is a voltage reading from an ADC. But an ADC will send out integer values. --> then read how ADCs work and about their data format.

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..

****

In the end we need more information...

Klaus
 

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.
 

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?
 

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
 

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.
 

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!
 

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
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top