Bird
Raised Fist0
Verilogprogramming~20 mins

ROM (Read-Only Memory) in Verilog - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Verilog ROM Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
1:30remaining
What is the output of this ROM read operation?
Given the following Verilog ROM module and testbench snippet, what value will be output on data_out when addr = 3'b010?
Verilog
module rom_example(input [2:0] addr, output reg [7:0] data_out);
  reg [7:0] rom [0:7];
  initial begin
    rom[0] = 8'hAA;
    rom[1] = 8'hBB;
    rom[2] = 8'hCC;
    rom[3] = 8'hDD;
    rom[4] = 8'hEE;
    rom[5] = 8'hFF;
    rom[6] = 8'h11;
    rom[7] = 8'h22;
  end
  always @(*) begin
    data_out = rom[addr];
  end
endmodule

// Testbench snippet
// addr = 3'b010;
// Expected data_out = ?
A8'hDD
B8'hBB
C8'hEE
D8'hCC
Attempts:
2 left
💡 Hint
Remember that the address 3'b010 corresponds to decimal 2, so the ROM output is the value stored at index 2.
🧠 Conceptual
intermediate
1:00remaining
Which statement about ROM initialization in Verilog is true?
Consider these statements about initializing ROM in Verilog. Which one is correct?
AROM contents can be initialized using an <code>initial</code> block with explicit assignments.
BROM contents must be loaded from an external file at runtime only.
CROM cannot be initialized in Verilog; it must be programmed after synthesis.
DROM contents are automatically zero unless explicitly written during simulation.
Attempts:
2 left
💡 Hint
Think about how Verilog simulation allows setting initial values for memory arrays.
🔧 Debug
advanced
1:30remaining
Why does this ROM code cause a synthesis error?
Examine this ROM code snippet. Why will it cause a synthesis error?
Verilog
module rom_bug(input clk, input [1:0] addr, output reg [3:0] data_out);
  reg [3:0] rom [0:3];
  always @(posedge clk) begin
    data_out <= rom[addr];
  end
endmodule
AThe ROM is not initialized, so synthesis tools cannot infer ROM contents.
BUsing <code>always @(posedge clk)</code> with a ROM array causes synthesis error because ROM is combinational.
CThe output <code>data_out</code> must be declared as wire, not reg.
DThe address width is too small for the ROM size.
Attempts:
2 left
💡 Hint
Think about how ROM is usually modeled in Verilog and how synchronous blocks affect synthesis.
📝 Syntax
advanced
1:00remaining
Which ROM declaration is syntactically correct in Verilog?
Select the correct way to declare a 16x8-bit ROM in Verilog.
Areg [7:0] rom [0:15];
Breg [15:0] rom [7:0];
Creg rom [7:0][7:0];
Dwire [7:0] rom [0:15];
Attempts:
2 left
💡 Hint
Remember the syntax for declaring memory arrays in Verilog: reg [width-1:0] name [0:size-1];
🚀 Application
expert
2:00remaining
How many clock cycles does it take to read data from this ROM?
Given this ROM module with synchronous read, how many clock cycles after addr changes will data_out reflect the new data?
Verilog
module rom_sync(input clk, input [3:0] addr, output reg [7:0] data_out);
  reg [7:0] rom [0:15];
  initial begin
    rom[0] = 8'h01; rom[1] = 8'h02; rom[2] = 8'h03; rom[3] = 8'h04;
    // ... initialize other locations
  end
  always @(posedge clk) begin
    data_out <= rom[addr];
  end
endmodule
ADepends on the synthesis tool
BTwo clock cycles
COne clock cycle
DZero clock cycles (immediate combinational output)
Attempts:
2 left
💡 Hint
Since the ROM read is inside a clocked block with non-blocking assignment, output updates on the next clock edge.

Practice

(1/5)
1. What is the primary purpose of a ROM (Read-Only Memory) in Verilog?
easy
A. To store fixed data that cannot be changed during simulation or operation
B. To store data that can be written and read dynamically
C. To perform arithmetic operations
D. To generate clock signals

