VHDL Code for Dual Port RAM: Syntax and Example
A
dual port RAM in VHDL is a memory block with two independent ports for simultaneous read/write operations. It typically uses two sets of address, data, and control signals. You can implement it using a process block with separate read/write logic for each port.Syntax
The basic syntax for a dual port RAM in VHDL includes defining a type for memory, signals for two ports (A and B), and a process that handles read and write operations independently for each port.
- entity: Declares inputs and outputs for two ports.
- architecture: Contains the memory array and the process.
- process: Handles clocked read/write for both ports.
vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity dual_port_ram is
generic (
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 4
);
port (
clk : in std_logic;
-- Port A
addr_a : in std_logic_vector(ADDR_WIDTH-1 downto 0);
data_in_a : in std_logic_vector(DATA_WIDTH-1 downto 0);
we_a : in std_logic;
data_out_a : out std_logic_vector(DATA_WIDTH-1 downto 0);
-- Port B
addr_b : in std_logic_vector(ADDR_WIDTH-1 downto 0);
data_in_b : in std_logic_vector(DATA_WIDTH-1 downto 0);
we_b : in std_logic;
data_out_b : out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end dual_port_ram;
architecture Behavioral of dual_port_ram is
type ram_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal ram : ram_type := (others => (others => '0'));
begin
process(clk)
begin
if rising_edge(clk) then
-- Port A write
if we_a = '1' then
ram(to_integer(unsigned(addr_a))) <= data_in_a;
end if;
-- Port A read
data_out_a <= ram(to_integer(unsigned(addr_a)));
-- Port B write
if we_b = '1' then
ram(to_integer(unsigned(addr_b))) <= data_in_b;
end if;
-- Port B read
data_out_b <= ram(to_integer(unsigned(addr_b)));
end if;
end process;
end Behavioral;Example
This example shows a dual port RAM with 8-bit data and 4-bit address width. It supports independent read and write on both ports A and B on the rising clock edge.
vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity dual_port_ram is
generic (
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 4
);
port (
clk : in std_logic;
addr_a : in std_logic_vector(ADDR_WIDTH-1 downto 0);
data_in_a : in std_logic_vector(DATA_WIDTH-1 downto 0);
we_a : in std_logic;
data_out_a : out std_logic_vector(DATA_WIDTH-1 downto 0);
addr_b : in std_logic_vector(ADDR_WIDTH-1 downto 0);
data_in_b : in std_logic_vector(DATA_WIDTH-1 downto 0);
we_b : in std_logic;
data_out_b : out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end dual_port_ram;
architecture Behavioral of dual_port_ram is
type ram_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal ram : ram_type := (others => (others => '0'));
begin
process(clk)
begin
if rising_edge(clk) then
if we_a = '1' then
ram(to_integer(unsigned(addr_a))) <= data_in_a;
end if;
data_out_a <= ram(to_integer(unsigned(addr_a)));
if we_b = '1' then
ram(to_integer(unsigned(addr_b))) <= data_in_b;
end if;
data_out_b <= ram(to_integer(unsigned(addr_b)));
end if;
end process;
end Behavioral;Output
No direct console output; the RAM stores and outputs data on ports A and B as per clock and control signals.
Common Pitfalls
- Simultaneous write to the same address: Writing to the same address from both ports at the same time can cause undefined behavior.
- Read-before-write timing: Reading and writing the same address in the same clock cycle may return old or new data depending on synthesis.
- Incorrect address conversion: Forgetting to convert
std_logic_vectortointegerusingto_integer(unsigned())causes errors. - Missing clock edge condition: Always use
if rising_edge(clk)to synchronize memory operations.
vhdl
wrong: data_out_a <= ram(addr_a); -- addr_a is std_logic_vector, needs conversion right: data_out_a <= ram(to_integer(unsigned(addr_a)));
Quick Reference
- Use
std_logic_vectorfor addresses and data ports. - Convert addresses to integer with
to_integer(unsigned(addr))before indexing. - Use separate write enable signals for each port.
- Synchronize all operations on the rising clock edge.
- Be cautious with simultaneous writes to the same address.
Key Takeaways
Dual port RAM allows simultaneous read/write on two independent ports using separate address and control signals.
Always synchronize RAM operations with a clock edge using a process block.
Convert address signals from std_logic_vector to integer before accessing the memory array.
Avoid writing to the same address from both ports at the same time to prevent conflicts.
Use separate write enable signals for each port to control memory writes independently.