--
------------------------------------------------------------------
--
-- This code is form www.hendrikdettmer.de
--
-- Copyright by 
--
-- Hendrik Dettmer		(me@hendrikdettmer.de)
--
-- Have fun!
-- Questions? Just mail me!
-------------------------------------------------------------------
--

library ieee;
use IEEE.std_logic_1164.ALL;
use IEEE.std_logic_arith.ALL;
use IEEE.std_logic_unsigned.ALL;

entity Shift is
Generic (
			size : positive := 8);
Port (	 rst : in STD_LOGIC;	
			 clk : in STD_LOGIC;
		  	seed : in STD_LOGIC_VECTOR(size-1 downto 0);
	  		out2 : out STD_LOGIC);
end Shift;

architecture Behavioral3 of Shift is

signal status : STD_LOGIC_VECTOR(size-1 downto 0);


begin
	
	clkproc: process(clk)
		begin
			if clk'event and clk = '1' then
				status(size-2 downto 0) <= status(size-1 downto 1);
				if rst = '1' then
					status <= seed;
					out2 <= '0';
				else
					out2 <= status(0);
				end if;
			end if;
	end process;
end Behavioral3;

library ieee;
use IEEE.std_logic_1164.ALL;
use IEEE.std_logic_arith.ALL;
use IEEE.std_logic_unsigned.ALL;

entity LFSRmain is
Generic (
	  sensebit : positive := 4 ;							--Indexplatz des Sensebits (wichtig beim A51)
			size : positive := 8 ;							--Größe des LFSR
			taps : STD_LOGIC_VECTOR := "01010101");	--Vektor für die Zuweisung der XORs
Port (	 rst : in STD_LOGIC;					
			 clk : in STD_LOGIC;
	 clkintern : in StD_LOGIC;
		  KorFn : in STD_LOGIC := '0';					--Wichtig nur für den A51
			seed : in STD_LOGIC_VECTOR(size-1 downto 0);	--Ursprungseingabe
	  senseout : out STD_LOGIC;							--SenseBit out für den A51
			out1 : out STD_LOGIC);
end LFSRmain;

architecture Behavioral of LFSRmain is

signal status : STD_LOGIC_VECTOR(size-1 downto 0);
signal xorvec : STD_LOGIC_VECTOR(size-1 downto 0);

begin
	
	
	gen1: for i in size-1 downto 0 generate
		max:if i = (size-1) generate
			xorvec(size-1) <= status(size-1) XOR KorFn;
		end generate;
		
		mid:if i < (size-1) generate
			one: if taps(i) = '1' generate
				xorvec(i) <= xorvec(i+1) xor status(i);
			end generate;
			nul: if taps(i) = '0' generate
				xorvec(i) <= xorvec(i+1);
			end generate;
		end generate;

	end generate;
	
	clkproc: process(clk, status,clkintern)
		begin
			senseout <= status(sensebit);
			out1 <= status(size-1);
			if clk'event and clk = '1' and clkintern = '1' then
					status(size-1 downto 0) <= status(size-2 downto 0) & xorvec(0);
					if rst = '1' then
						status <= seed;
					end if;
			end if;
	end process;
end Behavioral;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity A51 is
	Port (	clk : in STD_LOGIC;
			 reset : in STD_LOGIC;
				  K : in std_logic_vector(63 downto 0); -- session key
   			 Fn : in std_logic_vector(21 downto 0); -- frame counter
		out_ready : out std_logic;
		  out_bit : out std_logic);
end A51;

architecture Behavioral2 of A51 is

SIGNAL seed19 : STD_LOGIC_VECTOR(18 downto 0);
SIGNAL seed22 : STD_LOGIC_VECTOR(21 downto 0);
SIGNAL seed23 : STD_LOGIC_VECTOR(22 downto 0);

signal m: unsigned(8 downto 0);

SIGNAL  seedShift : std_logic_vector(85 downto 0); 

