library ieee;
use ieee.std_logic_1164.all;
USE IEEE.numeric_std.ALL;

entity SINC3 is
	port (
	   clk_in : in std_logic;
	   data_in : in std_logic;
	   run : in std_logic;
     data_out : out signed (15 downto 0)
	);
end SINC3;

architecture Behavioral of SINC3 is

signal data_in_unsigned : unsigned (23 downto 0);
signal acc1 : unsigned (23 downto 0);
signal acc2 : unsigned (23 downto 0);
signal acc3 : unsigned (23 downto 0);
signal acc3_d : unsigned (23 downto 0);
signal diff1 : unsigned (23 downto 0);
signal diff2 : unsigned (23 downto 0);
signal diff3 : unsigned (23 downto 0);
signal diff1_d : unsigned (23 downto 0);
signal diff2_d : unsigned (23 downto 0);
signal word_count : unsigned (7 downto 0);
signal word_clk : std_logic;

begin
    process (data_in)
    begin
        if (data_in = '0') then
            data_in_unsigned <= (others => '0');
        else
            data_in_unsigned <= to_unsigned(1,data_in_unsigned'length);
        end if;
    end process;

    process (clk_in,run)
    begin
        if (run = '0') then
            acc1 <= (others => '0');
            acc2 <= (others => '0');
            acc3 <= (others => '0');
        elsif (rising_edge(clk_in)) then
            acc1 <= acc1 + data_in_unsigned;
            acc2 <= acc2 + acc1;
            acc3 <= acc3 + acc2;
        end if;
    end process;

    process (clk_in,run)
    begin
        if (run = '0') then
            word_count <= (others => '0');
        elsif (rising_edge(clk_in)) then
            word_count <= word_count + to_unsigned(1,word_count'length);
        end if;
    end process;

    process (word_count)
    begin
        word_clk <= word_count(7);
    end process;

    process (word_clk,run)
    begin
        if (run = '0') then
            acc3_d <= (others => '0');
            diff1_d <= (others => '0');
            diff2_d <= (others => '0');
            diff1 <= (others => '0');
            diff2 <= (others => '0');
            diff3 <= (others => '0');
        elsif (rising_edge(word_clk)) then
            diff1 <= acc3 - acc3_d;
            diff2 <= diff1 - diff1_d;
            diff3 <= diff2 - diff2_d;
            acc3_d <= acc3;
            diff1_d <= diff1;
            diff2_d <= diff2;
        end if;
    end process;

    process (word_clk)
    begin
        if (rising_edge(word_clk)) then
            data_out(15) <= not diff3(23);
            data_out(14) <= diff3(22);
            data_out(13) <= diff3(21);
            data_out(12) <= diff3(20);
            data_out(11) <= diff3(19);
            data_out(10) <= diff3(18);
            data_out(9) <= diff3(17);
            data_out(8) <= diff3(16);
            data_out(7) <= diff3(15);
            data_out(6) <= diff3(14);
            data_out(5) <= diff3(13);
            data_out(4) <= diff3(12);
            data_out(3) <= diff3(11);
            data_out(2) <= diff3(10);
            data_out(1) <= diff3(9);
            data_out(0) <= diff3(8);
        end if;
    end process;

end Behavioral;