This may have something to do with the fact that you have an asynchronous reset.
Quartus will try to recognise when your code can be most efficiently compiled using some of the hard RAM blocks that exist in the FPGA silicon. If the behaviour of your code matches that of the hard RAM block, then the RAM block can be used, which saves a load of general purpose logic cells.
Your RAM array is a prime candidate for implementation this way, of course.
However: your output DAT_O doesn't quite match the capabilities of the hard RAM blocks, which are fully synchronous - ie. every input and every output is clocked. DAT_O is forced low whenever RST_I is high, independently of your clock, which might explain the error "uninferred due to asynchronous read logic".
If WE_I is never driven high, then Quartus can optimise out the RAM entirely; it becomes a small ROM instead, which in turn might be getting implemented in logic cells rather than using a hard RAM block. The warnings go away because Quartus chose not to use a RAM block at all.
You might be having an issue with combinatorial loops because you're trying to force DAT_O to be something other than the RAM contents when the reset signal is asserted. That means that DAT_O cannot be the same as the usual signal output from a RAM block, because the multiplexer you'd need doesn't exist.
Try using a synchronous reset and see if that helps:
entity RAM is
generic(
ADDR_WIDTH : integer := 8;
DATA_WIDTH : integer := 16
);
port(
CLK_I, RST_I, WE_I, STB_I : in std_logic;
ADR_I : in std_logic_vector(7 downto 0); -- Address in
DAT_I : in std_logic_vector(15 downto 0); -- Data in
SEL_I : in std_logic_vector(7 downto 0); -- Wishbone fluff
ACK_O : out std_logic; -- ACK for wishbone
DAT_O : out std_logic_vector(15 downto 0) -- Data out
);
end entity RAM;
architecture RTL of RAM is
subtype WORD is std_logic_vector(15 downto 0);
type MEMORY is array(0 to 2**ADDR_WIDTH-1) of WORD;
signal RAM256:MEMORY := (
"0100000000001011", -- 0: LOAD 11 (Bit 15-13 determines the instruction)
"0010000000001100", -- 1: ADD 12
"0110000000001101", -- 2: STO 13
-- ... Cut out to save space ... --
"0000000000000001", -- 11: 1
"0000000000000010", -- 12: 2
others => "0000000000000000");
begin
process(CLK_I, RST_I, ADR_I, STB_I)
variable RAM_ADDR_IN : integer range 0 to 2**ADDR_WIDTH-1;
begin
if rising_edge(CLK_I) then
if (RST_I = '1') then
DAT_O <= (others => '0');
ACK_O <= '0';
else
RAM_ADDR_IN := conv_integer(ADR_I); -- Convert the adress vector to int
ACK_O <= '0';
if STB_I = '1' then
if (WE_I = '1') then
RAM256(RAM_ADDR_IN) <= DAT_I; -- Write what's on the DAT_I to memory at RAM_ADDR_IN
else
DAT_O <= RAM256(RAM_ADDR_IN); -- Read what's in the memory and put it on DAT_O
end if;
ACK_O <= '1';
end if;
end if;
end process;
end rtl;