1
\$\begingroup\$

I have a Spartan3E 250K FPGA. I have a dual-mismatched-port block RAM implemented. According to my calculations, making a 8Kbyte RAM should be possible. However, ISE will change my block RAM to a (overmapped) distributed RAM when I try to go over 2Kbytes of RAM. With 2Kbytes though, it says I'm only using 1 of 12 block RAMs

Do I really need to create multiple block RAMs and string them together to get a full 8Kbyte block RAM component?

The code is nearly a straight rip from ISE's template library:

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_arith.all; use IEEE.NUMERIC_STD.ALL; use ieee.std_logic_unsigned.all; entity blockram is generic ( --Port A is for general use. Port B is for fetching WIDTHA : integer := 16; SIZEA : integer := 2048; ADDRWIDTHA : integer := 11; WIDTHB : integer := 32; SIZEB : integer := 1024; ADDRWIDTHB : integer := 10 ); port( Clock : in std_logic; EnableA : in std_logic; EnableB : in std_logic; WriteEnableA : in std_logic; WriteEnableB : in std_logic; AddressA : in std_logic_vector(ADDRWIDTHA-1 downto 0); AddressB : in std_logic_vector(ADDRWIDTHB-1 downto 0); DataInA : in std_logic_vector(WIDTHA-1 downto 0); DataInB : in std_logic_vector(WIDTHB-1 downto 0); DataOutA : out std_logic_vector(WIDTHA-1 downto 0); DataOutB : out std_logic_vector(WIDTHB-1 downto 0) ); end blockram; architecture Behavioral of blockram is function max(L, R: INTEGER) return INTEGER is begin if L > R then return L; else return R; end if; end; function min(L, R: INTEGER) return INTEGER is begin if L < R then return L; else return R; end if; end; function log2 (val: INTEGER) return natural is variable res : natural; begin for i in 0 to 31 loop if (val <= (2**i)) then res := i; exit; end if; end loop; return res; end function log2; constant minWIDTH : integer := min(WIDTHA,WIDTHB); constant maxWIDTH : integer := max(WIDTHA,WIDTHB); constant maxSIZE : integer := max(SIZEA,SIZEB); constant RATIO : integer := maxWIDTH / minWIDTH; -- An asymmetric RAM is modelled in a similar way as a symmetric RAM, with an -- array of array object. Its aspect ratio corresponds to the port with the -- lower data width (larger depth) type ramType is array (0 to maxSIZE-1) of std_logic_vector(minWIDTH-1 downto 0); -- You need to declare <ram> as a shared variable when : -- - the RAM has two write ports, -- - the RAM has only one write port whose data width is maxWIDTH -- In all other cases, <ram> can be a signal. --shared variable ram : ramType := (others => (others => '0')); signal ram: ramType; signal readA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0'); signal readB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); signal regA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0'); signal regB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); begin process (Clock) begin if rising_edge(Clock) then if EnableA = '1' then readA <= ram(conv_integer(AddressA)); if WriteEnableA = '1' then ram(conv_integer(AddressA)) <= DataInA; end if; end if; regA <= readA; end if; end process; process (Clock) begin if rising_edge(Clock) then if EnableB = '1' then for i in 0 to RATIO-1 loop -- The read statement below is placed before the write statement on purpose -- to ensure read-first synchronization through the variable mechanism readB((i+1)*minWIDTH-1 downto i*minWIDTH) <= ram(conv_integer(AddressB & conv_std_logic_vector(i,log2(RATIO)))); end loop; end if; regB <= readB; end if; end process; DataOutA <= regA; DataOutB <= regB; end behavioral; 
\$\endgroup\$
2
  • \$\begingroup\$ Do you have your dual-port RAM isolated to its own module, and could you share that module with us? There may be some detail about your definition that's preventing ISE from using the blockram at the larger sizes. \$\endgroup\$ Commented Sep 8, 2012 at 3:41
  • \$\begingroup\$ @DaveTweed I added the code. It's nearly a straight rip from ISE's code template for asymmetric dual port RAM \$\endgroup\$ Commented Sep 8, 2012 at 4:57

1 Answer 1

1
\$\begingroup\$

Inferring dual-port with different data widths is a bit of a pain - I gave up (using the template code was a non-starter as it had clearly never been tested with generics other than the defaults)

Hold your nose and use Coregen :(

\$\endgroup\$
3
  • \$\begingroup\$ I'll just break it up instead(ie, use multiple blockram components). I strongly prefer simulation with ghdl. Also, I noticed that without using the hidden use-new-parser option, XST won't synthesize a block RAM ever for me on a Spartan 3E \$\endgroup\$ Commented Sep 10, 2012 at 13:10
  • \$\begingroup\$ Does GHDL not work with Xilinx's libraries? \$\endgroup\$ Commented Sep 10, 2012 at 14:34
  • \$\begingroup\$ Xilinx libraries can be used in ghdl. \$\endgroup\$ Commented May 12, 2014 at 8:13

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.