library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.fixed_float_types.all; use ieee.fixed_pkg.all; entity low_pass_filter is generic (integer_bits : integer; fraction_bits : integer); port (clock : in std_logic; reset : in std_logic; sample : in sfixed(integer_bits-1 downto -fraction_bits); sample_ready : in std_logic; output : out sfixed(integer_bits-1 downto -fraction_bits); output_ready : out std_logic); end; architecture behaviour of low_pass_filter is constant order : natural := 16; constant counter_bits : natural := 5; subtype datapath_type is sfixed(integer_bits-1 downto -fraction_bits); -- controller type state_type is (waiting, sampling, calculating_first, calculating, calculating_last, outputting); signal state, next_state : state_type; -- coefficient store subtype coeff_type is sfixed(1 downto -32); type coeff_array_type is array (natural range 0 to order) of coeff_type; constant coefficients : coeff_array_type := ( B"00_00001001011011111101001111001101", -- 0.0368626 B"00_00000101000000101101011101110001", -- 0.019574609 B"11_11111010000100001100010110000010", -- -0.023181587 B"11_11110000111000101111010111011001", -- -0.05903686 B"11_11110011011010110101111110100000", -- -0.04914286 B"00_00000110000111010110010111000001", -- 0.02388607 B"00_00100011100101110101010001000101", -- 0.13902785 B"00_00111110100110010011100100100010", -- 0.2445255 B"00_01001001100000101010101111101100", -- 0.28715014 B"00_00111110100110010011100100100010", -- 0.2445255 B"00_00100011100101110101010001000101", -- 0.13902785 B"00_00000110000111010110010111000001", -- 0.02388607 B"11_11110011011010110101111110100000", -- -0.04914286 B"11_11110000111000101111010111011001", -- -0.05903686 B"11_11111010000100001100010110000010", -- -0.023181587 B"00_00000101000000101101011101110001", -- 0.019574609 B"00_00001001011011111101001111001101" -- 0.0368626 ); -- sample store type sample_array_type is array (natural range 0 to order) of datapath_type; signal samples : sample_array_type; signal samples_shift : std_logic; -- address generator signal address : unsigned(counter_bits-1 downto 0); signal address_clear : std_logic; signal address_counting : std_logic; -- accumulator signal accumulator : datapath_type; signal accumulator_calculating : std_logic; signal accumulator_clear : std_logic; -- result register signal result : datapath_type; signal result_ready : std_logic; signal result_save : std_logic; begin -------------------------------------------------------------------------------- -- controller -- state register process begin wait until rising_edge(clock); if reset = '1' then state <= waiting; else state <= next_state; end if; end process; -- state decoding process(state, address, sample_ready) begin samples_shift <= '0'; address_counting <= '0'; address_clear <= '0'; accumulator_calculating <= '0'; accumulator_clear <= '0'; result_save <= '0'; next_state <= state; case state is when waiting => if sample_ready = '1' then next_state <= sampling; end if; when sampling => samples_shift <= '1'; next_state <= calculating_first; when calculating_first => accumulator_clear <= '1'; address_clear <= '1'; next_state <= calculating; when calculating => address_counting <= '1'; accumulator_calculating <= '1'; if address = order-1 then next_state <= calculating_last; end if; when calculating_last => accumulator_calculating <= '1'; next_state <= outputting; when outputting => next_state <= waiting; result_save <= '1'; end case; end process; -- address generator process begin wait until rising_edge(clock); if address_clear = '1' then address <= (others => '0'); elsif address_counting = '1' then address <= address + 1; end if; end process; -- sample shift register bank process begin wait until rising_edge(clock); if samples_shift = '1' then samples(0) <= sample; for i in 1 to order loop samples(i) <= samples(i-1); end loop; end if; end process; -- accumulator process variable coefficient : datapath_type; variable sample : datapath_type; variable product : datapath_type; begin wait until rising_edge(clock); if accumulator_clear = '1' then accumulator <= (others => '0'); elsif accumulator_calculating = '1' then sample := samples(to_integer(address)); coefficient := resize(coefficients(to_integer(address)), coefficient); product := resize(sample * coefficient, product); accumulator <= resize(accumulator + product, accumulator); end if; end process; -- output register process begin wait until rising_edge(clock); result_ready <= '0'; if result_save = '1' then result <= accumulator; result_ready <= '1'; end if; end process; -- drive the out ports output <= result; output_ready <= result_ready; end;