1
\$\begingroup\$

My question is very simple i think, but i would be really gratefull if anyone can help me with this.

When i want to write in the fpga memory using the classic following line code:

             type RAM_ARRAY is array (0 to 127 ) of std_logic_vector (7 downto 0);

Does that code, creates a new memory using the fpga resources or it writes directly in the fpga built in memory?

And if the answer is the first one, how can i write directly in the built in memory of the fpga so that way i dont use more resources.

Im using as reference this code: https://www.edaplayground.com/x/3Zs

This is my code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

entity RAM_SP is
generic(
        constant memory_depth : integer := 256; -- numero de palabras de la memoria
        constant memory_lenght : integer := 8   -- numero de bits por palabra
     );
     
Port (  
     data_in : in std_logic_vector(memory_lenght - 1 downto 0); -- datos de entrada
     address : in std_logic_vector(memory_lenght - 1 downto 0); -- direccion de memoria
     W_R : in std_logic;  --Escribe con '0' y Lee con '1'
     data_out : out std_logic_vector(memory_lenght - 1 downto 0)-- datos de salida
    );
end RAM_SP;

architecture Behavioral of RAM_SP is
type mem is array (memory_depth - 1 downto 0) of std_logic_vector(7 downto 0); --Una memoria de 256 palabras de 8 bits
signal memory : mem; --Asocio la memoria creada a la señal/palabra/constante memory
signal addr : integer range 0 to memory_depth - 1; --Creo una señal que puede tomar valores enteros de 0 a 255
begin

process(address, data_in, W_R)
begin
    addr <= conv_integer(address);
    if(W_R = '0')then
        memory(addr)<=data_in;
    elsif(W_R = '1')then
        data_out<=memory(addr);
    else
        data_out<="ZZZZZZZZ";
    end if;
end process;
end Behavioral;
\$\endgroup\$
  • 2
    \$\begingroup\$ It really depends on how you access the array once you create it. Most of the tools are capable of inferring ram if your access pattern supports it, but if you try to read/write several locations each clock cycle it would have to be implemented as a bunch of FFs and LUTs \$\endgroup\$ – ks0ze Oct 6 at 1:56
  • \$\begingroup\$ What changes would you suggest me if i want to write to the ram block and not the resources, in the synthesis i saw that im using the fpga resources, can you help me? \$\endgroup\$ – esencia Oct 6 at 16:58
1
\$\begingroup\$

Both implementations are possible. The choice of the implementation depends on the optimization of the design software. However you can control the way it is implemented by using directives.

First, in the following example in Quartus II the software design has chosen to use memory:

library IEEE;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_1164.ALL;


entity question524852 is
    Port (  Din:in std_logic_vector(7 downto 0);
              ADin:in std_logic_vector(7 downto 0);
                clk :in std_logic;
                we :in std_logic;
                incall:in std_logic_vector(0 to 129);
                s: out std_logic_vector(7 downto 0) );
end question524852;

architecture Behavioral of question524852 is
    type RAM_ARRAY is array (0 to 129 ) of std_logic_vector (7 downto 0);
    signal myTable:RAM_ARRAY;
    signal outs : std_logic_vector(7 downto 0);
begin
    process(clk)
    begin
            if (clk'event and clk='1') then 
                if (we='1') then
                    if (incall(to_integer(unsigned(ADin)))='1') then
                        myTable( to_integer(unsigned(ADin)))<="10101010";
                    else
                        myTable( to_integer(unsigned(ADin)))<=Din;
                    end if;
                end if;
                outs <= myTable( to_integer(unsigned(ADin))); 
            end if;
    end process;
        
    s <= outs;
end Behavioral;

What we get is the following:

enter image description here

Using memory directives we can force the design software to use either logic elements or any type of memory.

To use logic elements add the following:

type RAM_ARRAY is array (0 to 129 ) of std_logic_vector (7 downto 0);
signal myTable:RAM_ARRAY;
attribute ramstyle : string;
attribute ramstyle of myTable : signal is "logic";

so we get:

enter image description here

To force M9K memory blocks for example:

type RAM_ARRAY is array (0 to 129 ) of std_logic_vector (7 downto 0);
signal myTable:RAM_ARRAY;
attribute ramstyle : string;
attribute ramstyle of myTable : signal is "M9K";

and we get again:

enter image description here

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ thanks for the explanation, one question, in my code that im using, im using the fpga resources, but i dont know why if im suing the same logic as the first example that you gave me, can you help me? \$\endgroup\$ – esencia Oct 6 at 16:53
  • \$\begingroup\$ The implementation is defined for synthesis and I can see that your code is not synthesizable since you are using wait (in the playground) which is only used for simulation. The directives that I show in my example are for Intel (Altera) Quartus and usually it depends on the design suite. \$\endgroup\$ – Paul Ghobril Oct 6 at 17:24
  • \$\begingroup\$ i updated my code, i dont use the wait statement, only in the testbench \$\endgroup\$ – esencia Oct 6 at 17:32
  • \$\begingroup\$ thank you so much, now i am using the internal ram, i only put the clk as the sensitivity list and that solve it. \$\endgroup\$ – esencia Oct 6 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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