--- ============================================================================
--
-- Design unit      :   aes_column_ops
--
-- File Name        :   aes_column_ops.vhd
--
-- Purpose          :   Design file
--
--
-- 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_gf_2exp8_arith.all;


package aes_column_ops is


	type column_t is array (0 to 3) of gf_2exp8_t;

	function mix_column(col : in column_t) return column_t;

	function inv_mix_column(col : in column_t) return column_t;



end aes_column_ops;


package body aes_column_ops is


	type trans_matrix_t is array (0 to 3, 0 to 3) of gf_2exp8_t;

	constant TRANS_MATRIX : trans_matrix_t :=
	(
		(X"02", X"03", X"01", X"01"),
		(X"01", X"02", X"03", X"01"),
		(X"01", X"01", X"02", X"03"),
		(X"03", X"01", X"01", X"02")
	);

	constant INV_TRANS_MATRIX : trans_matrix_t :=
	(
		(X"0e", X"0b", X"0d", X"09"),
		(X"09", X"0e", X"0b", X"0d"),
		(X"0d", X"09", X"0e", X"0b"),
		(X"0b", X"0d", X"09", X"0e")
	);


	function mix_column(col : in column_t) return column_t is
		variable v_col : column_t;
	begin
		for c in v_col'range loop
			v_col(c) := X"00";
		end loop;

		for r in v_col'range loop
			for c in v_col'range loop
				v_col(r) := add_gf_2exp8(v_col(r), mul_gf_2exp8(TRANS_MATRIX(r,c), col(c)));
			end loop;
		end loop;

		return v_col;
	end mix_column;


	function inv_mix_column(col : in column_t) return column_t is
		variable v_col : column_t;
	begin
		for c in v_col'range loop
			v_col(c) := X"00";
		end loop;

		for r in v_col'range loop
			for c in v_col'range loop
				v_col(r) := add_gf_2exp8(v_col(r), mul_gf_2exp8(INV_TRANS_MATRIX(r,c), col(c)));
			end loop;
		end loop;

		return v_col;
	end inv_mix_column;


end aes_column_ops;
