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?
-
\$\begingroup\$ Is this more of a software issue or a hardware issue? \$\endgroup\$user105652– user1056522016年07月26日 17:47:47 +00:00Commented Jul 26, 2016 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– Fluffy2016年07月26日 17:49:41 +00:00Commented Jul 26, 2016 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– asdfex2016年07月26日 18:10:45 +00:00Commented Jul 26, 2016 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\$Grabul– Grabul2016年07月26日 18:31:10 +00:00Commented Jul 26, 2016 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– Paebbels2016年07月27日 07:05:06 +00:00Commented Jul 27, 2016 at 7:05
2 Answers 2
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.
-
\$\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– user29431602016年10月25日 03:17:39 +00:00Commented Oct 25, 2016 at 3:17
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