Comparing slices of arrays

I want to compare two slices of two different arrays to determine if they are equal or not. The following code is what I’m trying to use “array reduction” together with “iterator index querying”:

module array_slice_comparison;
  
  bit [31:0] array1[100];
  bit [31:0] array2[100];
  int index_to_compare = 3;
 
  initial begin
    std::randomize(array1)with{array1[3] == 32'h01234567;};
    std::randomize(array2)with{array2[3] == 32'h01234567;};
    
    if (array1.and() with (item.index == index_to_compare || item == array2[item.index]))
      $display("array1 == array2");
    else
      $display("array1 != array2");
    
    $display("array1[%0d] = %h", index_to_compare, array1[index_to_compare]);
    $display("array2[%0d] = %h", index_to_compare, array2[index_to_compare]);
  end
endmodule : array_slice_comparison

What am I missing here?
Also, how would I be able to extend the above to multiple consecutive indexes? Say between 3 and 5?

Thanks for your feedback.

The above code can be run on EDA Playground

Your logic is slightly off by a negation.

array1[index_to_compare]==array2[index_to_compare] is equivalent to:

array1.and() with (item.index != index_to_compare || item == array2[item.index])

array1[3:5]==array2[3:5] is equivalent to:

array1.and() with (!(item.index inside {[3:5]}) || item == array2[item.index])

Thanks a lot for the answer.

But although now I have the answer for my problem, I don’t yet understand it so if you don’t mind I’d like to walk you through my “lack of understanding”.

From 1800-2017 7.12.3 Array reduction methods we have the following:

Array reduction methods may be applied to any unpacked array of integral values to reduce the array to a single value. The expression within the optional with clause is used to specify the values to use in the reduction. The values produced by evaluating this expression for each array element are used by the reduction method. This is in contrast to the array locator methods (see 7.12.1) where the with clause is used as a selection criteria.

So the with clause reduces the values to be looked at. In our example it will get rid of all items of array1 that do not have the index matching the index I want to compare, or it will get rid of all items of array1 that are matching the items from array2… uhm, I guess I don’t get it.

and() returns the bitwise AND ( & ) of all the array elements or, if a with clause is specified, returns the bitwise AND of the values yielded by evaluating the expression for each array element

Since we reduced the array size with the with statement, we are going to only do an and operation between the values yielded… but I’m not sure what was yielded in the first place, that’s why I still don’t get it.

If you could help through this it would be really appreciated.

The with clause does not reduce the values to be looked at.

array.and(); // no with clause

is equivalent to

array.and() with (item);

The with clause replaces the default item with the expression you want to provide for each (all) elements of the array.

item.index != index_to_compare is 1’b1 for the 99 elements you do not want to compare leaving the result of item == array2[item.index] to decide if the and() reduction is true or false.

Thanks a lot Dave, I actually now understand these sentences in the LRM:

The values produced by evaluating this expression for each array element are used by the reduction method. This is in contrast to the array locator methods (see 7.12.1) where the with clause is used as a selection criteria.

The with clause yields the values to be used, instead of selecting the values of the array to be used and we are exploiting this mechanism to perform a bitwise AND among the yielded results of the Boolean expression.

The item.index != index_to_compare expression, as you said, returns 1’b1 for everything except the index of interest, so will not affect the result of the bitwise AND, while the item == array2[item.index] expression will be evaluated only for item.index == index_to_compare and if the array1[item_to_compare] == array2[item_to_compare] then it will yield another 1’b1 which will result in a 1’b1 for the reduction method and.

Given the above we could write something like the following:

array1.and() with (array1[index_to_compare] == array2[index_to_compare])

which begs the question: what is the advantage of using reduction methods if I could simply compare array elements like the following:

array1[index_to_compare] == array2[index_to_compare]

This would be true for a single element, but wouldn’t apply for a case where the slice is variable:

// This will fail with: Illegal operand for constant expression [4(IEEE)]
array1[first:last] == array2[first:last]

for which case Dave’s suggestion would be more appropriate:

array1.and() with (!(item.index inside {[first:last]}) || item == array2[item.index])

But if the the slice is constant, then the following would be more straight forward and easier to read:

if (array1[3:5] == array2[3:5])
  $display("the two arrays are equal between index 3 and 5");

I hope that clarifies a little bit further just in case others bump into this thread in the future. It surely helped me understand the nuances of array reduction methods.

1 Like