Simulation of large RAM
If the memory you are simulating can fit into the ram of the workstation then using a fixed-size storage is the easiest to use. But as you have seen, signals are much more expensive compared to variables. This difference is related to the discrete event simulation model that VHDL is based on. A signal assignment schedules a transaction at a given point in time, but a variable assignment is strictly a sequential statement that execute in zero simulation time. The difference can be seen in the memory usage of the two different models. The results are obtained by running the example code below in Riviera PRO.

Memory allocation when using a signal for data storage:

Allocation: Simulator allocated 891567 kB (elbread=1023 elab2=890389 kernel=154 sdf=0)


Memory allocation when using a variable for data storage:

 Allocation: Simulator allocated 39599 kB (elbread=1023 elab2=38421 kernel=154 sdf=0)


Example code

library ieee;
use ieee.std_logic_1164.all;
use std.env;

entity memtest is
end;

architecture sim of memtest is
    signal clk : std_logic := '0';

    signal we : std_logic;
    signal writedata, q : integer;
    signal addr : natural;

    -- Uncomment or comment to switch between variable or signal for memory storage.
    --signal mem : integer_vector(0 to 2 * 2048**2-1);

begin

    clk &lt;= not clk after 10 ns;

    -----------------------------------
    stimulus :
    -----------------------------------    
        process 
    begin
        for n in 0 to 100 loop
            wait until falling_edge(clk);
            we &lt;= '1' ; 
            writedata &lt;= n;
            addr &lt;= n;
        end loop;
        env.stop;
    end process;

    -----------------------------------    
    memory :
    -----------------------------------
    process ( clk )
            -- Uncomment or comment to switch between variable or signal for memory storage.
        variable mem : integer_vector(0 to 2 * 2048**2-1);
    begin
        if rising_edge(clk) then
            q &lt;= mem(addr);

            if we = '1' then
                                -- Remember to modify assignment operator when switching data storage.
                mem(addr) := writedata;
            end if;
        end if;
    end process;
end;