-- file Crc8005_32.vhd
-- Crc8005_32 crcspec_v3_0 implementation
-- copyright: (C) 2016-2020 MPSI Technologies GmbH
-- author: Alexander Wirthmueller (auto-generation)
-- date created: 28 Jun 2025
-- IP header --- ABOVE

-- module parameters:
-- poly (polynomial): 8005
-- wD (data width 8/16/32/64/128 [bit]): 32
-- leNotBe (endianness): true

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Crc8005_32 is
	generic (
		initInvert: boolean := false;
		byteFlip: boolean := false;
		outFlip: boolean := false;
		outInvert: boolean := false
	);
	port (
		reset: in std_logic;
		mclk: in std_logic;

		AXIS_tready: out std_logic;
		AXIS_tvalid: in std_logic;
		AXIS_tdata: in std_logic_vector(31 downto 0);
		AXIS_tkeep: in std_logic_vector(3 downto 0);
		AXIS_tlast: in std_logic;

		crc: out std_logic_vector(15 downto 0);
		validCrc: out std_logic
	);
end Crc8005_32;

architecture Rtl of Crc8005_32 is

	------------------------------------------------------------------------
	-- signal declarations
	------------------------------------------------------------------------

	constant wPoly: natural := 16;
	constant wD: natural := 32;

	---- main operation (op)
	type stateOp_t is (
		stateOpInit,
		stateOpCapt
	);
	signal stateOp: stateOp_t;

	signal word_imd: std_logic_vector(wD-1 downto 0);
	signal word: std_logic_vector(wD-1 downto 0);

	signal crc_imd: std_logic_vector(wPoly-1 downto 0);
	signal crc_sig: std_logic_vector(wPoly-1 downto 0);

	signal validCrc_sig: std_logic;

	signal first: std_logic;

