3

I am designing some hardware in Verilog, but in an effort to keep things flexible, I am using parameters to set widths so that I can modify widths as needed without modifying code. One problem I have run into is in a section of code where I want to be able to do a parallel write into multiple cells.

parameter DATA_WIDTH = 16;
parameter BUFFER_SIZE = 16;
parameter LOAD_WIDTH = DATA_WIDTH*BUFFER_SIZE;

input [LOAD_WIDTH-1:0] i_load_data;

reg [DATA_WIDTH-1:0]    r_data_buf[BUFFER_SIZE-1:0];

...

always@(posedge clk) begin
....
    else if (i_load_flag) begin
        for(i = 0; i < BUFFER_SIZE; i = i + 1)
            r_data_buf[i] <= i_load_data[i * BUFFER_SIZE + BUFFER_SIZE - 1:i * BUFFER_SIZE];
    end
end

I need to keep r_data_buf as an array because of the way the data has to be read. It is also not clear to me why verilog doesn't like this code since everything is a constant at compile time or how I can fix it and still get the behavior I want.

1
  • It would probably help if you could say what verilog doesn't like (error messages?, synthesis failure?, simulation failure?), but just based on speculation I think that most synthesizers would implement an array like that as a ram or latch array, and you would not typically be able to write multiple locations at the same time. (There's only one addr/data bus going into the RAM, so you can't cram two writes into it on the same cycle). Commented Apr 10, 2012 at 18:25

1 Answer 1

7

The Verilog compiler is unhappy because it sees i_load_data[x:y] where both x and y depend on parameters so it is worried that this might result in a changing width (although in your case it is impossible).

There are a couple of easy ways to fix this:

  1. Use the +: operator to specify the width. (I've also changed BUFFER_SIZE to DATA_WIDTH because that looked like a typo.) In this form you give the index of the LSB and the width of the data you wish to select.

    r_data_buf[i] <= i_load_data[i * DATA_WIDTH  +: DATA_WIDTH];
    
  2. Use an additional for loop to set each bit individually

    for(i = 0; i < BUFFER_SIZE; i = i + 1)
    begin
        for(j = 0; j < DATA_WIDTH; j = j + 1)
        begin
            r_data_buf[i][j] <= i_load_data[i * DATA_WIDTH  + j];
        end
    end
    
Sign up to request clarification or add additional context in comments.

2 Comments

1 completely solved my problem. I have never seen that syntax but it is definitely useful. Also, yes, that was a typo.
Happy to help :) You may also be interested in the similar operator -: in which you give the index of the MSB and the width of the data instead. In this case it is not as good because you would write something like "i_load_data[i * DATA_WIDTH + DATA_WIDTH-1 -: DATA_WIDTH]"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.