----------------------------------------------------------------------------------
-- 						  Modul pro vypocet CRC32 IEEE802.3								  --
-- CRC32 GP = 1+x^1+x^2+x^4+x^5+x^7+x^8+x^10+x^11+x^12+x^16+x^22+x^23+x^26+x^32 --
----------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

entity crc is
port ( 
		DATA_IN : in std_logic_vector (7 downto 0);
		CRC_EN: in std_logic;  
		RESET: in std_logic; 
		CLK: in std_logic;
		CRC_OUT: out std_logic_vector (31 downto 0)
);
end crc;

architecture imp_crc of crc is
signal crc_i : std_logic_vector (31 downto 0):=(others =>'0');
signal newcrc: std_logic_vector (31 downto 0):=(others =>'0');
signal data_i: std_logic_vector (7 downto 0) :=(others =>'0');
begin
	
	---------------------------------------------------------------------------------
	-- prizpusobeni FCS do framu
	---------------------------------------------------------------------------------
	process (crc_i, DATA_IN)
	variable crc_out_i: std_logic_vector (31 downto 0);
	variable data: std_logic_vector (7 downto 0);
	begin   
		-- reverze fcs pro dopneni do framu
		for i in 0 to 31 loop 						
			crc_out_i(i) := crc_i(31-i);
		end loop;
		CRC_OUT <= not crc_out_i;
	
		-- reverze vstupnich dat
		for i in 0 to 7 loop 						 
			data(i) := DATA_IN(7-i);
		end loop;
		data_i <= data;
	end process;

	---------------------------------------------------------------------------------
	-- Rovnice pro paralelni CRC
   newcrc(0) <= data_i(6) xor data_i(0) xor crc_i(24) xor crc_i(30);
   newcrc(1) <= data_i(7) xor data_i(6) xor data_i(1) xor data_i(0) xor crc_i(24) xor crc_i(25) xor crc_i(30) xor crc_i(31);
   newcrc(2) <= data_i(7) xor data_i(6) xor data_i(2) xor data_i(1) xor data_i(0) xor crc_i(24) xor crc_i(25) xor crc_i(26) xor crc_i(30) xor crc_i(31);
   newcrc(3) <= data_i(7) xor data_i(3) xor data_i(2) xor data_i(1) xor crc_i(25) xor crc_i(26) xor crc_i(27) xor crc_i(31);
   newcrc(4) <= data_i(6) xor data_i(4) xor data_i(3) xor data_i(2) xor data_i(0) xor crc_i(24) xor crc_i(26) xor crc_i(27) xor crc_i(28) xor crc_i(30);
   newcrc(5) <= data_i(7) xor data_i(6) xor data_i(5) xor data_i(4) xor data_i(3) xor data_i(1) xor data_i(0) xor crc_i(24) xor crc_i(25) xor crc_i(27) xor crc_i(28) xor crc_i(29) xor crc_i(30) xor crc_i(31);
   newcrc(6) <= data_i(7) xor data_i(6) xor data_i(5) xor data_i(4) xor data_i(2) xor data_i(1) xor crc_i(25) xor crc_i(26) xor crc_i(28) xor crc_i(29) xor crc_i(30) xor crc_i(31);
   newcrc(7) <= data_i(7) xor data_i(5) xor data_i(3) xor data_i(2) xor data_i(0) xor crc_i(24) xor crc_i(26) xor crc_i(27) xor crc_i(29) xor crc_i(31);
   newcrc(8) <= data_i(4) xor data_i(3) xor data_i(1) xor data_i(0) xor crc_i(0) xor crc_i(24) xor crc_i(25) xor crc_i(27) xor crc_i(28);
   newcrc(9) <= data_i(5) xor data_i(4) xor data_i(2) xor data_i(1) xor crc_i(1) xor crc_i(25) xor crc_i(26) xor crc_i(28) xor crc_i(29);
   newcrc(10) <= data_i(5) xor data_i(3) xor data_i(2) xor data_i(0) xor crc_i(2) xor crc_i(24) xor crc_i(26) xor crc_i(27) xor crc_i(29);
   newcrc(11) <= data_i(4) xor data_i(3) xor data_i(1) xor data_i(0) xor crc_i(3) xor crc_i(24) xor crc_i(25) xor crc_i(27) xor crc_i(28);
   newcrc(12) <= data_i(6) xor data_i(5) xor data_i(4) xor data_i(2) xor data_i(1) xor data_i(0) xor crc_i(4) xor crc_i(24) xor crc_i(25) xor crc_i(26) xor crc_i(28) xor crc_i(29) xor crc_i(30);
   newcrc(13) <= data_i(7) xor data_i(6) xor data_i(5) xor data_i(3) xor data_i(2) xor data_i(1) xor crc_i(5) xor crc_i(25) xor crc_i(26) xor crc_i(27) xor crc_i(29) xor crc_i(30) xor crc_i(31);
   newcrc(14) <= data_i(7) xor data_i(6) xor data_i(4) xor data_i(3) xor data_i(2) xor crc_i(6) xor crc_i(26) xor crc_i(27) xor crc_i(28) xor crc_i(30) xor crc_i(31);
   newcrc(15) <= data_i(7) xor data_i(5) xor data_i(4) xor data_i(3) xor crc_i(7) xor crc_i(27) xor crc_i(28) xor crc_i(29) xor crc_i(31);
   newcrc(16) <= data_i(5) xor data_i(4) xor data_i(0) xor crc_i(8) xor crc_i(24) xor crc_i(28) xor crc_i(29);
   newcrc(17) <= data_i(6) xor data_i(5) xor data_i(1) xor crc_i(9) xor crc_i(25) xor crc_i(29) xor crc_i(30);
   newcrc(18) <= data_i(7) xor data_i(6) xor data_i(2) xor crc_i(10) xor crc_i(26) xor crc_i(30) xor crc_i(31);
   newcrc(19) <= data_i(7) xor data_i(3) xor crc_i(11) xor crc_i(27) xor crc_i(31);
   newcrc(20) <= data_i(4) xor crc_i(12) xor crc_i(28);
   newcrc(21) <= data_i(5) xor crc_i(13) xor crc_i(29);
   newcrc(22) <= data_i(0) xor crc_i(14) xor crc_i(24);
   newcrc(23) <= data_i(6) xor data_i(1) xor data_i(0) xor crc_i(15) xor crc_i(24) xor crc_i(25) xor crc_i(30);
   newcrc(24) <= data_i(7) xor data_i(2) xor data_i(1) xor crc_i(16) xor crc_i(25) xor crc_i(26) xor crc_i(31);
   newcrc(25) <= data_i(3) xor data_i(2) xor crc_i(17) xor crc_i(26) xor crc_i(27);
   newcrc(26) <= data_i(6) xor data_i(4) xor data_i(3) xor data_i(0) xor crc_i(18) xor crc_i(24) xor crc_i(27) xor crc_i(28) xor crc_i(30);
   newcrc(27) <= data_i(7) xor data_i(5) xor data_i(4) xor data_i(1) xor crc_i(19) xor crc_i(25) xor crc_i(28) xor crc_i(29) xor crc_i(31);
   newcrc(28) <= data_i(6) xor data_i(5) xor data_i(2) xor crc_i(20) xor crc_i(26) xor crc_i(29) xor crc_i(30);
   newcrc(29) <= data_i(7) xor data_i(6) xor data_i(3) xor crc_i(21) xor crc_i(27) xor crc_i(30) xor crc_i(31);
   newcrc(30) <= data_i(7) xor data_i(4) xor crc_i(22) xor crc_i(28) xor crc_i(31);
   newcrc(31) <= data_i(5) xor crc_i(23) xor crc_i(29);
	
	---------------------------------------------------------------------------------
	-- Sekvencni cast CRC32 IEEE802.3
	---------------------------------------------------------------------------------
	process (CLK) begin
		if (CLK'EVENT and CLK = '1') then
			if (RESET = '1') then 
				crc_i <= (others =>'1');	-- inicializace v xFFFFFFFF
			elsif (CRC_EN = '1') then 
				crc_i <= newcrc;
			end if;
		end if;
	end process; 
	 
end architecture imp_crc; 