Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21587 Discussions

infer true dual port asynchronous ram

Altera_Forum
Honored Contributor II
3,835 Views

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
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
2,221 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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

0 Kudos
Altera_Forum
Honored Contributor II
2,221 Views

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

0 Kudos
Reply