------------------------------------------------------------
-- Copyright: 2011 George Mason University, Virginia USA
--            http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
-- =====================================================================

-- Copyright © 2010-2011 by Cryptographic Engineering Research Group (CERG),

-- ECE Department, George Mason University

-- Fairfax, VA, U.S.A.

-- =====================================================================


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

use work.sha3_skein_package.ALL;
use work.sha3_pkg.all;

entity gmu_skein_datapath is
	generic ( 	
		version : integer := SHA3_ROUND3;
		adder_type : integer := SCCA_BASED;
		h : integer := HASH_SIZE_256 );
	port (
		-- external

		clk : in std_logic;
		rst : in std_logic;
		din  : in std_logic_vector(511 downto 0);	
		dout : out std_logic_vector(h-1 downto 0);	
		tw_position64 : in std_logic_vector(63 downto 0);
				
		-- control signals

		er 		: in std_logic;
		sf 		: in std_logic;		-- 1 for first block of a message		

		sfinal 	: in std_logic; 	 -- 0 for msg, 1 for output

		slast 	: in std_logic;  -- 1 for last block and output , 0 else

		snb		: in std_logic
	);				  
end gmu_skein_datapath;

architecture struct of gmu_skein_datapath is   	
	------ Constants						  	

	constant nw : integer := 8; -- fixed

	constant b : integer := 512; -- fixed	   

	constant bzeros 	: std_logic_vector(b-1 downto 0) := (others => '0');
	constant mw			: integer := b;		-- message width	

	constant log2mw : integer := log2(mw);						
	constant log2mwzeros : std_logic_vector(log2mw-1 downto 0) := (others => '0');
	constant mwzeros	: std_logic_vector(mw-1 downto 0) := (others => '0');  
	constant perm : permute_type (0 to nw-1) := get_perm( b );
	constant rot : rot_type (0 to nw/2-1,0 to 7) := get_rot( b );  
	constant iv : std_logic_vector(b-1 downto 0) := get_iv( h, version );																			  
	constant sixteenzeros : std_logic_vector(15 downto 0) := (others => '0');	 
	constant seventyone0 : std_logic_vector(70 downto 0) := (others =>'0');
	constant remzeros : std_logic_vector(log2mw-4 downto 0) := (others => '0');
	constant remones : std_logic_vector(log2mw-4 downto 0) := (others => '1');		
	----------	


	-- TWEAK

	signal tweak : std_logic_vector(127 downto 0);				  
	constant tw_tree_level : std_logic_vector(6 downto 0) := (others =>'0');
	constant tw_reserved : std_logic_vector(15 downto 0) := (others =>'0');	
	constant tw_bit_pad : std_logic := '0'; -- bit pad always '0' as message will be multiple of a byte

	constant zeros : std_logic_vector(31 downto 0) := (others => '0'); -- fill the rest of tweak's position

	signal tw_type  : std_logic_vector(5 downto 0);
	signal tw_final, tw_first : std_logic;
	signal tw_position : std_logic_vector(63 downto 0);
	
	-- ROUND SIGNALS			 

	signal min,min_endian1,min_endian2, msg : std_logic_vector(mw-1 downto 0);
	signal r, rmux, rp : std_logic_vector(b-1 downto 0);	
	signal threefish, cv,  keyin : std_logic_vector(b-1 downto 0);	  
	signal switch_out, switch1, switch2 : std_logic_vector(h-1 downto 0);
	signal keyout  : key_array(nw-1 downto 0);	
	signal keyinj : key_array(nw-1 downto 0);	
	signal round : round_array(0 to 4, nw-1 downto 0);	
	signal roundout : round_array(0 to 3, nw-1 downto 0);	  
	
	-- 4x

	signal sshalf : std_logic;		