Solution

  1. Step 1: Understand ROM functionality

    ROM is designed to hold data that is fixed and cannot be modified during operation.
  2. Step 2: Compare with other memory types

    Unlike RAM, ROM data is read-only and does not support writing during runtime.
  3. Final Answer:

    To store fixed data that cannot be changed during simulation or operation -> Option A
  4. Quick Check:

    ROM = fixed data storage [OK]
Hint: ROM stores fixed data only, no writes allowed [OK]
Common Mistakes:
  • Confusing ROM with RAM (read-write memory)
  • Thinking ROM can perform operations
  • Assuming ROM generates signals
2. Which of the following is the correct way to declare a ROM using an array and initial block in Verilog?
easy
A. integer rom_mem; always @(posedge clk) rom_mem = 8'hAA;
B. wire [7:0] rom_mem [0:3]; always @(posedge clk) rom_mem[0] <= 8'hAA;
C. reg [7:0] rom_mem; initial rom_mem = 8'hAA;
D. reg [7:0] rom_mem [0:3]; initial begin rom_mem[0] = 8'hAA; rom_mem[1] = 8'hBB; rom_mem[2] = 8'hCC; rom_mem[3] = 8'hDD; end

Solution

  1. Step 1: Identify correct ROM declaration

    ROM is declared as a reg array with an initial block to assign fixed values.
  2. Step 2: Check each option

    reg [7:0] rom_mem [0:3]; initial begin rom_mem[0] = 8'hAA; rom_mem[1] = 8'hBB; rom_mem[2] = 8'hCC; rom_mem[3] = 8'hDD; end uses reg array and initial block correctly. wire [7:0] rom_mem [0:3]; always @(posedge clk) rom_mem[0] <= 8'hAA; uses wire and always block incorrectly. Options C and D do not declare arrays properly.
  3. Final Answer:

    reg [7:0] rom_mem [0:3]; initial begin rom_mem[0] = 8'hAA; rom_mem[1] = 8'hBB; rom_mem[2] = 8'hCC; rom_mem[3] = 8'hDD; end -> Option D
  4. Quick Check:

    ROM array + initial block = reg [7:0] rom_mem [0:3]; initial begin rom_mem[0] = 8'hAA; rom_mem[1] = 8'hBB; rom_mem[2] = 8'hCC; rom_mem[3] = 8'hDD; end [OK]
Hint: Use reg array with initial block for ROM data [OK]
Common Mistakes:
  • Using wire instead of reg for ROM array
  • Assigning inside always block for ROM
  • Not using an array for multiple ROM entries
3. Given the following Verilog ROM code, what is the output value of data_out when addr = 2'b10?
module rom_example(input [1:0] addr, output reg [7:0] data_out);
  always @(*) begin
    case(addr)
      2'b00: data_out = 8'h1A;
      2'b01: data_out = 8'h2B;
      2'b10: data_out = 8'h3C;
      2'b11: data_out = 8'h4D;
      default: data_out = 8'h00;
    endcase
  end
endmodule
medium
A. 8'h4D
B. 8'h1A
C. 8'h3C
D. 8'h00

Solution

  1. Step 1: Locate the case for addr = 2'b10

    The case statement assigns data_out = 8'h3C when addr is 2'b10.
  2. Step 2: Confirm output value

    Since addr matches 2'b10, data_out will be 8'h3C.
  3. Final Answer:

    8'h3C -> Option C
  4. Quick Check:

    addr 2'b10 -> data_out 8'h3C [OK]
Hint: Match addr in case to find data_out quickly [OK]
Common Mistakes:
  • Choosing wrong case label
  • Confusing hex values
  • Ignoring default case
4. Identify the error in this ROM Verilog code snippet:
module rom_bug(input [1:0] addr, output reg [7:0] data_out);
  reg [7:0] rom_mem [0:3];
  initial begin
    rom_mem[0] = 8'hAA;
    rom_mem[1] = 8'hBB;
    rom_mem[2] = 8'hCC;
    rom_mem[3] = 8'hDD;
  end
  always @(*) begin
    data_out = rom_mem[addr];
  end
