A ROM (Read-Only Memory) stores fixed data that does not change. Using a constant array in VHDL helps us create a simple ROM to hold values we want to read anytime.
ROM using constant array in VHDL
library ieee; use ieee.std_logic_1164.all; entity rom_constant_array is generic ( N : positive := 4; M : positive := 4 ); port( address : in integer range 0 to N-1; data_out : out std_logic_vector(M-1 downto 0) ); end entity; architecture behavior of rom_constant_array is type rom_type is array (0 to N-1) of std_logic_vector(M-1 downto 0); constant rom_contents : rom_type := ( 0 => "value0", 1 => "value1", -- ... fill all values ... N-1 => "valueN-1" ); begin process(address) begin data_out <= rom_contents(address); end process; end architecture;
The constant array holds all ROM data fixed at compile time.
The address input selects which data value to output.
library ieee; use ieee.std_logic_1164.all; entity rom_example is port( address : in integer range 0 to 3; data_out : out std_logic_vector(3 downto 0) ); end entity; architecture behavior of rom_example is type rom_type is array (0 to 3) of std_logic_vector(3 downto 0); constant rom_contents : rom_type := ( 0 => "0001", 1 => "0010", 2 => "0100", 3 => "1000" ); begin process(address) begin data_out <= rom_contents(address); end process; end architecture;
library ieee; use ieee.std_logic_1164.all; entity rom_empty is port( address : in integer range 0 to 0; data_out : out std_logic_vector(3 downto 0) ); end entity; architecture behavior of rom_empty is type rom_type is array (0 to 0) of std_logic_vector(3 downto 0); constant rom_contents : rom_type := ( 0 => "0000" ); begin process(address) begin data_out <= rom_contents(address); end process; end architecture;
library ieee; use ieee.std_logic_1164.all; entity rom_single_element is port( address : in integer range 0 to 0; data_out : out std_logic_vector(7 downto 0) ); end entity; architecture behavior of rom_single_element is type rom_type is array (0 to 0) of std_logic_vector(7 downto 0); constant rom_contents : rom_type := ( 0 => "10101010" ); begin process(address) begin data_out <= rom_contents(address); end process; end architecture;
This program defines a 4-word ROM with 4-bit values. The testbench cycles through addresses 0 to 3 and prints the data output for each address.
library ieee; use ieee.std_logic_1164.all; entity rom_demo is port( address : in integer range 0 to 3; data_out : out std_logic_vector(3 downto 0) ); end entity; architecture behavior of rom_demo is type rom_type is array (0 to 3) of std_logic_vector(3 downto 0); constant rom_contents : rom_type := ( 0 => "0001", 1 => "0010", 2 => "0100", 3 => "1000" ); begin process(address) begin data_out <= rom_contents(address); end process; end architecture; -- Testbench to show ROM output library ieee; use ieee.std_logic_1164.all; entity rom_demo_tb is end entity; architecture testbench of rom_demo_tb is signal address : integer range 0 to 3 := 0; signal data_out : std_logic_vector(3 downto 0); begin uut: entity work.rom_demo port map( address => address, data_out => data_out ); process begin for i in 0 to 3 loop address <= i; wait for 10 ns; report "Address: " & integer'image(i) & " Data Out: " & std_logic_vector'image(data_out); end loop; wait; end process; end architecture;
Time complexity: Reading from ROM is O(1) because it's direct indexing.
Space complexity: Depends on ROM size (number of elements and data width).
Common mistake: Using an address outside the defined range causes simulation errors.
Use ROM with constant array when data never changes; use RAM if you need to write data.
ROM using constant array stores fixed data accessible by address.
It is simple and fast for reading fixed values in hardware design.
Always ensure address range matches the ROM size to avoid errors.
Practice
constant array to implement ROM in VHDL?Solution
Step 1: Understand ROM functionality
ROM (Read-Only Memory) stores fixed data that does not change during operation.Step 2: Role of constant array in VHDL
A constant array holds fixed values accessible by address, perfect for ROM implementation.Final Answer:
To store fixed data that can be read by address during simulation or synthesis -> Option DQuick Check:
ROM = fixed data storage [OK]
- Confusing ROM with writable RAM
- Thinking ROM can be changed during runtime
- Using variable arrays instead of constant arrays
Solution
Step 1: Check array declaration syntax
In VHDL, constant arrays must be declared with proper type and range, here 0 to 3 for 4 elements.Step 2: Check value format for std_logic_vector
Values must be std_logic_vector literals; hex notation x".." is correct for 8-bit vectors.Final Answer:
constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (x"01", x"02", x"04", x"08"); -> Option AQuick Check:
Hex literals with x".." for std_logic_vector [OK]
- Using double quotes for hex values incorrectly
- Assigning integers directly to std_logic_vector
- Incorrect array type or syntax
data_out when addr = "10" (binary 2)?
constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (x"0A", x"1B", x"2C", x"3D"); process(addr) begin data_out <= ROM(to_integer(unsigned(addr))); end process;
Solution
Step 1: Convert address to integer
Address "10" in binary equals decimal 2.Step 2: Access ROM at index 2
ROM(2) is x"2C" as per the constant array declaration.Final Answer:
x"2C" -> Option AQuick Check:
addr 2 accesses ROM(2) = x"2C" [OK]
- Confusing binary "10" as decimal 10
- Using unsigned conversion incorrectly
- Accessing wrong ROM index
constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (x"01", x"02", x"03");
Solution
Step 1: Check array range and element count
Array declared from 0 to 3 means 4 elements expected.Step 2: Count assigned elements
Only 3 elements are assigned, causing a size mismatch error.Final Answer:
ROM array size does not match the number of elements assigned -> Option BQuick Check:
Array size must equal element count [OK]
- Assigning fewer elements than declared range
- Misusing quotes for hex literals
- Thinking constants can be variables
addr?Solution
Step 1: Check ROM declaration size and initialization
ROM must have 16 elements (0 to 15) each 8-bit wide, fully initialized.Step 2: Verify address conversion and data read
Address is 4-bit std_logic_vector, converted to integer with to_integer(unsigned(addr)) to index ROM correctly.Step 3: Validate code correctness
constant ROM : array (0 to 15) of std_logic_vector(7 downto 0) := (x"00", x"01", x"02", x"03", x"04", x"05", x"06", x"07", x"08", x"09", x"0A", x"0B", x"0C", x"0D", x"0E", x"0F"); process(addr) begin data_out <= ROM(to_integer(unsigned(addr))); end process; correctly initializes all 16 elements and reads data using proper address conversion.Final Answer:
constant ROM : array (0 to 15) of std_logic_vector(7 downto 0) := (x"00", x"01", x"02", x"03", x"04", x"05", x"06", x"07", x"08", x"09", x"0A", x"0B", x"0C", x"0D", x"0E", x"0F"); process(addr) begin data_out <= ROM(to_integer(unsigned(addr))); end process; -> Option CQuick Check:
Full initialization + correct address indexing = constant ROM : array (0 to 15) of std_logic_vector(7 downto 0) := (x"00", x"01", x"02", x"03", x"04", x"05", x"06", x"07", x"08", x"09", x"0A", x"0B", x"0C", x"0D", x"0E", x"0F"); process(addr) begin data_out <= ROM(to_integer(unsigned(addr))); end process; [OK]
- Not initializing all ROM elements
- Using addr directly without conversion
- Declaring ROM without initialization
Ready to prove it?
Pass the test and this pattern moves unknown