begin														
	tw_type <= TW_OUT_CONS when sfinal = '1' else TW_MSG_CONS; 
	tw_final  <= (slast or sfinal);
	tw_first  <= (sf or sfinal);   
	tw_position <= conv_std_logic_vector(8,64) when sfinal = '1' else tw_position64;
	
	-- tweak		

	tweak <= tw_final & tw_first  & tw_type & tw_bit_pad & tw_tree_level & tw_reserved & zeros & tw_position;
	
	-- input																										 

	min_endian1 <= switch_endian_byte(din,b,64);
	min_endian2 <= switch_endian_word(min_endian1,b,64);

	msgRegGen : process( rst, clk )
	begin		
		if ( rst = '0' ) then
			msg <= (others => '0');
		elsif rising_edge( clk ) then
			if ( sfinal = '1' ) then
				msg <= (others => '0');
			elsif ( snb = '1' ) then
				msg <= min_endian2;
			end if;
		end if;
	end process;
	
	rmux <= min_endian2 when snb = '1' else rp;
	r_reg : process( rst, clk )
	begin		
		if ( rst = '0' ) then
			r <= (others => '0');
		elsif rising_edge( clk ) then
			if ( sfinal = '1' ) then
				r <= (others => '0');
			elsif ( er = '1' ) then
				r <= rmux;
			end if;
		end if;
	end process;	
	
	-----------------------

	--------- ROUND -------

	inout_gen : for i in nw-1 downto 0 generate
		round(0,i) <= r(iw*(i+1)-1 downto iw*i);
		rp(iw*(i+1)-1 downto iw*i) <= round(4,i);
	end generate;		
		
	-- cntrl signal	

	process ( clk )	   
	begin
		if rising_edge( clk ) then
			if ( snb = '1' ) then
				sshalf <= '0';
			elsif ( er = '1' ) then
				sshalf <= not sshalf;
			end if;
		end if;
	end process;	
	
	-- core

	row_gen : for i in 0 to 3 generate
		key_inj : if ( i mod 4 = 0 ) generate																								
			keyinj_gen : for j in nw-1 downto 0 generate 
				add_call : adder generic map ( adder_type => adder_type, n => 64 ) port map ( a => keyout(j), b => round(i,j) , s => keyinj(j));
			end generate;			
			mix_gen_gen : for j in 0 to nw/2-1 generate
				mix_gen : entity work.skein_mix_4r(struct) generic map ( adder_type => adder_type, rotate_0 => rot(j,i), rotate_1 => rot(j,i+4) ) port map ( sel => sshalf, a => keyinj(2*j), b => keyinj(2*j+1), c => roundout(i,2*j), d => roundout(i,2*j+1) );
			end generate;
		end generate;
		nokey_inj : if (i mod 4 /= 0 ) generate	
			mix_gen_gen : for j in 0 to nw/2-1 generate
				mix_gen_r : entity work.skein_mix_4r(struct) generic map (adder_type => adder_type,  rotate_0 => rot(j,i), rotate_1 => rot(j,i+4) ) port map ( sel => sshalf, a => round(i,2*j), b => round(i,2*j+1), c => roundout(i,2*j), d => roundout(i,2*j+1) );
			end generate;
		end generate;
	end generate;			  
	
	perm1: for i in 1 to 4 generate 
		perm2 : for j in 0 to nw-1 generate
			round(i,j) <= roundout(i-1,perm(j));
		end generate;
	end generate;
	--------- ROUND -------

	-----------------------			   

	
	threefish_out_gen : for i in nw-1 downto 0 generate
		threefish(64*(i+1)-1 downto 64*i) <= keyinj(i);
	end generate;
	cv <= threefish xor msg;
	
	keyin <= iv when sf = '1' else cv;
	keygen_gen : entity work.skein_keygen(struct) 
		generic map (version => version, adder_type => adder_type, b => b, nw => nw) 
		port map ( clk => clk, rst => rst, load => snb, en => er, keyin => keyin, tweak => tweak, keyout => keyout );
	
	switch_out <= cv(h-1 downto 0);
	switch1 <= switch_endian_word(switch_out, h, iw); 
	switch2 <= switch_endian_byte(switch1,h,iw);
	dout <= switch2;	

end struct;

Generated on Tue Nov 22 15:16:34 CET 2011
Home