endmodule
medium
A. ROM array should be declared as wire, not reg
B. No error; code correctly implements ROM
C. Initial block cannot be used for ROM initialization
D. Using addr as index without conversion causes error

Solution

  1. Step 1: Check ROM declaration and initialization

    ROM is declared as reg array and initialized in initial block, which is correct for simulation.
  2. Step 2: Verify data output assignment

    Using addr as index to read rom_mem is valid and data_out is assigned in combinational always block.
  3. Final Answer:

    No error; code correctly implements ROM -> Option B
  4. Quick Check:

    ROM reg array + initial + combinational read = correct [OK]
Hint: ROM uses reg array + initial block + combinational read [OK]
Common Mistakes:
  • Thinking initial block is illegal for ROM
  • Confusing reg and wire for ROM arrays
  • Assuming addr needs conversion
5. You want to implement a 4-word ROM in Verilog that outputs the square of the address value (0, 1, 4, 9). Which of the following code snippets correctly implements this ROM?
hard
A. always @(addr) begin case(addr) 2'b00: data_out=8'd0; 2'b01: data_out=8'd1; 2'b10: data_out=8'd4; 2'b11: data_out=8'd9; default: data_out=8'd0; endcase end
B. reg [7:0] rom [0:3]; initial begin rom[0]=8'd0; rom[1]=8'd1; rom[2]=8'd4; rom[3]=8'd9; end always data_out = rom[addr];
C. reg [7:0] rom [0:3]; assign rom[0]=0; assign rom[1]=1; assign rom[2]=4; assign rom[3]=9; assign data_out=rom[addr];
D. reg [7:0] rom [0:3]; always @(posedge clk) begin rom[0]<=0; rom[1]<=1; rom[2]<=4; rom[3]<=9; end assign data_out=rom[addr];

Solution

  1. Step 1: Analyze each code snippet for ROM implementation

    reg [7:0] rom [0:3]; initial begin rom[0]=8'd0; rom[1]=8'd1; rom[2]=8'd4; rom[3]=8'd9; end always @(*) data_out = rom[addr]; lacks module and always block structure; data_out assignment is incomplete. always @(addr) begin case(addr) 2'b00: data_out=8'd0; 2'b01: data_out=8'd1; 2'b10: data_out=8'd4; 2'b11: data_out=8'd9; default: data_out=8'd0; endcase end uses a case statement to output fixed squares based on addr, which is a valid ROM implementation. reg [7:0] rom [0:3]; assign rom[0]=0; assign rom[1]=1; assign rom[2]=4; assign rom[3]=9; assign data_out=rom[addr]; tries to assign values to wire array elements, which is illegal. reg [7:0] rom [0:3]; always @(posedge clk) begin rom[0]<=0; rom[1]<=1; rom[2]<=4; rom[3]<=9; end assign data_out=rom[addr]; tries to assign ROM values inside a clocked always block, which is not suitable for ROM initialization.
  2. Step 2: Confirm correct ROM behavior

    always @(addr) begin case(addr) 2'b00: data_out=8'd0; 2'b01: data_out=8'd1; 2'b10: data_out=8'd4; 2'b11: data_out=8'd9; default: data_out=8'd0; endcase end correctly outputs squares for each address using a combinational case statement, matching ROM behavior.
  3. Final Answer:

    always @(addr) begin case(addr) 2'b00: data_out=8'd0; 2'b01: data_out=8'd1; 2'b10: data_out=8'd4; 2'b11: data_out=8'd9; default: data_out=8'd0; endcase end -> Option A
  4. Quick Check:

    ROM as combinational case statement = always @(addr) begin case(addr) 2'b00: data_out=8'd0; 2'b01: data_out=8'd1; 2'b10: data_out=8'd4; 2'b11: data_out=8'd9; default: data_out=8'd0; endcase end [OK]
Hint: Use case statement for fixed ROM outputs [OK]
Common Mistakes:
  • Assigning to wire arrays
  • Initializing ROM inside clocked always block
  • Not using combinational logic for ROM output
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