--
-- Copyright (c) 2001 Koay Kah Hoe.  Permission to copy is granted
-- provided that this header remains intact.  This code is provided
-- with no warranties.
--
-- Version : 1.0
--

-------------------------------------------------------------------------------
-- RAM_S: Library module created by VHDL Module Generator
--
-- RAM_S
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity RAM_S is
	generic (
		AWidth: integer:= 7;
		DataWidth: integer:= 8
	);
	port (
		D: in UNSIGNED(DataWidth-1 downto 0);
		A: in UNSIGNED(AWidth-1 downto 0);
		WE,WCLK : in STD_LOGIC;
		O : out UNSIGNED(DataWidth-1 downto 0)
	);
	type ENUM_Multiplexer is (TristateBuffers, NormalGates);
	constant Multiplexer: ENUM_Multiplexer := TristateBuffers;
end RAM_S;

architecture RAM_S_arch of RAM_S is

	constant len : INTEGER := 2**(AWidth-4);
	signal RAMSel : STD_LOGIC_VECTOR(len-1 downto 0);
	type RAMOut_Array is array (0 to len-1) of UNSIGNED(O'range);
	signal RAMOut : RAMOut_Array;
	signal iA : integer range 0 to len-1;

	component RAM16XnS
	generic (
		DataWidth: integer := DataWidth 
	);
	port (
		D: in UNSIGNED(DataWidth-1 downto 0);
		A: in UNSIGNED(3 downto 0);
		WE,WCLK : in STD_LOGIC;
		O : out UNSIGNED(DataWidth-1 downto 0)
	);
	end component;

begin

	-- AWidth > 4
	G1: if AWidth>4 generate
		iA <= CONV_INTEGER(A(AWidth-1 downto 4));
	
		-- Convert binary number to ripple format
		process (iA,WE)
			variable S:UNSIGNED (len-1 downto 0);
		begin
			S := CONV_UNSIGNED(1,len);
			for I in 0 to len-1 loop
				if I < iA then
					S := SHL(S,"1");
				end if;
			end loop;
			if WE = '0' then
				S := (others=>'0');
			end if;
			RAMSel <= CONV_STD_LOGIC_VECTOR(S,len);
		end process;
	
		G1_1: for I in 0 to len-1 generate
			U_RAM16XnS: RAM16XnS
				port map (D, A(3 downto 0), RAMSel(I), WCLK, RAMOut(I));

			-- Multiplexer using tristate buffers
			G1_1_1: if Multiplexer=TristateBuffers generate
				O <= RAMOut(I) when iA=I else (others=>'Z');
			end generate;
		end generate;

		-- Multiplexer using normal gates
		G1_2: if Multiplexer=NormalGates generate
			process (iA,RAMOut)
			begin
				O <= RAMOut(0);
				for I in 1 to len-1 loop
					if iA=I then
						O <= RAMOut(I);
					end if;
				end loop;
			end process;
		end generate;

	end generate;

	-- AWidth = 4
	G2: if AWidth=4 generate
		U_RAM16XnS: RAM16XnS
			port map (D, A, WE, WCLK, O);
	end generate;

end RAM_S_arch;

