Inferir BRAM con direcciones no utilizadas de manera eficiente

3

¿Cuál es la forma correcta de inferir una RAM con algunas direcciones más altas no utilizadas (utilizando RAM de bloque)?
Al usar el código a continuación (valores predeterminados para genéricos, sintetizador Xilinx y mapa), obtengo una RAM del mismo tamaño que si la profundidad estuviera establecida en 2**ADDRWIDTH :

entity foo is
    generic (
        DATAWIDTH : positive := 8;
        DATADEPTH : positive := 5000;
        ADDRWIDTH : positive := 13
    );
    port (
        clk_a  : in std_logic;
        we_a   : in std_logic;
        addr_a : in std_logic_vector(ADDRWIDTH-1 downto 0);
        di_a   : in std_logic_vector(DATAWIDTH-1 downto 0);
        do_a   : out std_logic_vector(DATAWIDTH-1 downto 0)
    );
end foo;

architecture bar of foo is
    type myram_type is array (DATADEPTH-1 downto 0) of std_logic_vector(DATAWIDTH-1 downto 0); --! type for ram content
    shared variable myram : myram_type; --! ram
begin
    process (clk_a)
    begin
        if rising_edge(clk_a) then
            if we_a = '1' then
                myram(conv_integer(addr_a)) := di_a;
            end if;
            do_a <= myram(conv_integer(addr_a));
        end if;
    end process;
end bar;

Por ejemplo, quiero una RAM con DATAWIDTH = 8 y DATADEPTH = 5000 , por lo que la dirección debe ser ADDRWIDTH = 13 porque ADDRWIDTH = 12 solo permitiría abordar 4096 ubicaciones RAM. Asumamos que un recurso RAM de bloque en mi FPGA puede contener 8192 bits. Si codifiqué esto a mano, requerí 5000 * 8/8192 redondeados hacia arriba = 5 recursos de RAM de bloque. Sin embargo, con el código anterior, la síntesis y el mapa de Xilinx dan como resultado el uso de 8 recursos de RAM de bloque, porque eso es lo que puede ser abordado por direcciones de 13 bits de ancho ...
Sin embargo, este no es realmente un uso eficiente de los recursos, ya que 3 de las 8 memorias RAM de bloque nunca se utilizarán.
Intenté verificar si la dirección en la entrada es mayor que DATADEPTH y luego asignar no cuida los datos, pero eso hace que todo el ram se implemente como RAM / LUTRAM distribuido. ¿Me estoy perdiendo algo importante o tengo que usar un generador grande y feo para esto?

    
pregunta damage

3 respuestas

3

En realidad, usar 8 BRAM en una configuración de 8K × 1, en lugar de 5 BRAM en una configuración de 1K × 8, es más eficiente en varias formas importantes.

Con los 8 BRAM, simplemente puede conectar todas las direcciones y las líneas de control a todos los BRAM y un bit de los buses de entrada y salida de datos a cada uno de los BRAM. No se requiere ninguna otra lógica en absoluto.

Por otro lado, con la configuración 5-BRAM, necesitará lógica adicional para decodificar los 3 bits de dirección superiores para habilitar un BRAM a la vez, y también necesitará un multiplexor de 5: 1 en los datos Bus de salida para seleccionar los datos de BRAM correcta al leer. Esto utiliza recursos adicionales dentro del FPGA, y también afecta negativamente a la sincronización, reduciendo la frecuencia de reloj máxima que puede utilizar.

Si realmente necesita utilizar la capacidad de BRAM de la manera más eficiente posible, y no le importa el tiempo ni los problemas de recursos, tendrá que codificar explícitamente su memoria como un módulo. que utiliza cinco memorias 1K × 8 internamente.

    
respondido por el Dave Tweed
2

Inferir módulos duros (como bloques de bloque) del código es una proposición bastante frágil, por lo que los sintetizadores generalmente proporcionan pautas de codificación, de las cuales supongo que usaste las "Pautas de codificación del lenguaje de descripción de hardware (HDL) de Xilinx".

Al leer esas pautas y darse cuenta de que ciertos estilos de codificación que parecerían perfectamente válidos (como el uso de señales en lugar de variables compartidas para un ram de doble puerto) en realidad no funcionarán, tendrá una idea de cuán limitadas son las técnicas de inferencia. / p>

Por lo tanto, creo que o bien existe tal limitación con Xilinx, o la herramienta está eligiendo no minimizar el uso de BRAM en favor de otras optimizaciones (como se menciona en la respuesta de Dave Tweed).

Parece que, lamentablemente, estás limitado a:

  • Explícitamente en cascada los BRAM necesarios.
  • Las memorias múltiples en cascada están codificadas de manera 'guiatoria' simplista.
  • Usando el generador CORE.
  • Dejar que los BRAM adicionales se desperdicien y seguir adelante, quizás cuando las condiciones sean las adecuadas, la herramienta hará lo que esperaba y usará 5 BRAM.
respondido por el apalopohapa
0

Si necesita usar 13 bits de dirección para su RAM, entonces esas 13 señales físicas de dirección para un BRAM deben asignarse a su RAM. Las líneas de dirección no se pueden compartir fácilmente con algún otro módulo, por lo que obtiene efectivamente toda la RAM física a la que acceden esas 13 líneas de dirección. Si necesitas 5000 palabras, obtendrás 8192 palabras de BRAM. Como notó, si sintetiza la RAM a partir de LUTs, puede hacer una RAM con solo 5000 palabras pero pierde la eficiencia de la BRAM.

    
respondido por el Joe Hass

Lea otras preguntas en las etiquetas