# Forum: FPGA, VHDL & Verilog First order IIR low pass - quantization prevents full output range

Rate this post
 0 ▲ useful ▼ not useful
I'm quite new to VHDL and I'm struggling with a first order low pass
filter I want to implement. In a naive attempt, I wanted to implement
the following equation in VHDL:



In my VHDL code I did the following:
 process (Clk) begin if rising_edge(Clk) then if Rst = '0' then AccuP <= (others => '0'); else AccuP <= AccuN; end if; end if; end process; process(AccuP, DataIn, FiltAlpha, FiltBeta) begin AccuN <= resize(shift_right(unsigned(FiltBeta)*unsigned(AccuP) + unsigned(FiltAlpha)*unsigned(DataIn), 16), AccuN'length); end process; 

where
FiltAlpha = a * 2^16 = 14559
FiltBeta = 2^16-FiltAlpha = 50977

Since the filter coefficient a lies between 0 and 1, I had to upscale
it, i.e. I multiplied my filter coefficient with 2^16, carried out the
fixed point multiplication and shifted the result to the right 16 times.

This is somehow "working", meaning that if I plot a step response I get
the expected exponential output signal, although I'm not sure about the
delay visible between sample 500 and 1000. The input step jumps from 0
to 4095 at 0.

The problem I face now is, that the final value of the result does not
converge to 4095 as I'd expect, in fact it stops at 4091. This is caused
by the right shift operation in the code above, where due to rounding I
lose the fractional bits.

I couldn't really find a way to avoid this problem. So my questions
basically are:
- How to get rid of this, i.e. how do I implement a filter which will
reach the full output signal? What would be the "correct" way of
implementing such a filter?
- Could I just accept it or is their some additional problems with my
implementation I overlook at the moment?

: Moved by Moderator

Rate this post
 0 ▲ useful ▼ not useful
Edit: Messed up the picture, attached is a better one. If some admin
could replace it it would be great.

Rate this post
 0 ▲ useful ▼ not useful
VHDL Newbie schrieb:
> This is caused
> by the right shift operation in the code above, where due to rounding I
> lose the fractional bits.
What if you add 1/2 before cutting the bits?

Duke

Rate this post
 0 ▲ useful ▼ not useful
VHDL Newbie schrieb:
  process(AccuP, DataIn, FiltAlpha, FiltBeta) begin AccuN <= resize(shift_right(unsigned(FiltBeta)*unsigned(AccuP) + unsigned(FiltAlpha)*unsigned(DataIn), 16), AccuN'length); end process; 
Why a process?
Do such things concurrent will reduce the risc of incomplete sensitivity
lists:
 -- process(AccuP, DataIn, FiltAlpha, FiltBeta) -- begin AccuN <= resize(shift_right(unsigned(FiltBeta)*unsigned(AccuP) + unsigned(FiltAlpha)*unsigned(DataIn), 16), AccuN'length); -- end process; 

And why not using unsigned vectors for the accus to get rid of that
conversions back and forth?

VHDL Newbie schrieb:
> - How to get rid of this, i.e. how do I implement a filter which will
> reach the full output signal?
You must implement an "internal" accumulator with more bits than you
have to output to sum up the lower bits also. So simply use internally a
20 bit accu for summation and pass the high bits to the upper level.

Duke Scarring schrieb:
> What if you add 1/2 before cutting the bits?
Thats somehow the same way: add one bit to the vectors length...  ;-)

VHDL Newbie schrieb:
> In a naive attempt, I wanted to implement the following equation in
> VHDL
By selecting "nice binary" values it is fairly easy to avoid rounding
error:
http://www.lothar-miller.de/s9y/categories/58-Filter
Try google translator, its German.

• $formula (LaTeX syntax)$