Advice on how to slice a dynamic array

Hi All,

I have trouble trying to build a task in system verilog. I request your suggestions.

The purpose of the task is to look at the value of “blk_len” passed in as a argument and pack it into blocks of 32 elements each (the last block might have less than 32 elements depending upon the blk_len value).

So this is what I’ve tried so far.

parameter WORD_SIZE = 32;

task write(bit [23:0] addr, bit [15:0] blk_len, bit[31:0] data[]);
  int count;
  bit[31:0] hold_data[];

  count = (blk_len - 1)/WORD_SIZE;

  for(int i=0; i<= count; i++) begin
    if(i == count)
      hold_data = data[(i*WORD_SIZE) : (blk_len - (i*WORD_SIZE) - 1)];  // this line is to wrap up the remaining elements into the last block
    else
      hold_data = data[(i*WORD_SIZE) : (i*WORD_SIZE + (WORD_SIZE-1))];  
    $display(hold_data);
  end
endtask

When I try to run this, I get an error saying “Illegal operand for constant expression [4(IEEE)]”

To work around this, I learnt about a +: operator in verilog and re-wrote as follows,


final_chunk = blk_len - 32*(count-1);
hold_data = data[(i*WORD_SIZE) +: final_chunk];

This didn’t work as well.

Can you give me some suggestions on how to finish this task? or some other approach with which this problem can be dealt with ?

Thanks

In reply to szy0014:

Your for loop does not make any sense because each iteration overwrites the previous value of hold_data. Also what is the relationship between data and wr_data. Where is the declaration of wr_data.

The range you are trying to describe [(iWORD_SIZE) : (iWORD_SIZE + (WORD_SIZE-1))] should be written as [(i*WORD_SIZE) +: WORD_SIZE].

You may want to take a look at the streaming pack/unpack operator in the LRM

In reply to dave_59:

I’m sorry about that. For simplicity, I used simple variable names and I’m just displaying my hold_data in this code. In actual scenario I would do something with that. It’s okay if it is erased after I use it (in this case just display it).

I will look into the streaming pack/unpack operator. I edited the original question for clarity

Thank You.

In reply to szy0014:

Another thing that does not make sense is that data and hold_data are both 32-bit (WORD_SIZE) dynamic arrays, yet you appear to be trying to index a single WORD of the array by bit position.

In reply to dave_59:

Yes. Since I could not compile, I’m not sure if that is the right way. My intent is : ‘data’ is a dynamic 2D array whose size is defined by ‘blk_len’. For example, if ‘blk_len’ is 10, ‘data’ holds 10 32-bit words. I have another dynamic array hold_data, which holds the slice of data (calculated by the math). In other words, based on the math, I want to create ‘hold_data’ array which holds the subset of words of the data array. Is this the wrong way to do it?

Thanks.

In reply to szy0014:

I assume you mean that data is a dynamic array whose size is larger than blk_len and you want the first blk_len elements moved over to hold_data. If the element size of data and hold_data are the same (as your example shows), then you just need a for loop.

hold_data = new[blk_len];
for(int i=0;i<blk_len;i++) hold_data[i] = data[i];

You can also do this in one statement using the streaming pack operator.

hold_data = {>>{data with [0:blk_len-1]}};

The nice thing about the streaming operator is that it works even if the array element sizes differ. You just might have to play around with it if the alignment does not work out.

In reply to dave_59:

Thanks a lot Dave. That worked.