-- -- description of a passive SRAM -- library ieee; use ieee.std_logic_1164.all; use std.textio.all; use ieee.std_logic_arith.all; use work.txt_util.all; entity SRAM2 is generic( mem_words: integer := 32 ); port( RST: in std_logic; -- doesn't go to RAM, but is useful for testing A: in std_logic_vector(7 downto 0); WE_L: in std_logic; RD_L: in std_logic; D: inout std_logic_vector(7 downto 0) ); end SRAM2; -- I/O Dictionary -- -- A: Address bus -- WE_L: Write Enable -- RD_L: Read Enable -- D: Data bus -- -- architecture model of SRAM2 is constant tSU : time := 4 ns; constant tH : time := 3 ns; constant tW_WE : time := 40 ns; constant tRD : time := 6 ns; constant tW_RD : time := 40 ns; signal add_hold: boolean := false; signal dat_hold: boolean := false; signal add_val: std_logic_vector(A'range); signal dat_val: std_logic_vector(D'range); signal no_reset_yet: boolean := true; begin wait_for_reset: process begin wait until RST = '1'; wait until RST = '0'; no_reset_yet <= false; end process wait_for_reset; -- hold time monitors add_monitor: process begin wait until A'event; assert not add_hold or A = add_val report "E@SIMPLE_SRAM: Address hold time violated" severity Error; end process add_monitor; dat_monitor: process begin wait until D'event; assert not dat_hold or D = dat_val report "E@SIMPLE_SRAM: Data hold time violated" severity Error; end process dat_monitor; test_proc: process -- Internal Memory type mem_add_type is array (integer range <>) of std_logic_vector(A'range); type mem_dat_type is array (integer range <>) of std_logic_vector(D'range); variable mem_add: mem_add_type(mem_words-1 downto 0); variable mem_dat: mem_dat_type(mem_words-1 downto 0); variable used_pnt: integer := 0; procedure write is variable start_cycle: time; begin start_cycle := now; -- check setup times assert A'last_event >= tSU report "E@SIMPLE_SRAM: Address setup time violated" severity Error; assert D'last_event >= tSU report "E@SIMPLE_SRAM: Data setup time violated" severity Error; -- report action for transaction log print("I@SIMPLE_SRAM: "& hstr(D)& "h written to "& hstr(A)& "h"); -- can't do this anymore: --*-- verify address --*assert A = wadd --* report "E@SIMPLE_SRAM: Address incorrect, expected "& --* str(wadd)& " received "& str(A) --* severity Error; -- can't do this anymore: --*-- verify data --*for i in wdat'range loop --* if wdat(i) /= '-' and wdat(i) /= D(i) then --* print("E@SIMPLE_SRAM: Write Data Invalid, written data = "& str(D)& --* " expected data = "& str(wdat) ); --* exit; --* end if; --*end loop; wait until to_X01(WE_L) = '1'; -- Store written data for i in 0 to used_pnt loop if i = used_pnt then -- access to a new address mem_add(i) := A; mem_dat(i) := D; if used_pnt < mem_words - 1 then used_pnt := used_pnt + 1; else print("W@SRAM2: Simulation model can't handle additional addresses"); end if; end if; if mem_add(i) = A then -- access to an existing address mem_dat(i) := D; exit; end if; end loop; -- verify pulse width on WE_L assert now - start_cycle >= tW_WE report "E@SIMPLE_SRAM: WE_L pulse width violated" severity Error; -- verify address and data haven't changed during the cycle assert A'last_event >= (now - start_cycle) report "E@SIMPLE_SRAM: Address hold time violated" severity Error; assert D'last_event >= (now - start_cycle) report "E@SIMPLE_SRAM: Data hold time violated" severity Error; -- now make sure the hold times are maintained add_hold <= true, false after tH; dat_hold <= true, false after tH; add_val <= A; dat_val <= D; end write; procedure read is constant xx: std_logic_vector(D'range) := (others => 'X'); variable start_cycle: time; begin start_cycle := now; -- check setup times assert A'last_event >= tSU report "E@SIMPLE_SRAM: Address setup time violated" severity Error; assert D = (D'range => 'Z') report "E@SIMPLE_SRAM: Data bus is driven" severity Error; -- can't do this anymore: --*-- verify address --*assert A = wadd --* report "E@SIMPLE_SRAM: Address incorrect, expected "& --* str(wadd)& " received "& str(A) --* severity Error; -- Retrieve data from internal memory for i in 0 to used_pnt+1 loop if i = used_pnt+1 then -- access to a new address print("W@SRAM2: Address has not been written to yet"); print("I@SIMPLE_SRAM: "& hstr(xx)& " provided for "& hstr(A)& "h"); D <= (others => 'X'); exit; end if; if mem_add(i) = A then -- access to an existing address D <= mem_dat(i) after tRD; print("I@SIMPLE_SRAM: "& hstr(mem_dat(i))& "h provided for "& hstr(A)& "h"); exit; end if; end loop; wait until to_X01(RD_L) = '1'; -- verify pulse width on RD_L assert now - start_cycle >= tW_RD report "E@SIMPLE_SRAM: RD_L pulse width violated" severity Error; -- verify address and data haven't changed during the cycle assert A'last_event >= (now - start_cycle) report "E@SIMPLE_SRAM: Address hold time violated" severity Error; -- now make sure the hold times are maintained add_hold <= true, false after tH; dat_hold <= false; add_val <= A; end read; begin D <= (others => 'Z'); wait until WE_L'event or RD_L'event; assert (WE_L /= 'X' and WE_L /= 'Z' and WE_L /= 'U' and WE_L /= '-') or no_reset_yet report "E@SRAM2: WE_L="& str(WE_L)& " invalid value" severity Error; assert (RD_L /= 'X' and RD_L /= 'Z' and RD_L /= 'U' and WE_L /= '-') or no_reset_yet report "E@SRAM2: RD_L="& str(RD_L)& " invalid value" severity Error; assert to_X01(RD_L) /= '0' or to_X01(WE_L) /= '0' report "E@SRAM2: both read and write are asserted"& "RD_L="& str(RD_L)& " WE_L="& str(WE_L) severity Error; -- decide whether read or write access if to_X01(WE_L) = '0' then write; end if; if to_X01(RD_L) = '0' then read; end if; end process test_proc; end model;