Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

infer true dual port asynchronous ram

hallo everyone,

i need a true dual port asynchronous ram for my selfmade soft-core project. to be hardware independent i try to infer the ram-block from vhdl-code.

this is my code:

--
-- Dual-Port Block RAM with Two Write Ports
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity TDPR is
    generic(    width    :    natural := 16;
                depth :    natural := 6);
            
    port    (    clka  :     in     std_logic;
                clkb  :     in     std_logic;
                ena   :  in     std_logic;
                enb   :  in     std_logic;
                wea   :  in     std_logic;
                web   :  in     std_logic;
                rsta  :  in     std_logic;
                rstb  :  in     std_logic;
                addra :  in     std_logic_vector(depth-1 downto 0);
                addrb :  in     std_logic_vector(depth-1 downto 0);
                dia   :  in     std_logic_vector(width-1 downto 0);
                dib   :  in     std_logic_vector(width-1 downto 0);
                doa   :  out     std_logic_vector(width-1 downto 0);
                dob   :  out     std_logic_vector(width-1 downto 0));
end TDPR;
architecture syn of TDPR is
    type ram_type is array ((2**depth)-1 downto 0) of std_logic_vector(width-1 downto 0);
    shared variable RAM : ram_type;
begin
    process(CLKA)
    begin
        if CLKA'event and CLKA = '1' then
            if ENA = '1' then
                if WEA = '1' then
                    RAM(conv_integer(ADDRA)) := DIA;
                end if;
                 if  rsta  =  '1'  then                             --  optional  reset
                         doa  <=  (others  =>  '0');
                     else
                         doa  <=  ram(conv_integer(addra))  ;
                     end  if;
            end if;
        end if;
    end process;
     
    process (CLKB)
    begin
        if CLKB'event and CLKB = '1' then
            if ENB = '1' then
                if WEB = '1' then
                    RAM(conv_integer(ADDRB)) := DIB;
                end if;
                if  rstb  =  '1'  then                             --  optional  reset
                         dob  <=  (others  =>  '0');
                     else
                         dob  <=  ram(conv_integer(addrb))  ;
                     end  if;
        end if;
    end if;
    end process;
end syn;
xilinx ise infers the correct block structure. but quartus gives an error message:

Info: Found 1 instances of uninferred RAM logic

Info: RAM logic "TDPR:inst|RAM" is uninferred due to asynchronous read logic

Error: Cannot synthesize dual-port RAM logic "TDPR:inst|RAM"

is there any possibility to use an true dual port asynchronous ram in vhdl code.

