Files
HDLfilter/FiltroHDL/Filter.vhd
2017-03-07 01:18:29 -03:00

194 lines
3.7 KiB
VHDL

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.array_functions.all;
entity Filter is
generic (
CLK_FREQ : integer := 200e6;
DATA_RATE: integer := 250e3;
SIMETRIC : boolean := TRUE;
CONSTANTS : array_of_integers := (-10,-9,-8,-7,-6,-5,-4,3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
);
port (
clk_i : in std_logic;
enable: in std_logic;
reset: in std_logic;
d_i : in std_logic;
d_o : out std_logic
);
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:
signal accum: integer range -MAX_RANGE to MAX_RANGE := 0;
signal i : integer range 0 to N-1 := 0;
signal i_rst : std_logic := '0';
signal d_s : std_logic := '0';
type STATUS_T is ( wait_start,
clear,
sum_loop );
signal state, next_state : STATUS_T := wait_start;
begin
d_o <= d_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 <= 0;
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
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;