Quiero probar un núcleo IP de video que lee un bloque de memoria y vuelve a escribir en él. El núcleo de IP está utilizando el VFBC. Mi idea para la prueba era escribir un núcleo que se pareciera al VFBC, pero solo usara una RAM simple de 32 Megas como back-end.
Se asigna así:
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 se bloquea alegando que necesita más de 2 gigas de ram, y quetasim asigna 12 gigas en el proceso de compilación para la simulación.
Nota: No quiero sintetizar esto. ¡Es solo para simulación!
Entonces la pregunta es: ¿cómo puedo simular tal RAM de manera eficiente en VHDL?
Si la memoria que está simulando cabe en la RAM de la estación de trabajo, lo más fácil es usar un almacenamiento de tamaño fijo. Pero como has visto, las señales son mucho más caras que las variables. Esta diferencia está relacionada con el modelo de simulación de eventos discretos en el que se basa VHDL. Una asignación de señal programa una transacción en un momento dado, pero una asignación de variable es estrictamente una declaración secuencial que se ejecuta en tiempo de simulación cero. La diferencia se puede ver en el uso de memoria de los dos modelos diferentes. Los resultados se obtienen ejecutando el siguiente código de ejemplo en Riviera PRO.
Asignación de memoria cuando se utiliza una señal para el almacenamiento de datos:
Allocation: Simulator allocated 891567 kB (elbread=1023 elab2=890389 kernel=154 sdf=0)
Asignación de memoria cuando se utiliza una variable para el almacenamiento de datos:
Allocation: Simulator allocated 39599 kB (elbread=1023 elab2=38421 kernel=154 sdf=0)
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;
¿Necesita usar toda esa memoria?
¿Podrías salirte con la tuya simulando un recuerdo escaso...
Usando alguna estructura de datos como un diccionario (tengo un árbol AVL - en mi biblioteca 'hecho en el trabajo', por lo que me temo que no puedo compartirlo :( ) puede almacenar solo los valores que se han escrito y las direcciones en las que fueron escritas. Si su simulación solo toca una pequeña fracción de la matriz, ¡puede ahorrar mucho!
Los modelos de memoria de Micron solían hacer este tipo de cosas, solían new
asignar una fila a la vez a medida que se accedía. Vea si puede desenterrar sus viejos modelos DRAM síncronos de velocidad de datos única, fueron bastante instructivos, según recuerdo.
usuario_1818839
Karsten Becker