-- +-----------------------------+ -- | Copyright 1995-1996 DOULOS | -- | Library: memory | -- | designer : Tim Pagden | -- | opened: 26 Nov 1995 | -- +-----------------------------+ library vfp; library ieee; architecture original of sram_core_GENERIC is use vfp.host_environment_parameters.all; use vfp.standard_types.all; use vfp.generic_functions.all; use vfp.generic_conversions.all; use IEEE.std_logic_1164.all; constant memory_depth : integer := 2 ** address_width; constant num_bits_in_integer : integer := vfp.host_environment_parameters.num_bits_in_integer; attribute dnh_file_name : string(1 to 12); attribute dnh_file_name of sram_core_GENERIC : entity is architecture_DNH_filename; begin -- address, 0 to 31 -- memory_depth, 0 to 7 -- num_slices_in_integer, 4 -- WE is inactive after the posedge until the -ve edge -- CS and OE are both active high -- the disadvantage of modeling with integer memory is that there's -- no representation of undefined or unknown in the integer memory -- itself. As the default value of integer is 100..000 in 32 bit -- parlance, you have to be aware that 000..000 could mean -- uninitialized as well as real all-zero data ram_access: process (address, cs, we, oe) constant num_slices_in_integer : integer := num_bits_in_integer / data_in'length; constant memory_depth : integer := (2**(address'length)) / num_slices_in_integer; type integer_memory is array (0 to memory_depth-1) of integer; variable memory_array : integer_memory; variable memory_index : integer; variable memory_data : integer; variable memory_word : std_ulogic_vector(num_bits_in_integer-1 downto 0); variable intra_memory_index : integer; variable upper_bound : integer; variable invalid_control_signals : boolean; variable address_int : integer; begin data_out <= (others => 'X'); -- initially set output buffers driving unknowns if not (cs = '1' or cs = '0') then invalid_control_signals := TRUE; elsif not (oe = '1' or oe = '0') then invalid_control_signals := TRUE; elsif not (we = '1' or we = '0') then invalid_control_signals := TRUE; else invalid_control_signals := FALSE; data_out <= (others => 'Z'); -- set output buffers high-impedance if memory control signals are valid levels end if; if not invalid_control_signals then -- cs, oe and we must each be 1 or 0 for this branch to be taken address_int := to_integer(address); if cs = '1' then -- memory access possible if oe = '1' then -- read or clash possible if we = '1' then -- read cycle memory_index := address_int / num_slices_in_integer; -- 4 := 17/4 -- converts address into index into memory memory_data := memory_array(memory_index); -- extracts integer where addressed word is placed memory_word := to_std_ulogic_vector (memory_data, num_bits_in_integer); -- converts integer to 32-bit vector intra_memory_index := address_int mod num_slices_in_integer; -- 1 := 17/4 -- address now used to get word-index of addressed word in 32-bit vector upper_bound := (intra_memory_index + 1) * data_out'length; -- defines upper index of addressed word in 32-bit vector data_out <= To_StdLogicVector (memory_word(upper_bound-1 downto upper_bound-data_out'length)); -- To_StdLogicVector is IEEE std_logic_1164, drives data bus with addressed memory word elsif we = '0' then assert false report "oe and we are both active." severity warning; end if; elsif oe = '0' then -- oe is inactive, only write possible if (we = '1') and we'event then -- write cycle memory_index := address_int / num_slices_in_integer; -- converts address into index into memory memory_data := memory_array(memory_index); -- extracts integer where addressed word is placed memory_word := to_std_ulogic_vector (memory_data, num_bits_in_integer); -- converts integer to 32-bit vector intra_memory_index := address_int mod num_slices_in_integer; -- address now used to get word-index of addressed word in 32-bit vector upper_bound := (intra_memory_index + 1) * data_in'length; -- defines upper index of addressed word in 32-bit vector memory_word(upper_bound-1 downto upper_bound-data_in'length) := to_StdULogicVector (data_in); -- inserts data into extracted memory word -- ... now convert whole word to integer & place back in integer array memory_array(memory_index) := to_integer(to_twos_complement(memory_word)); elsif we = '1' then -- both we and oe not active, nowt happens elsif we = '0' then -- we active, nowt happens until posedge of WE end if; end if; else -- memory not selected end if; else assert false report "Control signals are not active, memory is not selected." severity note; end if; end process; end original;