Jiren
Jiren

Reputation: 11

For loops for reading data from a ROM Block in Verilog

I asked this question yesterday, but it was closed because I was unable to provide code for the problem and relevant waveforms. Hence, this is an updated version of the question yesterday.

I am trying to write to an array of registers using for loops on Verilog. However, I am having issues with the syntax I believe, because the array always only has the first value held in the ROM (50) after I run the code (it is worth mentioning, I’m a newbie at Verilog).

Essentially, I have 16 entries stored in a ROM block, and I want to read the data stored in the ROM block to an array. The ROM was created using the Block Memory Generator in the IP catalogue. Here is what I have done:

    reg [4:0] coord  = 5'd0; //counter for the address of the ROMs
    wire [10:0] out_ROM; // Output of ROM block (douta)

    coordinates rom1 (.clka(clk), .addra(coord), .douta(out_x1)); // instantiation of the ROM IP
    
    reg  [10:0] x1 [15:0]; // Array which needs to store the ROM block info

    always@(posedge clk)
    begin

       for (coord = 5'd0; coord < 5'd16; coord = coord + 1) begin
           
              x1[coord] <= out_ROM; //assign the data at each address (coord) to the array
        end
    end

The following is what the test bench waveform shows:

enter image description here

This is how the test bench starts off as, however, after 16 clock cycles, the counter coord jumps to 16, and the value in x1 is the first value in the ROM block (50): enter image description here

I am not sure as to why the counter skips all the other values and jumps straight to 16. And why is the output the first value in the ROM block, surely if coord is 16, the output value of the ROM should be the value at address number 16, which is 1390 and not 50.

I wanted to also attach the COE file used to generate the single port ROM memory block generator, however, I don't think stack overflow supports attachments. Is there any other way to share the COE file (I don't think it's overly important, but can be necessary to reproduce the code).

Any help would be massively appreciated. Thanks!

Upvotes: 0

Views: 909

Answers (1)

Ryan Johnson
Ryan Johnson

Reputation: 114

  1. You are misunderstanding how a for loop works. You have a comment next to the declaration of coord that says it is a counter. It is not. It is a loop variable. You have a for loop in your code. The for loop will run in its entirety at every posedge of the clock (you, in essence, wrote "at every positive edge of the clock, run this for loop from start to finish").
  2. You are instantiating a very small ROM (11x32) using the Xilinx Block Memory Generator IP. This is inefficient. You're wasting an entire block ram (or at least half of one). Use the Distributed Memory Generator instead, or infer it in RTL.

You may want something more like this:

// testbench stimulus

  reg clk=0; always #5 clk=!clk;

  reg reset=1;
  initial begin
    #1us;
    reset = 0;
  end

// Code

  reg [4:0] coord=0; // counter for the address of the ROMs
  wire [10:0] out_ROM; // Output of ROM block (douta)
  
  reg [10:0] rom1[31:0]; // Instantiate the ROM in RTL
  initial begin // Initialize the ROM
    rom1[0] = 11'd123;
    rom1[1] = 11'd258;
    // ...
  end
  
  reg [10:0] x1[15:0]; // Array which needs to store the ROM block info

  always @ (posedge clk)
    if (reset)
      coord <= 0;
    else
      coord <= coord + 1;
      
  always @ (posedge clk)
    x1[coord] <= out_ROM; // assign the data at each address (coord) to the array

Upvotes: 1

Related Questions