comc cmoc
comc cmoc

Reputation: 47

Creating large dual-port RAM in VHDL

I am trying to generate a RAM to store an editable bitmap for a rudimentary paint program in VHDL. To do this, one set of I/O takes the address of the current pixel and outputs the stored pixel color. The other set takes the address of the pixel to be written and the color for its data input. Because of the size of the display, this needs to be a 1Megx12bit dual-port RAM. However, synthesis infers latches starting exactly at the 2^13th address leading me to believe I am running out of resources. What can I do to get this RAM to work?

Here's the code (note that the input tool is not used and will eventually be removed):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity DUALRAM_Custom is port (
    ADDR1  : in  STD_LOGIC_VECTOR(19 downto 0);
    D_in2  : in  STD_LOGIC_VECTOR(11 downto 0);
    ADDR2  : in  STD_LOGIC_VECTOR(19 downto 0);
    WE2    : in  STD_LOGIC;
    tool   : in  STD_LOGIC_VECTOR(3 downto 0);
    CLR    : in  STD_LOGIC;
    CLK    : in  STD_LOGIC;
    D_out1 : out STD_LOGIC_VECTOR(11 downto 0)
);      
end DUALRAM_Custom;

architecture Behavioral of DUALRAM_Custom is
    type RAM_type is ARRAY(0 to 1048575) of STD_LOGIC_VECTOR(11 downto 0);
    signal RAM : RAM_type := (others => (others => '0'));
begin

    process(CLK) is
    begin
        if((CLK'event) AND (CLK = '1')) THEN
            D_out1 <= RAM(to_integer(unsigned(ADDR1)));

            if ((WE2 = '1') AND (CLR = '0')) THEN
                if (CLR = '1') THEN
                    RAM(to_integer(unsigned(ADDR2))) <= x"000";
                else
                    RAM(to_integer(unsigned(ADDR2))) <= D_in2;
                end if;
            end if;
        end if;
    end process;
end Behavioral;

Upvotes: 1

Views: 5600

Answers (1)

Jim Lewis
Jim Lewis

Reputation: 3973

You need to look at exactly what type of RAM your parts support. One thing that is may be causing problems is the initialization of the RAM. Some technologies do not support reset on their RAMs. Some will as a pre-load during power up.

signal RAM : RAM_type := (others => (others => '0'));

Also note that your CLR logic is a little odd (as noted by Bill Lynch). Note that the functional part of a RAM on your chip probably does not have any form of reset on it, so this would be extra logic on the front end of your RAM. Mix that in with your coding style and it might result in something that your synthesis tool will not support. I would recommend at least temporarily removing the CLR functionality, get it working without it and experiment with re-adding it.

I also recommend using a variable for your RAM rather than a signal as a signal for a RAM of the size you are implementing may result in your simulation running much slower than a variable.

The following code is for a true dual port RAM. I have synthesized this for both Xilinx and Altera. It has a little more features than you need, so remove the parts you don't need and give it a try. It may take a little experimenting to get to the tools synthesizing exactly what you want.

architecture RTL of DPRam_RIRO_RF_1024_var is
begin
  MemProc : process (ClkA, ClkB) 
    type MemType is array (0 to 1023) of std_logic_vector(7 downto 0) ;
    variable Mem : MemType ;
  begin
    if rising_edge(ClkA) then     
      DataOutA <= Mem(to_integer(unsigned(AddrA))) ; 
      if WriteA = '1' then 
        Mem(to_integer(unsigned(AddrA))) := DataInA ; 
      end if ;
    end if ;

    if rising_edge(ClkB) then     
      DataOutB <= Mem(to_integer(unsigned(AddrB))) ; 
      if WriteB = '1' then 
        Mem(to_integer(unsigned(AddrB))) := DataInB ; 
      end if ;
    end if ;

  end process ; 
end RTL ;

Once you get something that works, be sure to look at how many resources it uses as I have noticed that some of my working RAMs ended up using 2X the resources I needed until I got the coding right.

Upvotes: 2

Related Questions