\$\begingroup\$

The simplest low pass FIR filter you can try is y(n) = x(n) + x(n-1). You can implement this quite easily in VHDL. Below is a very simple block diagram of the hardware you want to implement.

According to the formula, you need the current and previous ADC samples in order to get the appropriate output. What you should do is to latch the incoming ADC samples on the falling edge of the clock, and perform the appropriate calculations on the rising edge in order to get the appropriate output. Since you are adding two 16-bit values together, it's possible you'll end up with a 17-bit answer. You should store the input into 17-bit registers and use a 17-bit adder. Your output, however, will be the lower 16 bits of the answer. Code might look something like this but I can't guarantee that it will work completely since I haven't tested it, let alone synthesized it.

IEEE.numeric_std.all; ... signal x_prev, x_curr, y_n: signed(16 downto 0); signal filter_out: std_logic_vector(15 downto 0); ... process (clk) is begin if falling_edge(clk) then --Latch Data x_prev <= x_curr; x_curr <= signed('0' & ADC_output); --since ADC is 16 bits end if; end process; process (clk) is begin if rising_edge(clk) then --Calculate y(n) y_n <= x_curr + x_prev; end if; end process; filter_out <= std_logic_vector(y_n(15 downto 0)); --only use the lower 16 bits of answer

As you can see, you can use this general idea to add in more complicated formulas, such as ones with coefficients. More complicated formulas, like IIR filters, may require the use of variables to get algorithm logic correct. Finally, an easy way to get around filters that have real numbers as coefficients is to find a scale factor so that all the numbers end up being as close to whole numbers as possible. Your final result will have to be scaled back down by the same factor to get the correct result.

I hope this can be of use to you and help you get the ball rolling.

*This has been edited so that the data latching and output latching are in separate processes. Also using signed types instead of std_logic_vector. I'm assuming your ADC input is going to be a std_logic_vector signal.