Bird
Raised Fist0
VHDLprogramming~5 mins

ROM using constant array in VHDL

Choose your learning style10 modes available
Introduction

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.

When you want to store fixed lookup values like a small table of numbers.
When you need to hold a set of instructions or constants in hardware.
When you want to simulate memory that never changes during operation.
Syntax
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.

Examples
This example shows a 4-word ROM with 4-bit data values.
VHDL
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;
This shows a ROM with only one element, useful for edge case testing.
VHDL
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;
ROM with a single 8-bit value, showing smallest ROM size.
VHDL
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;
Sample Program

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.

VHDL
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;
OutputSuccess
Important Notes

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.

Summary

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

(1/5)
1. What is the main purpose of using a constant array to implement ROM in VHDL?
easy
A. To generate random data values dynamically
B. To create a writable memory block for data storage
C. To perform arithmetic operations on data
D. To store fixed data that can be read by address during simulation or synthesis

Solution

  1. Step 1: Understand ROM functionality

    ROM (Read-Only Memory) stores fixed data that does not change during operation.
  2. Step 2: Role of constant array in VHDL

    A constant array holds fixed values accessible by address, perfect for ROM implementation.
  3. Final Answer:

    To store fixed data that can be read by address during simulation or synthesis -> Option D
  4. Quick Check:

    ROM = fixed data storage [OK]
Hint: ROM stores fixed data accessed by address only [OK]
Common Mistakes:
  • Confusing ROM with writable RAM
  • Thinking ROM can be changed during runtime
  • Using variable arrays instead of constant arrays
2. Which of the following is the correct way to declare a ROM using a constant array of 8-bit std_logic_vector in VHDL?
easy
A. constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (x"01", x"02", x"04", x"08");
B. constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := ("0000001", "0000010", "0000100", "0001000");
C. constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := ("x01", "x02", "x04", "x08");
D. constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (1, 2, 4, 8);

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (x"01", x"02", x"04", x"08"); -> Option A
  4. Quick Check:

    Hex literals with x".." for std_logic_vector [OK]
Hint: Use x".." for hex std_logic_vector constants [OK]
Common Mistakes:
  • Using double quotes for hex values incorrectly
  • Assigning integers directly to std_logic_vector
  • Incorrect array type or syntax
3. Given the following VHDL ROM declaration and read process, what is the output on 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;
medium
A. x"2C"
B. x"1B"
C. x"0A"
D. x"3D"

Solution

  1. Step 1: Convert address to integer

    Address "10" in binary equals decimal 2.
  2. Step 2: Access ROM at index 2

    ROM(2) is x"2C" as per the constant array declaration.
  3. Final Answer:

    x"2C" -> Option A
  4. Quick Check:

    addr 2 accesses ROM(2) = x"2C" [OK]
Hint: Convert binary address to integer to index ROM [OK]
Common Mistakes:
  • Confusing binary "10" as decimal 10
  • Using unsigned conversion incorrectly
  • Accessing wrong ROM index
4. Identify the error in this VHDL ROM constant array declaration:
constant ROM : array (0 to 3) of std_logic_vector(7 downto 0) := (x"01", x"02", x"03");
medium
A. Hex values must be in single quotes, not double quotes
B. ROM array size does not match the number of elements assigned
C. std_logic_vector cannot be used in constant arrays
D. ROM must be declared as a variable, not constant

Solution

  1. Step 1: Check array range and element count

    Array declared from 0 to 3 means 4 elements expected.
  2. Step 2: Count assigned elements

    Only 3 elements are assigned, causing a size mismatch error.
  3. Final Answer:

    ROM array size does not match the number of elements assigned -> Option B
  4. Quick Check:

    Array size must equal element count [OK]
Hint: Match array range with number of elements exactly [OK]
Common Mistakes:
  • Assigning fewer elements than declared range
  • Misusing quotes for hex literals
  • Thinking constants can be variables
5. You want to create a 16-word ROM with 4-bit addresses and 8-bit data using a constant array in VHDL. Which of the following code snippets correctly implements this ROM and reads data based on the address input addr?
hard
A. constant ROM : array (0 to 15) of std_logic_vector(7 downto 0) := (others => (others => '0')); process(addr) begin data_out <= ROM(addr); end process;
B. constant ROM : array (0 to 15) of std_logic_vector(7 downto 0); process(addr) begin data_out <= ROM(addr); end process;
C. 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;
D. constant ROM : array (0 to 15) of std_logic_vector(7 downto 0) := (x"00", x"01", x"02", x"03"); process(addr) begin data_out <= ROM(to_integer(unsigned(addr))); end process;

Solution

  1. Step 1: Check ROM declaration size and initialization

    ROM must have 16 elements (0 to 15) each 8-bit wide, fully initialized.
  2. 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.
  3. 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.
  4. 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 C
  5. Quick 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]
Hint: Initialize all ROM elements and convert address to integer [OK]
Common Mistakes:
  • Not initializing all ROM elements
  • Using addr directly without conversion
  • Declaring ROM without initialization
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard