-- memory model with timing (OE_b=0)

library ieee;
use ieee.std_logic_1164.all;
library bitlib;
use bitlib.bit_pack.all;

entity static_RAM is
generic (constant tAA: time := 120 ns;	-- 6116 static CMOS RAM
	constant tACS:time := 120 ns;
	constant tCLZ:time := 10 ns;
	constant tCHZ:time := 10 ns;  
	constant tOH:time := 10 ns;
	constant tWC:time := 120 ns;
	constant tAW:time := 105 ns;
	constant tWP:time := 70 ns;
	constant tWHZ:time := 35 ns;
	constant tDW:time := 35 ns;
	constant tDH:time := 0 ns;
	constant tOW:time := 10 ns);

port (CS_b, WE_b, OE_b: in bit;
  Address: in bit_vector(7 downto 0);
  Data: inout std_logic_vector(7 downto 0) := (others => 'Z'));
end Static_RAM;

architecture SRAM of Static_RAM is
type RAMtype is array(0 to 255) of bit_vector(7 downto 0);
signal RAM1: RAMtype := (others => (others => '0'));  

begin
	RAM: process
	begin
		if (rising_edge(WE_b) and CS_b'delayed = '0') 
			  or (rising_edge(CS_b) and WE_b'delayed = '0') then
			RAM1(vec2int(Address'delayed)) <= to_bitvector(Data'delayed); --write
			if CS_b = '0' then
				Data <= transport Data'delayed after tOW;	-- read back after write
			  	-- Data'delayed is the value of Data just before the rising edge
			end if;
		end if;
		if falling_edge(WE_b) and CS_b = '0' then 	-- enter write mode
			Data <= transport "ZZZZZZZZ" after tWHZ;
		end if;
		if CS_b'event and OE_b = '0' then 
			if CS_b = '1' then					-- RAM is deselected
				Data <= transport "ZZZZZZZZ" after tCHZ;
			elsif WE_b = '1' then  				--read
				Data <= "XXXXXXXX" after tCLZ;
				Data <= transport to_stdlogicvector(RAM1(vec2int(Address))) 
							after tACS;
			end if;	
		end if;
		if Address'event and CS_b ='0' and OE_b ='0' and WE_b ='1' then --read	
				Data <= "XXXXXXXX" after tOH;
				Data <= transport to_stdlogicvector(RAM1(vec2int(Address))) 
							after tAA;
		end if;
		wait on CS_b, WE_b, Address;
	end process RAM;

	check: process
	begin
		if NOW /= 0 ns then
			if address'event then
				assert (address'delayed'stable(tWC))	-- tRC = tWC assumed
					report "Address cycle time too short"
					severity WARNING;
			end if;
	-- The following code only checks for a WE_b controlled write:	
			if rising_edge(WE_b) and CS_b'delayed = '0' then
				assert (address'delayed'stable(tAW))
					report "Address not valid long enough to end of write"
					severity WARNING;
				assert (WE_b'delayed'stable(tWP))
					report "Write pulse too short"
					severity WARNING;
				assert (Data'delayed'stable(tDW))
					report "Data setup time too short"
					severity WARNING;
				wait for tDH;
				assert (Data'last_event >= tDH)
					report "Data hold time too short"
					severity WARNING;
			end if;
		end if;
		wait on WE_b, address, CS_b;
	end process check;
end SRAM;