(i'm using quartus 9.0sp2)

with best regards erik_dl

9 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You should consider the hardware differences to understand the different behaviour.

    Xilinx actually has asynchronous (unregistered) RAM with all FPGA series as far as I'm aware of, Altera hasn't. Furthermore, inference of asynchronous RAM seems not to work even with those Altera Stratix devices, that have the option in hardware.

    You can review the Quartus VHDL templates to see which RAM constructs are supported for inference.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks for your fast answer.

    the quartus megafunctions supports asynchronous dual port ram. and the synthesis seems to be correct (although i have not tested it on my cyclone II board), so i thought that should be possible in vhdl too.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Asynchronous RAM is not available for Cyclone series, see the hardware handbook for details, but Stratix III and Stratix IV have it. Inference from HDL code seems not to work for those devices, though.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    hallo everyone,

    i need a true dual port asynchronous ram for my selfmade soft-core project. to be hardware independent i try to infer the ram-block from vhdl-code.

    this is my code:

    --
    -- Dual-Port Block RAM with Two Write Ports
    --
    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.std_logic_unsigned.all;
    entity TDPR is
        generic(    width    :    natural := 16;
                    depth :    natural := 6);
                
        port    (    clka  :     in     std_logic;
                    clkb  :     in     std_logic;
                    ena   :  in     std_logic;
                    enb   :  in     std_logic;
                    wea   :  in     std_logic;
                    web   :  in     std_logic;
                    rsta  :  in     std_logic;
                    rstb  :  in     std_logic;
                    addra :  in     std_logic_vector(depth-1 downto 0);
                    addrb :  in     std_logic_vector(depth-1 downto 0);
                    dia   :  in     std_logic_vector(width-1 downto 0);
                    dib   :  in     std_logic_vector(width-1 downto 0);
                    doa   :  out     std_logic_vector(width-1 downto 0);
                    dob   :  out     std_logic_vector(width-1 downto 0));
    end TDPR;
    architecture syn of TDPR is
        type ram_type is array ((2**depth)-1 downto 0) of std_logic_vector(width-1 downto 0);
        shared variable RAM : ram_type;
    begin
        process(CLKA)
        begin
            if CLKA'event and CLKA = '1' then
                if ENA = '1' then
                    if WEA = '1' then
                        RAM(conv_integer(ADDRA)) := DIA;
                    end if;
                     if  rsta  =  '1'  then                             --  optional  reset
                             doa  <=  (others  =>  '0');
                         else
                             doa  <=  ram(conv_integer(addra))  ;
                         end  if;
                end if;
            end if;
        end process;
         
        process (CLKB)
        begin
            if CLKB'event and CLKB = '1' then
                if ENB = '1' then
                    if WEB = '1' then
                        RAM(conv_integer(ADDRB)) := DIB;
                    end if;
                    if  rstb  =  '1'  then                             --  optional  reset
                             dob  <=  (others  =>  '0');
                         else
                             dob  <=  ram(conv_integer(addrb))  ;
                         end  if;
            end if;
        end if;
        end process;
    end syn;
    xilinx ise infers the correct block structure. but quartus gives an error message:

    Info: Found 1 instances of uninferred RAM logic

    Info: RAM logic "TDPR:inst|RAM" is uninferred due to asynchronous read logic

    Error: Cannot synthesize dual-port RAM logic "TDPR:inst|RAM"

    is there any possibility to use an true dual port asynchronous ram in vhdl code.

    (i'm using quartus 9.0sp2)

    with best regards erik_dl

    --- Quote End ---

    Hi,

    your reset and enable functions could not implemented with Altera Rams. This causes that the RAM is not inferred. The info is a little bit misleading. That means that Quartus could not use the internal RAM for implementation. The only way now for Quartus to implement a RAM are register, which don't have a dual input. That's why you get the error message.

    If you remove the reset and enable the RAM should be inferred, but that is not what you want ???

    Kind regards

    GPK
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I seem to recall a discussion on comp.lang.VHDL a while ago about this very issue.

    IIRC, the conclusion was that Xilinx devices changed read-during-write behaviour when you swapped RAM between a signal and a shared variable. For Altera, when it did compile (I cant remember whether reset and enable inputs were included) there was no difference between the shared variable and signal versions. This meant that to modify the behaviour you had to use the altsyncram megafunction.

    I think I found the discussion:

    http://groups.google.com/group/comp.lang.vhdl/browse_frm/thread/b4b6147c98e6af5a/81d7b4efdc6ce246?lnk=gst&q=dual+port+ram#81d7b4efdc6ce246
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    ok...its not the best way...but now i am using the megafunctions in my vhdl description.

    but at synthesis appeared an other problem.

    configuration of my altsyncram:

    - two read/write ports (true dual-port mode)

    - 256 words (word = 16 bits) -> 256x16

    - dual clock: use seperate clocks for A and B ports

    - create one clock enable signal for each clock signal

    so the total used memory bits should be 256*16 = 4096 bits

    but the synthesis uses 8192 bits (2 M4Ks).

    is this the correct behaviour? i have not find any application note to this topic.

    i am using a cyclone II device

    edit:

    i have tested the megafunction with Input/Output and Single Clock mode. in both cases the synthesis uses 1 M4K cell.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think, it's a Cyclone II problem. Quartus has special code to handle a silicon bug with internal RAM of some Cyclone II devices, resulting in doubled resource usage with true dual port RAM, If your devices aren't affected by the problem, you can disable this setting. Details can be found in the Cyclone II erata sheets.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks to all, that helps a lot to understand the compilation result.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    ah, that's right, you should have gotten a warning that tells you to read the errata.