-- ============================================================================
--
-- Design unit      :   tech_subkey_memory
--
-- File Name        :   tech_subkey_memory_virtex2.vhd
--
-- Purpose          :   The module provides subkey memory for implementation of
--                      encryption, decryption and key schedule using 32-bit
--                      datapath on Virtex-II family
--
--
-- Depends on       :
--
--  - Package(s)    :   aes_definitions, tech_iface
--
--  - 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            :   parity memory is used to store number of rounds
--                      beside the subkey
--
--
-- Author(s)        :   A. Freund (af) <a.freund@dsi-it.de>
--                      Digitale Signalverabeitung & Informationstechnik GmbH,
--                      Bremen, Germany
--
--
-- ============================================================================
--
-- Revision List:
-- Version      Author(s)       Date        Changes
--
-- v0.00        af              2006-11-15  initial version
--
-- see SVN logs
--
-- ============================================================================
--
-- Naming conventions:
--
--  - 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 ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

library unisim;
use unisim.vcomponents.all;


use work.aes_definitions.all;
use work.tech_iface.all;


entity tech_subkey_memory is
	port (
		clk			:	in	std_logic;						-- clock
		key_sched_i	:	in	subkey_memory_ks_in_type;		-- see package tech_iface
		enc_dec_i	:	in	subkey_memory_ed_in_type;		-- see package tech_iface
		enc_dec_o	:	out	subkey_memory_ed_out_type		-- see package tech_iface
	);
end tech_subkey_memory;


architecture behavioural of tech_subkey_memory is

	signal s_pm_a_in : std_logic_vector(3 downto 0) := (others => '0');
	signal s_pm_b_out : std_logic_vector(3 downto 0);

	signal s_addr_a : std_logic_vector(key_id_t'length + aes_round_no_t'length + part_no_t'length - 1 downto 0);
	signal s_addr_b : std_logic_vector(key_id_t'length + aes_round_no_t'length + part_no_t'length - 1 downto 0);


begin


	s_pm_a_in(aes_round_no_t'range) <= key_sched_i.rounds;

	s_addr_a <= key_sched_i.key_id & key_sched_i.subkey_no & key_sched_i.part_no;

	s_addr_b <= enc_dec_i.key_id & enc_dec_i.subkey_no & enc_dec_i.part_no;


	-- 1 Block-RAMs for subkey memory, port A : key schedule, port B : en-/decryprion

		-- RAMB16_S36_S36: Virtex-II/II-Pro, Spartan-3/3E 512 x 32 + 4 Parity bits Dual-Port RAM
		-- Xilinx  HDL Language Template version 7.1i

	skm: RAMB16_S36_S36
		generic map (
			WRITE_MODE_A => "READ_FIRST", 	--  WRITE_FIRST, READ_FIRST or NO_CHANGE
			WRITE_MODE_B => "READ_FIRST", 	--  WRITE_FIRST, READ_FIRST or NO_CHANGE
			SIM_COLLISION_CHECK => "NONE" 	-- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL"
		)
		port map (
			DOA		=>	open,					-- Port A 32-bit Data Output
			DOB		=>	enc_dec_o.subkey,		-- Port B 32-bit Data Output
			DOPA	=>	open,					-- Port A 4-bit Parity Output
			DOPB	=>	s_pm_b_out,				-- Port B 4-bit Parity Output
			ADDRA	=>	s_addr_a,				-- Port A 9-bit Address Input
			ADDRB	=>	s_addr_b,				-- Port B 9-bit Address Input
			CLKA	=>	clk,					-- Port A Clock
			CLKB	=>	clk,					-- Port B Clock
			DIA		=>	key_sched_i.subkey,		-- Port A 32-bit Data Input
			DIB		=>	X"00000000",			-- Port B 32-bit Data Input
			DIPA	=>	s_pm_a_in,				-- Port A 4-bit parity Input
			DIPB	=>	"0000",					-- Port-B 4-bit parity Input
			ENA		=>	key_sched_i.write_en,	-- Port A RAM Enable Input
			ENB		=>	enc_dec_i.rd_en,		-- PortB RAM Enable Input
			SSRA	=>	'0',					-- Port A Synchronous Set/Reset Input
			SSRB	=>	'0',					-- Port B Synchronous Set/Reset Input
			WEA		=>	key_sched_i.write_en,	-- Port A Write Enable Input
			WEB		=>	'0'						-- Port B Write Enable Input
		);



	enc_dec_o.rounds <= s_pm_b_out(aes_round_no_t'range);


end behavioural;
