VHDL: RAM

RAM is a useful thing to have when you need to store bits of information for later, the code below is for a simple, single port write first, RAM module and test bench. This may seem like a great bit of code to have lying around, but in reality it’s more for educational purposes. If you were actually going to use a RAM module like the one below you should really use a RAM generator from the manufacture of what ever device you are using ie: Xilinx, Altera, Lattice… These generated module are designed to take advantage of special RAM blocks built into the FPGA which allows them to be fast and efficient.

The function of this module is simple, by changing the address bits Address you can then read, on the next clock cycle, the data that is present at that memory location on the DataOut pins. In order to write data to a specific memory location you simply supply the data and address to the DataIn and Address lines respectively and then toggle the write enable WriteEn high for one clock cycle. The Enable bit is a global enable that prevents any actions from happening if the pin is low.

To change the width and depth of this module you only need to change the two generics at the top of the module. The DATA_WIDTH controls how many bits are in the input and out data. To adjust how many memory locations are in the RAM module you need to adjust the address width ADDRESS_WIDTH, this controls how many bits are in the address input and the number of RAM location will be 2^{\textit{ADDRESS\_WIDTH}} spots. For example if you have an address width of 8, like below, you would be able to read 256 different memory locations.

Code

VHDL

 Test Bench

Change Log

7/6/2013: Removed need for ADDR_COUNT generic. Updated port and generic names for consistency.

Share

11 thoughts on “VHDL: RAM

  1. Hello
    when I describe a RAM with reset pin to clear whole the ram, synthesis tool (xilinx ISE) doesn’t accept my describe as a Block RAM. It uses a lot of FF/Latch (flip flop) and warns me.
    when I remove this part of code:
    if Reset = ‘1’ then
    — Clear Memory on Reset
    for i in Memory’Range loop
    Memory(i) ‘0’);
    end loop;
    rest of the code will be accepted as a Block RAM, but not useful for my usage.

    Can U help me?

    • The default for this RAM is 256 locations each of 8 bits. It can be adjusted to 8 locations each of 6 bits by changing ADDRESS_WIDTH to 3 and DATA_WIDTH to 6.

  2. Query 1
    Is it possible to use my generic variables DIN_WIDTH and ADDR_WIDTH in the signal declaration lines below?
    signal Din : std_logic_vector(DIN_WIDTH downto 0) := (others => ‘0’);
    signal Addr : std_logic_vector(ADDR_WIDTH downto 0) := (others => ‘0’);
    instead of
    signal Din : std_logic_vector(7 downto 0) := (others => ‘0’);
    signal Addr : std_logic_vector(4 downto 0) := (others => ‘0’);

    In this case, do I need to declare these generics again as constants before my signal declarations? i.e.,
    constant DIN_WIDTH : integer := 8;
    constant ADDR_WIDTH : integer := 5;
    constant ADDR_COUNT : integer := 32;
    followed by signal declarations, generic map and port map?

    Query 2
    Is it possible to do the generic mapping without giving value to the constants declared? i.e.,

    COMPONENT RAM
    GENERIC (
    DIN_WIDTH : integer := 8;
    ADDR_WIDTH : integer := 5;
    ADDR_COUNT : integer := 32
    );
    ……………….
    END COMPONENT;

    ***generic constant declaration before signal declaration but without giving value to the constant variable***.
    constant DIN_WIDTH: integer ;
    constant ADDR_WIDTH: integer ;
    constant ADDR_COUNT: integer ;
    –Inputs
    signal CLK : std_logic := ‘0’;
    …………….
    BEGIN
    — Instantiate the Unit Under Test (UUT)
    uut: RAM

    generic map (DIN_WIDTH => DIN_WIDTH;
    ADDR_WIDTH => ADDR_WIDTH ;
    ADDR_COUNT => ADDR_COUNT);
    something like this?

    I want to change DIN_WIDTH, ADDR_WIDTH, ADDR_COUNT only in the generics not in the constant declaration. Is it possible?

    • If you declare a constant (or a generic for the module your in) before the signal declaration you can use it in the signal declaration, component declaration and instantiation.

      Entity test_bench is
      Generic (
      constant DIN_WIDTH : integer := 8;

      End test_bench;

      Architecture behavior of test_bench is
      Constant ADDR_WIDTH : integer := 5;

      Component RAM is…
      End component;

      Begin
      uut : RAM
      generic map (
      DIN_WIDTH := DIN_WIDTH,
      ADDR_WIDTH := ADDR_WIDTH);
      port map (
      ….

Leave a Reply

Your email address will not be published. Required fields are marked *