VHDL coding tips and tricks: What to be careful of when resetting a 2D RAM

Friday, August 19, 2016

What to be careful of when resetting a 2D RAM

In this post, I want to show you how to reset a RAM using vhdl. I have shown this using a two dimensional RAM, but in effect the method holds for any dimension.

A 2D RAM(Random Access Memory) is basically declared using an array type in VHDL. You can check this post for more information on this.

In the example, I have declared a RAM with width 8 bits and depth 256 elements. You can reset a RAM in two ways.

1)Resetting in one clock cycle:

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

entity top_module is
port(   Clk,reset : in std_logic;   --clock and reset signal
        wr_en : in std_logic;   --write enable signal
        data_in : in unsigned(7 downto 0);  --write input to the RAM
        data_out : out unsigned(7 downto 0);    --read signal from the RAM
        addr_wr : in integer;   --write address
        addr_rd : in integer    --read address
        );
end top_module;

architecture Behavioral of top_module is

--ram type declaration
type ram_type is array(0 to 255) of unsigned(7 downto 0);
signal ram : ram_type;  --definition of ram

begin

--reading and writing of RAM
process(clk)
begin
    if(rising_edge(Clk)) then
        if(reset = '1') then    --synchronous reset
        --all bits reset in one clock cycle
            ram <= (others => (others => '0'));
        else    
            if(wr_en = '1') then    --write to ram when wr_en is high
                ram(addr_wr) <= data_in;
            end if;
            data_out <= ram(addr_rd); --read from ram and output the result
        end if; 
    end if;
end process;    

end Behavioral;

Its easier to write the code for this method as you can see. But this requires writing to all the locations of the RAM in a single clock cycle. So the RAM is implemented on FPGA as a collection of 256 registers, each 8 bits wide. The in-built block RAM available on fpga isn't used, because it's not possible to write to more than two locations of block RAM in one clock cycle. 

This method is fine for small sized RAM's. But if you want to use bigger RAM's and make use of built-in resources in the fpga you need to adopt a different method.

2)Resetting in multiple clock cycles:

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

entity top_module_2 is
port(   Clk,reset : in std_logic;   --clock and reset signal
        wr_en : in std_logic;   --write enable signal
        data_in : in unsigned(7 downto 0);  --write input to the RAM
        data_out : out unsigned(7 downto 0);    --read signal from the RAM
        addr_wr : in integer;   --write address
        addr_rd : in integer    --read address
        );
end top_module_2;

architecture Behavioral of top_module_2 is

--ram type declaration
type ram_type is array(0 to 255) of unsigned(7 downto 0);
signal ram : ram_type;  --definition of ram
signal count : integer := 0;

begin

process(clk)
begin
    if(rising_edge(Clk)) then
        if(reset = '1') then    --synchronous reset
        --reset the ram locations one by one. so it takes 256 clock cycles to reset the ram
            if(count <= 255) then
                count <= count + 1;
                ram(count) <= x"00";
            else
                count <= 0;
            end if;
        else    
            if(wr_en = '1') then    --write to ram when wr_en is high
                ram(addr_wr) <= data_in;
            end if;
            data_out <= ram(addr_rd); --read from ram and output the result
        end if; 
    end if;
end process;    

end Behavioral;

 The resetting part is a bit more complex here. We take 256 clock cycles to reset the whole RAM. The signal 'count' is incremented in every clock cycle and used an an address to the RAM. This way of resetting satisfies the properties of a block RAM. So the synthesis tool uses the in-built block RAM available in fpga for inferring the RAM.

The disadvantage of this method is that, the reset signal have to be applied for a time, proportional to the depth or RAM. For large RAM's, this will cause a large delay. But on the good side, we can use block RAM available inside the FPGA and save the other resources for implementing non-memory logic.


No comments:

Post a Comment