library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use work.filter_pkg.all; entity Filter is generic ( CLK_FREQ : integer := 200e6; DATA_RATE: integer := 250e3; SIMETRIC : boolean := TRUE; CONSTANTS : array_of_integers := (-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8) ); port ( clk_i : in std_logic; enable: in std_logic; reset: in std_logic; d_i : in std_logic; d_o : out std_logic; p_o : out std_logic_vector(9 downto 0) ); end Filter; architecture Behavioral of Filter is --~ Array con las constantes, ordenadas de 0 a N constant K : array_of_integers := reorder_array(CONSTANTS, SIMETRIC); --~ Tamaño del array constant N : integer := K'length; --~ Frecuencia a la que se samplea la entrada constant SAMPLE_RATE : integer := DATA_RATE * (N-1); --~ Shift Register signal LSR : std_logic_vector(N-1 downto 0) := (others => '0'); --~ Constante y señales para el contador/divisor de frecuencia constant MAX_COUNT : integer := CLK_FREQ / (SAMPLE_RATE); signal counter : integer range 0 to MAX_COUNT - 1 := 0; signal sample_clk_s : std_logic := '0'; --~ Acumulador: constant INIT_VAL: integer range -MAX_RANGE to MAX_RANGE := 0; signal accum: integer range -MAX_RANGE to MAX_RANGE := INIT_VAL; signal i : integer range 0 to N-1 := 0; signal i_rst : std_logic := '0'; signal d_s : std_logic := '0'; signal p_s : std_logic_vector(9 downto 0) := (others => '0'); type STATUS_T is ( wait_start, clear, sum_loop ); signal state, next_state : STATUS_T := wait_start; begin d_o <= d_s; p_o <= p_s; --~ Proceso sincrónico para cambio de estados stateProcess: process(clk_i) begin if ( rising_edge(clk_i) ) then if ( reset = '1' ) then state <= wait_start; elsif ( enable = '1' ) then state <= next_state; end if; end if; end process; --~ Tranciciones entre estados stateTransition: process(state,i,sample_clk_s) begin case state is when wait_start => i_rst <= '0'; if ( sample_clk_s = '1' ) then next_state <= clear; else next_state <= wait_start; end if; when clear => i_rst <= '1'; next_state <= sum_loop; when sum_loop => i_rst <= '0'; if ( i = N-1 ) then next_state <= wait_start; else next_state <= sum_loop; end if; end case; end process; --~ Proceso sincrónico para contador interno y para acumulador process(clk_i) begin if ( rising_edge(clk_i) ) then if ( enable = '1' ) then if ( i_rst = '1' ) then i <= 0; accum <= INIT_VAL; else if ( i < N-1 ) then i <= i + 1; if ( LSR(i) = '1' ) then accum <= accum + K(i); else accum <= accum - K(i); end if; end if; end if; end if; end if; end process; --~ Latch de la salida, --~ Si. la salida va a estar latcheada OutputLatch: process(clk_i) begin if ( rising_edge(clk_i) ) then if ( enable = '1' and sample_clk_s = '1' and i = N-1 ) then p_s <= std_logic_vector(to_signed(accum,p_s'length)); if ( accum > 0 ) then d_s <= '1'; else d_s <= '0'; end if; end if; end if; end process; --~ Registro de desplazamiento para el sobremuestreo LSRprocess: process ( clk_i ) begin if ( rising_edge(clk_i) ) then if ( reset = '1' ) then LSR <= ( others => '0' ); elsif ( enable = '1' and sample_clk_s = '1' ) then LSR( 0 ) <= d_i; LSR( N-1 downto 1 ) <= LSR( N-2 downto 0 ); end if; end if; end process; --~ Divisor de frecuencia, para obtener la frecuencia de sampleo sample_clk_s <= '1' when counter = MAX_COUNT -1 else '0'; ClkDiv: process( clk_i, reset ) begin if ( rising_edge(clk_i) ) then if ( enable = '1' ) then if ( counter = MAX_COUNT -1 ) then counter <= 0; else counter <= counter + 1; end if; end if; end if; end process; end Behavioral;