I created for filter basic and simple requirements:
- average of 4 samples
- signal enable:
- ‘1’ – filter ON
- ‘0’ – filter OFF, zeros at the output
- synchronous reset
- don’t care about frequency, resources etc.
- output value updated in every cycle
Below you can find the code of the filter:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity AvgFilter is generic ( G_DATA_W :integer := 16; G_FIL_L :integer := 4 ); port ( clk :in std_logic; rst :in std_logic; en :in std_logic; iv_data :in std_logic_vector(G_DATA_W-1 downto 0); ov_avg :out std_logic_vector(G_DATA_W-1 downto 0) ); end entity; architecture AvgFilter_rtl of AvgFilter is -- calculate number of bits needed to extend sum vector function sumlog2(m :positive) return natural is begin for index in 1 to 30 loop if (m <= 2**index) then return(index); end if; end loop; return(31); end function; signal en_reg :std_logic; -- array for storing samples type t_arr_FilL_x_data is array (G_FIL_L-1 downto 0) of unsigned(G_DATA_W-1 downto 0); signal a_samples :t_arr_FilL_x_data; begin reg: process(clk) -- to add G_FIL_L values is needed sumlog2(G_FIL_L) more bits for result variable v_sum :unsigned(G_DATA_W+sumlog2(G_FIL_L)-1 downto 0); begin if rising_edge(clk) then if rst = '1' then en_reg <= '0'; a_samples <= (others => (others => '0')); v_sum := (others => '0'); ov_avg <= (others => '0'); else en_reg <= en; a_samples(0) <= unsigned(iv_data); for i in 1 to G_FIL_L-1 loop a_samples(i) <= a_samples(i-1); end loop; v_sum := (others => '0'); if en_reg = '1' then for i in 0 to G_FIL_L-1 loop v_sum := v_sum + resize(a_samples(i), v_sum'length); end loop; end if; ov_avg <= std_logic_vector(v_sum(G_DATA_W+sumlog2(G_FIL_L)-1 downto sumlog2(G_FIL_L))); -- divide by sumlog2(G_FIL_L) end if; end if; end process; end architecture;
Though the code should be easy to understand, I will describe it a little bit:
- a_samples – array of registers to store filter samples
- v_sum – variable storing sum of samples. Comparing to input width, is extended by two bits, because that variable is prepared to catch sum of four samples
- ov_avg – output register. Two LSB bits of sum are omitted. That operation is equal to dividing by 4, to get average value.
*** *** ***
All source codes used in that post you can find on gitlab.com.
*** *** ***