----------------------------------------------------------------------------------
--					Výpočet CHECKSUM PRO protokoly modelu TCP/IP  						  --
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity checksum is
	PORT (
		CLK: in std_logic;
		SUM_OUT: out std_logic_vector(15 downto 0);
		DATA_IN: in std_logic_vector(7 downto 0);
		CALC: in std_logic;
		RESET: in std_logic
	);
end checksum;

architecture Behavioral of checksum is

signal checksum17: std_logic_vector(16 downto 0)					:= (others => '0');
signal checksum_i, word: std_logic_vector(15 downto 0) 			:= (others => '0');
signal carry, lich, lich_next: std_logic 								:= '0';
signal mem, mem_next, data_in_i: std_logic_vector(7 downto 0)	:= (others => '0');	

begin
	-- inverze bitu - pokud vyjde checksuma 0x0000 nastavi se na 0xffff podle specifikace 
	SUM_OUT <= checksum_i when checksum_i = x"FFFF" else not checksum_i;

	-- Slabika pro secteni
	word <= mem & data_in_i;

	-- 16 bitova scitacka s carry in / out		
	checksum17 <= ("0"&checksum_i) + ("0"&word) + carry;
					 
	-- sekvencni cast
	process (CLK)
	begin 
		if rising_edge(CLK) then
			if (RESET = '1') then
				checksum_i <= (others => '0');
				carry <= '0';
				mem <= (others => '0');
			else
				lich <= lich_next;				
				mem <= mem_next;
				
				if lich = '1' then
					checksum_i <= checksum17(15 downto 0);
					carry <= checksum17(16);
				end if;
							
			end if;		
		end if;
	end process;

	----------------------------------------------------------------------
	-- Vstupni data validni pouze pokud je calc aktivni ------------------
	data_in_i <= DATA_IN when CALC = '1' else (others => '0');
	
	----------------------------------------------------------------------
	-- Kazdy sudy byte ulozit do registru --------------------------------
	mem_next <= data_in_i when lich = '0' else mem;
					
	----------------------------------------------------------------------
	-- Delicka 2 az do konce vypoctu -------------------------------------
	lich_next <= '0' when CALC = '0' and carry = '0' and lich = '0' else not lich;


end Behavioral;

