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

Edit: Messed up the picture, attached is a better one. If some admin could replace it it would be great.

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

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