We can update you automatically when this page changes.
To receive regular notification of updates to our Model of the
Month section, click here.
The behavioural code presented in this month's Model of the Month will enable you to create a large-capacity RAM model limited only by the virtual memory of you computer.
When modeling large memories using VHDL, many users are disappointed by the limited sizes of RAM that they can create. This is because of the way that simulators build the RAM model during elaboration. When modeling RAMs, it is better to use an integer array or an array of bit vectors for the RAM storage rather than an array of std_logic_vectors. In this example, we use an integer array because it is intellectually more challenging!
On this page, we show the VHDL for the generic RAM core (entity and architecture) and a 64k word by 16-bit RAM model which instantiates the generic RAM core. You are welcome to use the source code we provide but you must keep the copyright notice with the code (see the Acknowledgements page for more details).
-- Generic Large-capacity RAM Model -- +-----------------------------+ -- | Copyright 1995-1996 DOULOS | -- | Library: memory | -- | designer : Tim Pagden | -- | opened: 26 Nov 1995 | -- +-----------------------------+ -- Function: 64k x 16 SRAM with separate I/O. OE and CS are active HIGH -- WE latches data on rising edge library ieee; library vfp; use ieee.std_logic_1164.all; use vfp.generic_functions.all; entity sram_64k_16 is generic ( -- more to do with attribute'ing architecture_DNH_filename : string := "????????.dnh" -- ); port ( address : in std_ulogic_vector(15 downto 0); CS : in std_ulogic; WE : in std_ulogic; OE : in std_ulogic; data_in : in std_logic_vector(15 downto 0); data_out : out std_logic_vector(15 downto 0) ); begin -- data bus width must be integer power of 2 bits, < 64 assert is_factor_of_32(data_in'length) report "Width of data bus must be 1, 2, 4, 8, 16 or 32 bits." severity warning; end sram_64k_16; -- Architectures: -- 12.02.96 original PASSED SIMULATION library memory; architecture original of sram_64k_16 is use memory.sram_core_GENERIC_cmpt.all; constant address_width : integer := 16; constant data_width : integer := 16; attribute dnh_file_name : string(1 to 12); attribute dnh_file_name of sram_64k_16 : entity is architecture_DNH_filename; begin G1: sram_core_GENERIC generic map ( address_width => address_width, data_width => data_width ) port map ( address => address, CS => CS, WE => WE, OE => OE, data_in => data_in, data_out => data_out ); end original; -- +-----------------------------+ -- | Copyright 1995-1996 DOULOS | -- | Library: memory | -- | designer : Tim Pagden | -- | opened: 26 Nov 1995 | -- +-----------------------------+ -- Function: generic SRAM model with separate I/O. OE and CS are active HIGH -- WE latches data on rising edge library ieee; library vfp; use ieee.std_logic_1164.all; use vfp.generic_functions.all; entity sram_core_GENERIC is generic ( -- entity parameterization (must have these in the generic map) address_width : integer := 0; -- data_width : integer := 0; -- -- more to do with attribute'ing architecture_DNH_filename : string := "????????.dnh" -- ); port ( address : in std_ulogic_vector(address_width-1 downto 0); CS : in std_ulogic; WE : in std_ulogic; OE : in std_ulogic; data_in : in std_logic_vector(data_width-1 downto 0); data_out : out std_logic_vector(data_width-1 downto 0) ); begin -- data bus width must be integer power of 2 bits, < 64 assert is_factor_of_32(data_width) report "Width of data bus must be 1, 2, 4, 8, 16 or 32 bits." severity warning; end sram_core_GENERIC; -- Architectures: -- 12.02.96 original PASSED SIMULATION 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;
Advanced VHDL Techniques
ASIC Design and Project Services
Doulos Training Courses
Copyright 1995-1997 Doulos
This page was last updated 12th March 1996
We welcome your e-mail comments. Please contact us at: webmaster@doulos.co.uk