1

I'm trying to infer the usage of a RAM block of my FPGA, but I fail to understand what are the hints needed. I use Synplify Pro as my synthesis tool. If I'm not mistaken, this is a dual port synchronous RAM that I need to infer.

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

entity fifo is
  generic(
    constant DATA_WIDTH : integer;
    constant FIFO_DEPTH : integer
  );
  port(
    clk       : in std_logic;
    mmc_clk   : in std_logic; 
    reset     : in std_logic;
    spi_done  : in std_logic;
    rx_data   : in std_logic_vector(7 downto 0);

    write_en  : in std_logic;
    read_en   : in std_logic;

    data_out  : out std_logic_vector(7 downto 0);
    data_in   : in std_logic_vector(7 downto 0);
    empty_o   : out std_logic;
    full_o    : out std_logic;

    level_o   : out std_logic_vector(7 downto 0)
  );
end fifo;

architecture arch of fifo is

signal mmc_clk_prev, mmc_clk_i : std_logic;

begin

-- Memory Pointer Process
fifo_proc : process (CLK)
    type FIFO_memory is array (0 to FIFO_DEPTH-1) of std_logic_vector(DATA_WIDTH - 1 downto 0);
    variable memory : FIFO_memory;

    variable head : integer range 0 to FIFO_DEPTH - 1;
    variable tail : integer range 0 to FIFO_DEPTH - 1;

    variable looped : boolean;
    begin
    if reset = '1' then
        head := 0;
        tail := 0;
        looped := false;
        full_o  <= '0';
        empty_o <= '1';
    elsif rising_edge(CLK) then
        if (read_en = '1') then
            if ((looped = true) or (head /= tail)) then
                -- Update data output
                data_out <= memory(tail);
                -- Update tail pointer as needed
                if (tail = FIFO_DEPTH - 1) then
                    tail := 0;
                    looped := false;
                else
                    tail := tail + 1;
                end if;
            end if;
        end if;

        if (write_en = '1') then
            if ((looped = false) or (head /= tail)) then
                -- Write Data to memory
                memory(head) := data_in;
                -- Increment head pointer as needed
                if (head = FIFO_DEPTH - 1) then
                    head := 0;
                    looped := true;
                else
                    head := head + 1;
                end if;
            end if;
        end if;

        -- Update empty_o and full_o flags
        if (head = tail) then
            if looped then
                full_o <= '1';
            else
                empty_o <= '1';
            end if;
        else
            empty_o   <= '0';
            full_o    <= '0';
        end if;
    end if;

    if head-tail >= 0 then
        level_o <= std_logic_vector(to_unsigned(head-tail,level_o'length));
    end if;
end process;

end arch;

What am I missing?

Fluffy
  • 298
  • 4
  • 16
  • Is this more of a software issue or a hardware issue? –  Jul 26 '16 at 17:47
  • What do you mean? My FIFO can store up to 128 bytes, I want to be able to store them into one of the RAM block of my FPGA to reduce LUTs usage – Fluffy Jul 26 '16 at 17:49
  • Try using signals instead of variables and try to simplify the process a bit (e.g. all the tail/head stuff can go to a separate process). Software is always a bit picky to recognize such constructs in complicated processes. – asdfex Jul 26 '16 at 18:10
  • As @asdfex wrote : Try putting the RAM in a separate, simple process. There may be also some synthesis options, 128 bytes may be considered too small as default for a block RAM, check the synthesis report. – TEMLIB Jul 26 '16 at 18:31
  • What is the target architecture? Altera, Lattice, Xilinx, ...? I suspect your target BlockRAM has no read enable (you described one), which is not needed for a FIFO memory. – Paebbels Jul 27 '16 at 07:05
  • It's a Lattice board, the documentation does mention a read enable port on RAM blocks. I'll try to put the RAM in a simple process, thanks for your help – Fluffy Jul 27 '16 at 08:19

2 Answers2

1

I would recommend making a separate dual port ram similar to the one here and using it as a building block for your FIFO. I understand that will make your design a little more cumbersome, however the synthesis tool will actually be able to infer a dual port ram.

Lincoln
  • 430
  • 3
  • 11
  • Yes. Separating the pointer logic and the dual-port RAM logic will greatly improve the ability for the synthesizer to infer hardware blocks. A vendor may even (often does) provide IP that generates the assuredly-correct mapping onto memory blocks. – user2943160 Oct 25 '16 at 03:17
0

Have you tried the syn_ramstyle attribute.

Refer to http://www.ece.ucdavis.edu/~soheil/teaching/EEC180B-S06/inferring_blockRAMs.pdf

So, in your case, the code would look something like this:

attribute syn_ramstyle : string;
attribute syn_ramstyle of memory : signal is "block_ram";

HTH

dst
  • 81
  • 5