The behavioural code presented in this model will enable you to create a large-capacity RAM model limited only by the virtual memory of your computer.
When modelling 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 modelling fixed-size RAMs, it is often better to use an array variable rather than a signal for the RAM storage. Note that for inference of block RAMs in FPGAs, many tools require the use of signals. In this model, however, we are not going to use an array at all. Instead, we allocate memory space each time a new address is used by using an access type.
On a write, the model looks to see if the address has already been used. If so, the data is overwritten. If not, new storage is allocated for the address and data. On a read, the model searches for the address given, and on finding it returns the data. If the address is not found the memory returns 'U', for "uninitialised". An 'X' may also be a valid choice.
In this model, 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 Notices page for details).
-- Generic Large-capacity RAM Model
-- +-----------------------------+
-- | Copyright 1992-2008 DOULOS |
-- | Library: memory |
-- | designer : Tim Pagden |
-- +-----------------------------+
--
-- Ram write Ram Read
--
-- ___ ___ ___________
-- nCS \______________/ \_____________/
-- _______ ____________________________________
-- nWE \___/
-- ____________________________ _______________
-- nOE \___/
-- ____ _______________ __________________ ________
-- Addr ____X_______________X__________________X________
--
-- ____ _______________ __
-- Data ____X_______________X------- X__X---------------
--
library IEEE;
use IEEE.std_logic_1164.all;
use WORK.RamPack.all;
entity BigRam is
port (Address: in AddrType;
Data: inout DataType;
nCS, nWE, nOE: in Std_logic);
end;
architecture Lists of BigRam is
-- Model using single linked list
begin
process (Address, nCS, nWE, nOE)
type Item;
type ItemPtr is access Item;
type Item is
record
NextItem: ItemPtr;
Address: AddrType;
Word: DataType;
end record;
variable Head: ItemPtr;
procedure Get (Addr: in AddrType; Word: out DataType) is
-- Get the contents of the ram with address = Addr
variable Ptr: ItemPtr;
begin
Ptr := Head;
while Ptr /= null loop
if Ptr.Address = Addr then
Word := Ptr.Word;
return;
end if;
Ptr := Ptr.NextItem;
end loop;
Word := (others => 'U');
end Get;
procedure Set (Addr: in AddrType; Word: in DataType) is
-- Set the contents of the ram with address = Addr to Word
variable Ptr, PreviousPtr: ItemPtr;
begin
Ptr := Head;
PreviousPtr := null;
while Ptr /= null loop
if Ptr.Address = Addr then
if Word = DataType'(others => 'U') then
-- Delete item from list...
if PreviousPtr = null then
Head := Ptr.NextItem;
else
PreviousPtr.NextItem := Ptr.NextItem;
end if;
DEALLOCATE (Ptr);
else
Ptr.Word := Word;
end if;
return;
end if;
PreviousPtr := Ptr;
Ptr := Ptr.NextItem;
end loop;
if Word /= DataType'(others => 'U') then
-- Insert new item into list...
Ptr := new Item'(NextItem => null, Address => Addr, Word => Word);
if PreviousPtr = null then
Head := Ptr;
else
PreviousPtr.NextItem := Ptr;
end if;
end if;
end Set;
procedure Diagnose is
variable Ptr: ItemPtr;
variable Count: NATURAL := 0;
begin
if Diagnostics then
Ptr := Head;
while Ptr /= null loop
Count := Count + 1;
Ptr := Ptr.NextItem;
end loop;
assert FALSE
report "List length = " & INTEGER'IMAGE(Count)
severity Note;
end if;
end Diagnose;
variable D: DataType;
begin
Data <= (others => 'Z');
if nCS = '0' then
if nOE = '0' then -- Read operation
Get(Address, D);
Data <= D;
Diagnose;
elsif nWE = '0' then -- Write operation
Set (Address, Data);
Diagnose;
end if;
end if;
end process;
end;
To download the VHDL source code for this model, click here.