LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; --  Imports the standard textio package.

use work.utils_pkg.all; --  Imports the standard textio package.

ENTITY crc32 IS
	Generic
	(
		crc32_init	: unsigned(31 downto 0) := X"00000000"
	);
	Port
	(
		rst			: in  STD_LOGIC;
		clk			: in  STD_LOGIC;
		din_vld		: in  STD_LOGIC;
		din			: in  unsigned(7 downto 0);
		crc32_vld	: out STD_LOGIC;
		crc32_out	: out unsigned(31 downto 0)
		
	);
END crc32;

ARCHITECTURE behavior OF crc32 IS

	type crc_table_t is array (0 to 15) of unsigned(31 downto 0);
	
	constant crc_table	: crc_table_t :=
	(
		X"4DBDF21C", X"500AE278", X"76D3D2D4", X"6B64C2B0",
		X"3B61B38C", X"26D6A3E8", X"000F9344", X"1DB88320",
		X"A005713C", X"BDB26158", X"9B6B51F4", X"86DC4190",
		X"D6D930AC", X"CB6E20C8", X"EDB71064", X"F0000000"
	);
	
	signal crc0		: unsigned(31 downto 0);
	signal crc1		: unsigned(31 downto 0);
	signal crc2		: unsigned(31 downto 0);
	
--------------------------------------------------------------------------
begin

	crc1	<= X"0" & crc0(31 downto 4) xor crc_table(to_integer(crc0(3 downto 0) xor din(3 downto 0)));
	crc2	<= X"0" & crc1(31 downto 4) xor crc_table(to_integer(crc1(3 downto 0) xor din(7 downto 4)));
	
	crc32_out	<= crc0;
	
--------------------------------------------------------------------------
process(clk)
begin
	if rising_edge(clk) then
		if rst = '1' then
			crc0		<= crc32_init;
			crc32_vld	<= '0';
		elsif din_vld = '1' then	
			crc0		<= crc2;
			crc32_vld	<= '1';
		end if;
	end if;
end process;

--------------------------------------------------------------------------
end behavior;
