--------------------------------------------------
--+ Key Permutation
--------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;

entity keyInitialPer is 
	port (	entrada : in std_logic_vector(1 to 64);
			saida : out std_logic_vector(1 to 56));
end keyInitialPer;
architecture keyInitialPer of keyInitialPer is
begin
	saida <=
		entrada(57)&
		entrada(49)&
		entrada(41)&
		entrada(33)&
		entrada(25)&
		entrada(17)&
		entrada(9)&
		entrada(1)&
		entrada(58)&
		entrada(50)&
		entrada(42)&
		entrada(34)&
		entrada(26)&
		entrada(18)&

		entrada(10)&
		entrada(2)&
		entrada(59)&
		entrada(51)&
		entrada(43)&
		entrada(35)&
		entrada(27)&
		entrada(19)&
		entrada(11)&
		entrada(3)&
		entrada(60)&
		entrada(52)&
		entrada(44)&
		entrada(36)&

		entrada(63)&
		entrada(55)&
		entrada(47)&
		entrada(39)&
		entrada(31)&
		entrada(23)&
		entrada(15)&
		entrada(7)&
		entrada(62)&
		entrada(54)&
		entrada(46)&
		entrada(38)&
		entrada(30)&
		entrada(22)&

		entrada(14)&
		entrada(6)&
		entrada(61)&
		entrada(53)&
		entrada(45)&
		entrada(37)&
		entrada(29)&
		entrada(21)&
		entrada(13)&
		entrada(5)&
		entrada(28)&
		entrada(20)&
		entrada(12)&
		entrada(4);
end keyInitialPer;

library IEEE;
use IEEE.std_logic_1164.all;
entity shift is 
	port( entrada: in std_logic_vector(1 to 56);
		passo: in std_logic;
		saida: out std_logic_vector(1 to 56)	
	);
end shift;	-- para esquerda

architecture crypt of shift is
begin
	saida <= entrada(2 to 28) & entrada(1) & entrada(30 to 56) & entrada(29) when passo = '0' else
					entrada(3 to 28) & entrada(1 to 2) & entrada(31 to 56) & entrada(29 to 30) ;
end crypt;

-------------------------------------------------
--+ Compression Permutation
-------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;

entity CompressionPer is 
	port (	entrada : in std_logic_vector(1 to 56);
			saida : out std_logic_vector(1 to 48));
end CompressionPer;

architecture CompressionPer of CompressionPer is
begin

	saida<=
	entrada(14)&
	entrada(17)&
	entrada(11)&
	entrada(24)&
	entrada(1)&
	entrada(5)&
	entrada(3)&
	entrada(28)&
	entrada(15)&
	entrada(6)&
	entrada(21)&
	entrada(10)&

	entrada(23)&
	entrada(19)&
	entrada(12)&
	entrada(4)&
	entrada(26)&
	entrada(8)&
	entrada(16)&
	entrada(7)&
	entrada(27)&
	entrada(20)&
	entrada(13)&
	entrada(2)&

	entrada(41)&
	entrada(52)&
	entrada(31)&
	entrada(37)&
	entrada(47)&
	entrada(55)&
	entrada(30)&
	entrada(40)&
	entrada(51)&
	entrada(45)&
	entrada(33)&
	entrada(48)&

	entrada(44)&
	entrada(49)&
	entrada(39)&
	entrada(56)&
	entrada(34)&
	entrada(53)&
	entrada(46)&
	entrada(42)&
	entrada(50)&
	entrada(36)&
	entrada(29)&
	entrada(32);

end CompressionPer;

--------------------------------------------------
--+ Key Expansion
--------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;

entity keyExpansion is
	port(
		clk,rst, loadKey : in std_logic; 
		chave : in std_logic_vector(1 to 56);
		saida : out std_logic_vector(1 to 48);
		strKey, ready  : out std_logic
	);
end keyExpansion;

architecture crypt of keyExpansion is
	signal key, entradaComp: std_logic_vector(1 to 56);	
	signal round : integer range 0 to 16:=0;
	signal shift : std_logic;
begin

	shift <= '0' when round =  1 or round =  2 or round =  9 or round = 16 else '1';
	
	Shiftbox: entity work.shift
	port map(
		entrada => key,
		passo => shift,
		saida => entradaComp
	);

	comp: entity work.CompressionPer
	port map(
		entrada => entradaComp,
		saida=> saida
	);

	process(clk)
	begin
		if(clk'event and clk = '1')then
			if(rst = '1')then
				key	<= (others=>'0');
				round <= 0;
				strKey <= '0';
				ready <= '0';
			else
				strKey <= loadkey;
				if(loadKey = '1')then
					key <= chave;					
					round <= 1;
					ready <= '0';
				elsif (round > 0) then
					key <=	entradaComp;
					if(round < 16)then
						round <= round +1;
					else
						ready <= '1';	
					end if;	
			
				end if;
			end if;	
		end if;
	end process;
	
end crypt;
