Forum Discussion

mschiller-nrao's avatar
mschiller-nrao
Icon for New Contributor rankNew Contributor
2 months ago

Proper way to infer Quad Port Ram?

I generated the Quad Port Template in Quartus 2025.3.  I then wrapped it into a wrapper and finally into my design.

This is then instantiated with the following generics:

Info(19337): VHDL info at quad_port_ram.vhd(10): executing entity "quad_port_ram(data_width=578,addr_width=7)" with architecture "rtl" 
Info(19337): VHDL info at quad_port_ram.vhd(10): executing entity "quad_port_ram(data_width=578,addr_width=8)" with architecture "rtl" 
Info(19337): VHDL info at quad_port_ram.vhd(10): executing entity "quad_port_ram(data_width=578,addr_width=9)" with architecture "rtl" 
Info(19337): VHDL info at quad_port_ram.vhd(10): executing entity "quad_port_ram(data_width=578,addr_width=10)" with architecture "rtl" 

However I get the following errors: 
Warning(276002): Cannot convert all sets of registers into RAM megafunctions when creating nodes; therefore, the resulting number of registers remaining in design can cause longer compilation time or result in insufficient memory to complete Analysis and Synthesis 

Info(276012): RAM logic "stage_gen[13].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[12].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276014): Found 9 instances of uninferred RAM logic 
Info(276012): RAM logic "stage_gen[13].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[12].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[11].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[10].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[9].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[8].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[7].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[6].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 
Info(276012): RAM logic "stage_gen[5].pipe_fft_stage|math_fft_quad_port_ram_1_0_inst|quad_port_ram_inst|ram" is uninferred due to too many ports 

 

 

 

Is there something that can be done to properly infer quad-port ram in 25.3?

Here's the VHDL generated from the template:

-- Quartus Prime VHDL Template

-- Quad Port RAM with separate read/write addresses and

-- single read/write clock

-- This style of RAM cannot be used on Arria 10,

-- which does not support Quad Port RAM

 

library ieee;

use ieee.std_logic_1164.all;

 

entity quad_port_ram is

 

generic

(

DATA_WIDTH : natural := 2;

ADDR_WIDTH : natural := 6

);

 

port

(

clk : in std_logic;

read_addr_a : in natural range 0 to 2**ADDR_WIDTH - 1;

read_addr_b : in natural range 0 to 2**ADDR_WIDTH - 1;

write_addr_a : in natural range 0 to 2**ADDR_WIDTH - 1;

write_addr_b : in natural range 0 to 2**ADDR_WIDTH - 1;

data_a : in std_logic_vector((DATA_WIDTH-1) downto 0);

data_b : in std_logic_vector((DATA_WIDTH-1) downto 0);

we_a : in std_logic := '1';

we_b : in std_logic := '1';

q_a : out std_logic_vector((DATA_WIDTH -1) downto 0);

q_b : out std_logic_vector((DATA_WIDTH -1) downto 0)

);

 

end quad_port_ram;

 

architecture rtl of quad_port_ram is

 

-- Build a 2-D array type for the RAM

subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);

type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;

 

-- Declare the RAM

shared variable ram : memory_t;

 

begin

 

-- Port A

process(clk)

begin

if(rising_edge(clk)) then

if(we_a = '1') then

ram(write_addr_a) := data_a;

end if;

end if;

end process;

 

process(clk)

begin

if(rising_edge(clk)) then

q_a <= ram(read_addr_a);

end if;

end process;

 

-- Port B

process(clk)

begin

if(rising_edge(clk)) then

if(we_b = '1') then

ram(write_addr_b) := data_b;

end if;

end if;

end process;

 

process(clk)

begin

if(rising_edge(clk)) then

q_b <= ram(read_addr_b);

end if;

end process;

 

end rtl;

5 Replies

  • As another point of information.  I tried synthesizing the inferred quad_port_ram outside my design.   For reasonable size blocks eg 2048 deep x 32 wide the file inferred properly.  But I appear to start having problems as the block gets wider.  So I'm assuming this is some kind of synthesis bug where the wide ram (like 500x2048!) triggers the bug.  But it does work with the altera_syncram (basically the IP) solution....

    • RichardT_altera's avatar
      RichardT_altera
      Icon for Super Contributor rankSuper Contributor

      What is the problem you are facing? Which parameter setting caused the issue? Please provide more details.
      Additionally, what specific memory configuration setting do you plan to use?

  • Sorry I didn't make that clear  This is an AgileX I-series part.

    For now I've gotten it to work with effectively an IP core.. I generated the IP core, and then reverse engineered what it was calling to use the primitive/megafunction directly.  (eg altera_syncram).  But I hate that solution because for quad port it seems that only the altera_mf_ver (verilog) library even has the altera_syncram model [and for some reason the sim library calls it altera_syncram_derived instead of altera_syncram?!?!]  

    I'm a VHDL shop, so any verilog in my code base pisses me off because I can't use opensource simulators. [I do have a single seat of rivierapro... which I'm using to simulate this solution]




  • The template provided in Quartus is the correct way to infer the Quad-Port RAM.
    However, as sstrell mentioned, it depends on the device you are using. Quad-Port RAM is supported in Agilex and Stratix 10 devices.
    You can verify this by navigating to:

    IP CatalogRAM: 4-PORT FPGA IPRight-clickDetailsSupported Device Families

    Regards,
    Richard Tan