Re: dual port inference problem
On Jun 29, 3:35*pm, gabor <ga...@alacron.com> wrote:
> On Jun 29, 2:35*pm, Benjamin Couillard <benjamin.couill...@gmail.com>
> wrote:
>
>
>
>
>
> > Hi,
>
> > I have a problem with dual-port ram inference. I have a module called
> > "dual_port_ram.vhd" that I use to infer a dual port ram. This file is
> > based on Xilinx template and it works well almost everytime.
>
> > My problem is the following, I have a module called "widget.vhd" that
> > instantiates a 1024x20 bit dual-port ram. When I synthesize
> > widget.vhd, I see that ISE correctly inferred the *dual-port ram with
> > 2 block rams.
>
> > I have another VHDL module called "gadgets.vhd" that instantiates 4
> > "widget.vhd" components. We should expect ISE to synthesize
> > "gagdets.vhd" with 8 block rams.
>
> > However, when I synthesize "gadgets.vhd", ISE infers the 4 1024x20 bit
> > dual-port ram in distributed logic instead of using 8 block rams. I
> > have enough block rams in my device for the instantiation so it's not
> > some kind of fallback plan by ISE synthesis. What's even weirder is
> > that when I add the "keep_hierarchy" attribute in "widget.vhd", ISE
> > will synthesize "gagdets.vhd" with 8 block rams instead of
> > synthesizing it with 4 1024x20bit distributed logic ram.
>
> > Does anyone here have some kind of explanation?
>
> > I use ISE 11.1 with resource sharing disabled.
>
> > Best regards
>
> > Benjamin
>
> You didn't post the template, but I've seen some that don't
> really match the RAM architecture. *Instead of placing a
> register on the read output data, it places the register
> on the read address. *Then it fails to map to block RAM,
> but only if it shares the registered read address between
> RAM blocks. *I would expect the Xilinx templates to work
> correctly, but in case you are not using the latest one,
> this is something to check.
>
> Regards,
> Gabor
Here's my "dual_port_ram.vhd"
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dual_port_ram is
generic (width : integer := 16;
addr_width : integer := 7);
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;
addra : in std_logic_vector(addr_width-1 downto 0);
addrb : in std_logic_vector(addr_width-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 dual_port_ram;
architecture syn of dual_port_ram is
type ram_type is array (2**addr_width-1 downto 0) of std_logic_vector
(width-1 downto 0);
shared variable RAM : ram_type := (others => (others => '0')); --
begin
process (CLKA)
begin
if (rising_edge(CLKA)) then
if ENA = '1' then
DOA <= RAM(to_integer(unsigned(ADDRA)));
if WEA = '1' then
RAM(to_integer(unsigned(ADDRA))) := DIA;
end if;
end if;
end if;
end process;
process (CLKB)
begin
if (rising_edge(CLKB)) then
if ENB = '1' then
DOB <= RAM(to_integer(unsigned(ADDRB)));
if WEB = '1' then
RAM(to_integer(unsigned(ADDRB))) := DIB;
end if;
end if;
end if;
end process;
end syn;
|