library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.


entity spi_block is
    Port ( dcm_40MHz : in  STD_LOGIC;
           reset : in  STD_LOGIC;
				
				spi_clk : in STD_LOGIC;				--18MHz				
				spi_data : in STD_LOGIC;
				spi_done : out STD_LOGIC;
				spi_error : out STD_LOGIC;
				spi_data_parall : out std_logic_vector(15 downto 0)
				
				
			  );
end spi_block;

architecture Behavioral of spi_block is
type state1 is (idle,st0,st0_1,st1,st2);
signal data_reg1: STD_LOGIC:='1';
signal data_reg2: STD_LOGIC:='1';
signal clk_reg1: STD_LOGIC:='1';
signal clk_reg2: STD_LOGIC:='1';
--------------------------------reg------------------------
signal state1_reg: state1:=idle;
signal S_spi_done_reg : STD_LOGIC:='0';
signal S_spi_data_parall_reg : STD_LOGIC_vector(15 downto 0):=(others=>'0');
signal S_spi_error_reg : STD_LOGIC:='0';
signal S_counter1_reg : unsigned(6 downto 0):=(others=>'0');
signal S_counter2_reg : unsigned(3 downto 0):=(others=>'0');
--------------------------------reg------------------------

--------------------------------next------------------------
signal state1_next: state1:=idle;
signal S_spi_done_next : STD_LOGIC:='0';
signal S_spi_data_parall_next : STD_LOGIC_vector(15 downto 0):=(others=>'0');
signal S_spi_error_next : STD_LOGIC:='0';
signal S_counter1_next : unsigned(6 downto 0):=(others=>'0');
signal S_counter2_next : unsigned(3 downto 0):=(others=>'0');
--------------------------------next------------------------


begin

process(dcm_40MHz,reset)
begin
	if reset='0' then
		data_reg1<='1';
		data_reg2<='1';
		clk_reg1<='1';
		clk_reg2<='1';
		state1_reg<=idle;
		S_spi_error_reg<='0';
	elsif rising_edge(dcm_40MHz) then
		state1_reg<=state1_next;
		data_reg1<=spi_data;
		data_reg2<=data_reg1;
		clk_reg1<=spi_clk;
		clk_reg2<=clk_reg1;
		S_spi_done_reg<=S_spi_done_next;
		S_spi_data_parall_reg<=S_spi_data_parall_next;
		S_spi_error_reg<=S_spi_error_next;
		S_counter1_reg<=S_counter1_next;
		S_counter2_reg<=S_counter2_next;
	end if;
end process;



process(state1_reg,S_spi_data_parall_reg,S_spi_error_reg,S_counter1_reg,S_counter2_reg,clk_reg2,data_reg2)
begin
	state1_next<=state1_reg;
	S_spi_data_parall_next<=S_spi_data_parall_reg;
	S_spi_error_next<=S_spi_error_reg;
	S_spi_done_next<='0';
	S_counter1_next<=S_counter1_reg;
	S_counter2_next<=S_counter2_reg;
	case state1_reg is 
		when idle =>
			if clk_reg2='0' then
				S_spi_error_next<='0';
				S_spi_data_parall_next<=S_spi_data_parall_reg(14 downto 0) & data_reg2;
				state1_next<=st0;
			end if;
			S_counter1_next<=(others=>'0');
			S_counter2_next<=(others=>'0');
		when st0 =>
			S_counter1_next<=S_counter1_reg + 1;
			
			if S_counter1_reg>120 then 
				S_spi_done_next<='1';
				S_spi_error_next<='1';
				state1_next<=idle;
				
			end if;
			if clk_reg2='1' then
				S_spi_error_next<='0';
				state1_next<=st1;
			end if;
		when st1 =>
			S_counter1_next<=S_counter1_reg + 1;
			
			if S_counter1_reg>120 then 
				S_spi_done_next<='1';
				S_spi_error_next<='1';
				state1_next<=idle;
				
			end if;
			
			if clk_reg2='0' then
				if S_counter2_reg="1110" then
					S_spi_done_next<='1';
					state1_next<=st2;					
				else
					S_counter2_next<=S_counter2_reg + 1;
					state1_next<=st0;
					
				end if;
				S_spi_data_parall_next<=S_spi_data_parall_reg(14 downto 0) & data_reg2;
				
			end if;
		when st2 =>
			if  clk_reg2='1' then
				state1_next<=idle;	
			end if;
		when others=>
			null;
			
	end case;
	

end process;

spi_done<=S_spi_done_reg;
spi_error<=S_spi_error_reg;
spi_data_parall<=S_spi_data_parall_reg;


end Behavioral;

