1
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ Is this more of a software issue or a hardware issue? \$\endgroup\$ – Sparky256 Jul 26 '16 at 17:47
  • \$\begingroup\$ 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 \$\endgroup\$ – Fluffy Jul 26 '16 at 17:49
  • \$\begingroup\$ 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. \$\endgroup\$ – asdfex Jul 26 '16 at 18:10
  • \$\begingroup\$ 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. \$\endgroup\$ – TEMLIB Jul 26 '16 at 18:31
  • \$\begingroup\$ 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. \$\endgroup\$ – Paebbels Jul 27 '16 at 7:05
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – user2943160 Oct 25 '16 at 3:17
0
\$\begingroup\$

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

\$\endgroup\$

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.