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.
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;
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;
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