--- ============================================================================
--
-- Design unit      :   aes_common
--
-- File Name        :   aes_common.vhd
--
-- Purpose          :   This package defines supplemental types, subtypes,
--                      constants, and functions 
--
--
-- Depends on       :
--
-- - Package(s)     :   -
--
-- - Module(s)      :   -
--
--
-- Dev. Platform    :   Xilinx ISE 8.1i SP3 / Win32 (W2k SP4)
--
-- - Simulator(s)   :   Modelsim XE III 6.0d
--
-- - Synthesis      :   Xilinx XST
--
-- - Place & Route  :   Xilinx PAR
--
--
-- Errors           :   None known
--
--
-- Limitations      :   None known
--
--
-- Notes            :   -
--
--
-- Author(s)        :   A. Freund (af) <a.freund@dsi-it.de>, 
--                      M.v.d.Wall (mvdw) <vdwall@dsi-it.de>
--                      Digitale Signalverabeitung & Informationstechnik GmbH,
--                      Bremen, Germany
--
-- ============================================================================
--
-- Revision List:
--
-- see SVN logs
--
-- ============================================================================
--
-- Naming conventions:
--
-- - coding style: record-signals for related purposes (Gaisler-style)
-- - active-low signals are indicated by appending "_n"
-- - constants are in UPPERCASE
-- - name parts are separated by "_"
--
-- ============================================================================


library ieee;
use ieee.std_logic_1164.all;

use work.aes_definitions.all;
use work.aes_row_ops.all;
use work.aes_column_ops.all;



package aes_common is


	function add_round_key(state, state_key : aes_state_t) return aes_state_t;

	function select_column(state : aes_state_t; pos : natural) return column_t;

	function replace_column(state : aes_state_t; col : column_t; pos : natural) return aes_state_t;

	function select_row(state : aes_state_t; pos : natural) return row_t;

	function replace_row(state : aes_state_t; row : row_t; pos : natural) return aes_state_t;

	function to_aes_state_matrix(st : aes_state_t) return aes_sbox_matrix_t;
	function to_aes_state_vector(bb : aes_sbox_matrix_t) return aes_state_t;

end aes_common;


package body aes_common is


	function add_round_key(state, state_key : aes_state_t) return aes_state_t is
	begin
		return (state xor state_key);
	end add_round_key;


	function select_column(state : aes_state_t; pos : natural) return column_t is
		variable v_col : column_t;
	begin
		for i in v_col'range loop
			v_col(i) := state((127 - 32*pos - 8*i) downto (127 - 32*pos - 8*i) - 7);
		end loop;

		return v_col;
	end select_column;




	function replace_column(state : aes_state_t; col : column_t; pos : natural) return aes_state_t is
		variable v_st : aes_state_t;
	begin
		v_st := state;

		for i in col'range loop
			v_st((127 - 32*pos - 8*i) downto (127 - 32*pos - 8*i) - 7) := col(i);
		end loop;

		return v_st;
	end replace_column;




	function select_row(state : aes_state_t; pos : natural) return row_t is
		variable v_row : row_t;
	begin
		for i in v_row'range loop
			v_row(i) := state((127 - 8*pos - 32*i) downto (127 - 8*pos - 32*i) - 7);
		end loop;

		return v_row;
	end select_row;




	function replace_row(state : aes_state_t; row : row_t; pos : natural) return aes_state_t is
		variable v_st : aes_state_t;
	begin
		v_st := state;

		for i in row'range loop
			v_st((127 - 8*pos - 32*i) downto (127 - 8*pos - 32*i) - 7) := row(i);
		end loop;

		return v_st;
	end replace_row;



	function to_aes_state_matrix(st : aes_state_t) return aes_sbox_matrix_t is
		variable v_row : row_t;
		variable v_line : std_logic_vector(31 downto 0);
		variable v_bb : aes_sbox_matrix_t;
	begin
		for r in v_bb'range(1) loop
			for c in v_bb'range(2) loop
				v_bb(r, c) := (others => '0');
			end loop;
		end loop;

		for r in v_bb'range(1) loop
			v_row := select_row(st, r);
			v_line := v_row(0) & v_row(1) & v_row(2) & v_row(3);

			for c in v_bb'range(2) loop
				v_bb(r, c)(7 downto 0) := v_line(31 - 8*c downto 24 - 8*c);
			end loop;

		end loop;

		return v_bb;
	end to_aes_state_matrix;



	function to_aes_state_vector(bb : aes_sbox_matrix_t) return aes_state_t is
		variable v_row : row_t;
		variable v_line : std_logic_vector(31 downto 0);
		variable v_st : aes_state_t;
	begin
		v_st := (others => '0');

		for r in bb'range(1) loop
			v_line := (others => '0');

			for c in bb'range(2) loop
				v_line(31 - 8*c downto 24 - 8*c) := bb(r, c)(7 downto 0);
			end loop;

			for i in v_row'range loop
				v_row(i) := v_line(31 - 8*i downto 31-8*i - 7);
			end loop;

			v_st := replace_row(v_st, v_row, r);
		end loop;

		return v_st;
	end to_aes_state_vector;


end aes_common;