SIGNAL sense19 : STD_LOGIC;
SIGNAL sense22 : STD_LOGIC;
SIGNAL sense23 : STD_LOGIC;

SIGNAL clk19 : STD_LOGIC;
SIGNAL clk22 : STD_LOGIC;
SIGNAL clk23 : STD_LOGIC;

SIGNAL out19 : STD_LOGIC := '1';
SIGNAL out22 : STD_LOGIC := '1';
SIGNAL out23 : STD_LOGIC := '1';
SIGNAL outShift : STD_LOGIC;

SIGNAL KorFn1 : STD_LOGIC := '0';

component LFSRmain
	Generic (
	  sensebit : positive := 4 ;
			size : positive := 8 ;
			taps : STD_LOGIC_VECTOR := "01010101");
	Port ( rst : in STD_LOGIC;	
			 clk : in STD_LOGIC;
	 clkintern : in StD_LOGIC;
		  KorFn : in STD_LOGIC;
			seed : in STD_LOGIC_VECTOR(size-1 downto 0);
	  senseout : out STD_LOGIC;
			out1 : out STD_LOGIC);
end component;

component Shift 
	Generic (
			size : positive := 8) ;
	Port ( rst : in STD_LOGIC;	
			 clk : in STD_LOGIC;
		  	seed : in STD_LOGIC_VECTOR(size-1 downto 0);
	  		out2 : out STD_LOGIC);
end component;

begin
		ShiftR: Shift
				generic map ( size => 86)
				port map(reset, clk, seedShift, outShift);
		
		
		LFSR19: LFSRmain 
				generic map ( sensebit => 8,
								  size => 19,
								  taps => "0000000000000100111")
				port map ( reset, clk, clk19, KorFn1, seed19, sense19, out19);
	
		LFSR22: LFSRmain 
				generic map ( sensebit => 10,
								  size => 22,
								  taps => "0000000000000000000011")
				port map ( reset, clk, clk22, KorFn1, seed22, sense22, out22);
				
		LFSR23: LFSRmain 
				generic map ( sensebit => 10,
								  size => 23,
								  taps => "00000001000000000000111")
				port map ( reset, clk, clk23, KorFn1, seed23, sense23, out23);

	out_bit <= out19 XOR out22 XOR out23;
	KorFn1 <= outShift;
	
	clkproc: process(clk)
	begin
		
		if clk'event and clk = '1' then
			if reset = '1' then
				seed19 <= "0000000000000000000";
				seed22 <= "0000000000000000000000";
				seed23 <= "00000000000000000000000";
				seedShift <= Fn & K;
				m <= "000000000";
			else
				m <= m+1;
			end if;
		end if;
	end process;
	
	interclkproc: process(m, sense19,sense22,sense23)
	begin
		out_ready <= '0';
		if m <= 86 then
			clk19 <= '1';
			clk22 <= '1';
			clk23 <= '1';
			elsif m > 86 and m <= 187 then
				if not((sense19 or sense22) or sense23) = '1' then
					clk19 <= '1';
					clk22 <= '1';
					clk23 <= '1';
				elsif ((sense19 and sense22) and sense23) = '1' then
					clk19 <= '1';
					clk22 <= '1';
					clk23 <= '1';
				else
					clk19 <= sense22 xor sense23;
					clk22 <= sense19 xor sense23;
					clk23 <= sense19 xor sense22;
				end if;
			elsif m >= 187 and m <= 415 then 
				out_ready <='1';
				if not((sense19 or sense22) or sense23) = '1' then
					clk19 <= '1';
					clk22 <= '1';
					clk23 <= '1';
				elsif ((sense19 and sense22) and sense23) = '1' then
					clk19 <= '1';
					clk22 <= '1';
					clk23 <= '1';
				else
					clk19 <= sense22 xor sense23;
					clk22 <= sense19 xor sense23;
					clk23 <= sense19 xor sense22;
				end if;
			 else
				out_ready <= '0';
		end if;
	end process;

end Behavioral2;

