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.