begin

	------------------------------------------------------------------------
	-- implementation: main operation (op)
	------------------------------------------------------------------------

	AXIS_tready <= '1' when stateOp=stateOpCapt else '0';

	gen_word: for i in 0 to wD/8-1 generate
		gen_byte: for j in 0 to 7 generate
			word(8*i+j) <= word_imd(8*i+(8-j-1)) when byteFlip else word_imd(8*i+j);
		end generate;
	end generate;
	word_imd(wD-1 downto wPoly) <= AXIS_tdata(wD-1 downto wPoly);
	word_imd(wPoly-1 downto 0) <= not AXIS_tdata(wPoly-1 downto 0) when initInvert and first='1' else AXIS_tdata(wPoly-1 downto 0);

	crc <= not crc_sig when outInvert else crc_sig;

	gen_crc: for i in 0 to wPoly-1 generate
		crc_sig(i) <= crc_imd(wPoly-i-1) when outFlip else crc_imd(i);
	end generate;

	validCrc <= validCrc_sig;
	
	process (reset, mclk, stateOp)

	begin
		if reset='1' then
			stateOp <= stateOpInit;

			crc_imd <= (others => '0');

			validCrc_sig <= '0';

			first <= '1';

		elsif rising_edge(mclk) then
			if stateOp=stateOpInit then
				if AXIS_tlast='0' then
					crc_imd <= (others => '0');

					validCrc_sig <= '0';

					first <= '1';

					stateOp <= stateOpCapt;
				end if;

			elsif stateOp=stateOpCapt then
				if AXIS_tvalid='1' and (first='1' or validCrc_sig='1') then
					case AXIS_tkeep is
						when "1111" =>
							crc_imd(15) <= word(7) xor word(6) xor word(5) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor word(23) xor word(22) xor word(20) xor word(19) xor word(18) xor word(17) xor word(16) xor word(31) xor word(30) xor word(29) xor word(28) xor word(27) xor word(26) xor word(25) xor word(24) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(14) <= word(4) xor word(2) xor word(21) xor word(20) xor crc_imd(10) xor crc_imd(12);
							crc_imd(13) <= word(3) xor word(1) xor word(20) xor word(19) xor crc_imd(9) xor crc_imd(11);
							crc_imd(12) <= word(2) xor word(0) xor word(19) xor word(18) xor crc_imd(8) xor crc_imd(10);
							crc_imd(11) <= word(1) xor word(15) xor word(18) xor word(17) xor crc_imd(7) xor crc_imd(9);
							crc_imd(10) <= word(0) xor word(14) xor word(17) xor word(16) xor crc_imd(6) xor crc_imd(8);
							crc_imd(9) <= word(15) xor word(13) xor word(16) xor word(31) xor crc_imd(5) xor crc_imd(7);
							crc_imd(8) <= word(14) xor word(12) xor word(31) xor word(30) xor crc_imd(4) xor crc_imd(6);
							crc_imd(7) <= word(13) xor word(11) xor word(30) xor word(29) xor crc_imd(3) xor crc_imd(5);
							crc_imd(6) <= word(12) xor word(10) xor word(29) xor word(28) xor crc_imd(2) xor crc_imd(4);
							crc_imd(5) <= word(7) xor word(11) xor word(9) xor word(28) xor word(27) xor crc_imd(1) xor crc_imd(3) xor crc_imd(15);
							crc_imd(4) <= word(7) xor word(6) xor word(10) xor word(8) xor word(27) xor word(26) xor crc_imd(0) xor crc_imd(2) xor crc_imd(14) xor crc_imd(15);
							crc_imd(3) <= word(7) xor word(6) xor word(5) xor word(9) xor word(23) xor word(26) xor word(25) xor crc_imd(1) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(2) <= word(7) xor word(6) xor word(5) xor word(4) xor word(8) xor word(22) xor word(25) xor word(24) xor crc_imd(0) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(1) <= word(7) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor word(22) xor word(21) xor word(20) xor word(19) xor word(18) xor word(17) xor word(16) xor word(31) xor word(30) xor word(29) xor word(28) xor word(27) xor word(26) xor word(25) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(15);
							crc_imd(0) <= word(7) xor word(6) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor word(23) xor word(21) xor word(20) xor word(19) xor word(18) xor word(17) xor word(16) xor word(31) xor word(30) xor word(29) xor word(28) xor word(27) xor word(26) xor word(25) xor word(24) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(14) xor crc_imd(15);
							validCrc_sig <= '1';
						when "0111" =>
							crc_imd(15) <= word(7) xor word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor word(23) xor word(22) xor word(21) xor word(20) xor word(19) xor word(18) xor word(17) xor word(16) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(14) <= word(13) xor word(12) xor crc_imd(4) xor crc_imd(5);
							crc_imd(13) <= word(12) xor word(11) xor crc_imd(3) xor crc_imd(4);
							crc_imd(12) <= word(11) xor word(10) xor crc_imd(2) xor crc_imd(3);
							crc_imd(11) <= word(7) xor word(10) xor word(9) xor crc_imd(1) xor crc_imd(2) xor crc_imd(15);
							crc_imd(10) <= word(6) xor word(9) xor word(8) xor crc_imd(0) xor crc_imd(1) xor crc_imd(14);
							crc_imd(9) <= word(7) xor word(5) xor word(8) xor word(23) xor crc_imd(0) xor crc_imd(13) xor crc_imd(15);
							crc_imd(8) <= word(6) xor word(4) xor word(23) xor word(22) xor crc_imd(12) xor crc_imd(14);
							crc_imd(7) <= word(5) xor word(3) xor word(22) xor word(21) xor crc_imd(11) xor crc_imd(13);
							crc_imd(6) <= word(4) xor word(2) xor word(21) xor word(20) xor crc_imd(10) xor crc_imd(12);
							crc_imd(5) <= word(3) xor word(1) xor word(20) xor word(19) xor crc_imd(9) xor crc_imd(11);
							crc_imd(4) <= word(2) xor word(0) xor word(19) xor word(18) xor crc_imd(8) xor crc_imd(10);
							crc_imd(3) <= word(1) xor word(15) xor word(18) xor word(17) xor crc_imd(7) xor crc_imd(9);
							crc_imd(2) <= word(0) xor word(14) xor word(17) xor word(16) xor crc_imd(6) xor crc_imd(8);
							crc_imd(1) <= word(7) xor word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor word(23) xor word(22) xor word(21) xor word(20) xor word(19) xor word(18) xor word(17) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(0) <= word(7) xor word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor word(23) xor word(22) xor word(21) xor word(20) xor word(19) xor word(18) xor word(17) xor word(16) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							validCrc_sig <= '1';
						when "0011" =>
							crc_imd(15) <= word(7) xor word(6) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(14) xor crc_imd(15);
							crc_imd(14) <= word(5) xor word(4) xor crc_imd(12) xor crc_imd(13);
							crc_imd(13) <= word(4) xor word(3) xor crc_imd(11) xor crc_imd(12);
							crc_imd(12) <= word(3) xor word(2) xor crc_imd(10) xor crc_imd(11);
							crc_imd(11) <= word(2) xor word(1) xor crc_imd(9) xor crc_imd(10);
							crc_imd(10) <= word(1) xor word(0) xor crc_imd(8) xor crc_imd(9);
							crc_imd(9) <= word(0) xor word(15) xor crc_imd(7) xor crc_imd(8);
							crc_imd(8) <= word(15) xor word(14) xor crc_imd(6) xor crc_imd(7);
							crc_imd(7) <= word(14) xor word(13) xor crc_imd(5) xor crc_imd(6);
							crc_imd(6) <= word(13) xor word(12) xor crc_imd(4) xor crc_imd(5);
							crc_imd(5) <= word(12) xor word(11) xor crc_imd(3) xor crc_imd(4);
							crc_imd(4) <= word(11) xor word(10) xor crc_imd(2) xor crc_imd(3);
							crc_imd(3) <= word(7) xor word(10) xor word(9) xor crc_imd(1) xor crc_imd(2) xor crc_imd(15);
							crc_imd(2) <= word(6) xor word(9) xor word(8) xor crc_imd(0) xor crc_imd(1) xor crc_imd(14);
							crc_imd(1) <= word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14);
							crc_imd(0) <= word(7) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor word(15) xor word(14) xor word(13) xor word(12) xor word(11) xor word(10) xor word(9) xor word(8) xor crc_imd(0) xor crc_imd(1) xor crc_imd(2) xor crc_imd(3) xor crc_imd(4) xor crc_imd(5) xor crc_imd(6) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(15);
							validCrc_sig <= '1';
						when "0001" =>
							crc_imd(15) <= word(7) xor word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor crc_imd(7) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(14) <= crc_imd(6);
							crc_imd(13) <= crc_imd(5);
							crc_imd(12) <= crc_imd(4);
							crc_imd(11) <= crc_imd(3);
							crc_imd(10) <= crc_imd(2);
							crc_imd(9) <= word(7) xor crc_imd(1) xor crc_imd(15);
							crc_imd(8) <= word(7) xor word(6) xor crc_imd(0) xor crc_imd(14) xor crc_imd(15);
							crc_imd(7) <= word(6) xor word(5) xor crc_imd(13) xor crc_imd(14);
							crc_imd(6) <= word(5) xor word(4) xor crc_imd(12) xor crc_imd(13);
							crc_imd(5) <= word(4) xor word(3) xor crc_imd(11) xor crc_imd(12);
							crc_imd(4) <= word(3) xor word(2) xor crc_imd(10) xor crc_imd(11);
							crc_imd(3) <= word(2) xor word(1) xor crc_imd(9) xor crc_imd(10);
							crc_imd(2) <= word(1) xor word(0) xor crc_imd(8) xor crc_imd(9);
							crc_imd(1) <= word(7) xor word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							crc_imd(0) <= word(7) xor word(6) xor word(5) xor word(4) xor word(3) xor word(2) xor word(1) xor word(0) xor crc_imd(8) xor crc_imd(9) xor crc_imd(10) xor crc_imd(11) xor crc_imd(12) xor crc_imd(13) xor crc_imd(14) xor crc_imd(15);
							validCrc_sig <= '1';
						when others =>
							validCrc_sig <= '0';
					end case;

					first <= '0';

					if AXIS_tlast='1' then
						stateOp <= stateOpInit;
					end if;

				elsif AXIS_tlast='1' then
					validCrc_sig <= '0';

					stateOp <= stateOpInit;
				end if;
			end if;
		end if;
	end process;

end Rtl;
