3
\$\begingroup\$

I want to test a video IP core that reads a block of memory and writes to it again. The IP core is using the VFBC. My idea for testing was to write a core that looks like the VFBC, but just uses a simple 32Meg RAM as back-end.

It is allocated like this:

memory_size : NATURAL := ((2 * 2048) * 2048)
type memory_array is array (0 to (memory_size - 1)) of std_logic_vector(31 downto 0);
signal memory : memory_array;

ISim is crashing claiming that it needs more than 2 gig of ram, and questasim is allocating 12gig in the process of compilation for simulation.

Note: I don't want to synthesize this. It is for simulation only!

So the question is: how can I simulate such an RAM efficiently in VHDL?

\$\endgroup\$
2
  • 5
    \$\begingroup\$ Use a much simpler datatype for the memory array, such as integer, rather than std_logic_vector \$\endgroup\$
    – user16324
    Commented Nov 20, 2013 at 12:01
  • \$\begingroup\$ Thanks, that did improve it significantly. The load times are not acceptable. Still wondering though why it needs 2gig of RAM. Anyway better than 12 :) \$\endgroup\$ Commented Nov 20, 2013 at 15:11

2 Answers 2

6
\$\begingroup\$

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 <= not clk after 10 ns;

    -----------------------------------
    stimulus :
    -----------------------------------    
        process 
    begin
        for n in 0 to 100 loop
            wait until falling_edge(clk);
            we <= '1' ; 
            writedata <= n;
            addr <= 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 <= 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;
\$\endgroup\$
1
  • \$\begingroup\$ wow, I wouldn't have thought that this makes such a huge difference in simulation. \$\endgroup\$
    – andrsmllr
    Commented Dec 1, 2013 at 9:58
1
\$\begingroup\$

Are you needing to use all of that memory?

Could you get away with simulating a sparse memory...

Using some data structure like a dictionary (I have an AVL tree - in my 'made-at-work' library, so i can't share it I'm afraid :( ) you can store just the values which have been written and the addresses they were written to. If your simulation only touches a small fraction of the array, you can save a lot!

Micron's memory models used to do this kind of thing, they would use new to allocate a row at a time as they were accessed. See if you can dig up their old single-data-rate synchronous DRAM models, they were quite instructive as I recall.

\$\endgroup\$
1
  • \$\begingroup\$ In my case the memory is storing the whole picture and the resulting picture. The size is thus fully used, so your approach would probably not result in any savings. But the idea itself sounds good. \$\endgroup\$ Commented Nov 21, 2013 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.