简体   繁体   中英

How to remove the repeated consecutive elements in dynamic array in systemverilog?

module tb;
  
  bit [7:0] bytes [];
  bit [7:0] q[$];
  
  initial begin
    bytes = new[20];
    bytes[0] = 8'hee;
    bytes[1] = 8'hea;
    bytes[2] = 8'haf;
    bytes[3] = 8'haf;
    bytes[4] = 8'haf;
    bytes[5] = 8'h50;
    bytes[6] = 8'h6a;
    bytes[7] = 8'h0d;
    bytes[8] = 8'hc8;
    bytes[9] = 8'hc8;
    bytes[10] = 8'h21;
    foreach(bytes[i])
      $write("%h ", bytes[i]);
    $display("\n");
    q = bytes.unique();
    foreach(q[i])
      $write("%h ", q[i]);
  end
endmodule

In the above code, I need to remove the consecutive duplicate elements (only the consecutive duplicate elements) of the dynamic array called bytes and put them in a queue called q . Also, I need to remove all the trailing 0's. I tried using unique() , but what I get is something different.

Expected output:

ee ea af af af 50 6a 0d c8 c8 21 00 00 00 00 00 00 00 00 00 00

ee ea af 50 6a 0d c8 21

Output I am getting on QuestaSim on edaplayground

ee ea af af af 50 6a 0d c8 c8 21 00 00 00 00 00 00 00 00 00 00 
 
00 0d 21 50 6a af c8 ea ee

More information:

Once it's 0, it cannot have more duplicates. Since it's a dynamic array created by reading the data values on DUT interface, last value read is the 0 and that remains at 0 unless new data.

Since its duplication is only due to the current data being held on the output interface (following some arbitartion priority, waiting for few cycles for next priority port data). and the data is constraint randomized to have unique values (data which is input to DUT).

eg. I send a,b,c,d on the input on port 3 and port 3 waits for few cycles to check is any other port is requested, hence the output may be something like a bbb cc d ( 3 cycle for b and 2 cycle for c) and the dynamic array reads this output. Removing the duplicated items is so as to compare the input and output equivalence in Scoreboard.

You can loop through the original array and only add items to the new queue when consecutive items do not match. This also removes the trailing 00 .

module tb;
  
  bit [7:0] bytes [];
  bit [7:0] q[$];
  
initial begin
    bytes = new[20];
    bytes[0] = 8'hee;
    bytes[1] = 8'hea;
    bytes[2] = 8'haf;
    bytes[3] = 8'haf;
    bytes[4] = 8'haf;
    bytes[5] = 8'h50;
    bytes[6] = 8'h6a;
    bytes[7] = 8'h0d;
    bytes[8] = 8'hc8;
    bytes[9] = 8'hc8;
    bytes[10] = 8'h21;

    $display;
    foreach (bytes[i]) $write("%h ", bytes[i]);
    $display;

    q[0] = bytes[0];
    for (int i=1; i<bytes.size(); i++) begin
        if (bytes[i] != bytes[i-1]) q.push_back(bytes[i]);
    end
    if (q[$] == 0) void'(q.pop_back());

    foreach (q[i]) $write("%h ", q[i]);
    $display;
    $display;
end

endmodule

This outputs:

ee ea af af af 50 6a 0d c8 c8 21 00 00 00 00 00 00 00 00 00 
ee ea af 50 6a 0d c8 21

Here is a demonstration on edaplayground .


Regarding the unique array method, the IEEE Std 1800-2017, section 7.12.1 Array locator methods , states:

The ordering of the returned elements is unrelated to the ordering of the original array.

Perhaps that means that the resulting order can't be guaranteed. With your code, we get mixed results on different simulators on edaplayground (original code in Question) ; some produce your desired output order, while others do not.

It seems like the order of the elements in the queue which is returned by the unique method is not defined. So, how about changing your queue to be a queue of int s:

int q[$];

and then using unique_index :

q = bytes.unique_index();

and then using the sort method on that:

q.sort();

Then the order is defined, whatever simulator you use. (And it is better to write code that works on any simulator). So, we now have a queue of indexes, which we can use to index the original array ( byte ):

foreach(q[i])
   $write("%h ", bytes[q[i]]);

This gives me this output (on Aldec Riviera Pro):

ee ea af af af 50 6a 0d c8 c8 21 00 00 00 00 00 00 00 00 00 

ee ea af 50 6a 0d c8 21 00 

https://www.edaplayground.com/x/6pV6

module tb;
  
  bit [7:0] bytes [];
  int q[$];
  
  initial begin
    bytes = new[20];
    bytes[0] = 8'hee;
    bytes[1] = 8'hea;
    bytes[2] = 8'haf;
    bytes[3] = 8'haf;
    bytes[4] = 8'haf;
    bytes[5] = 8'h50;
    bytes[6] = 8'h6a;
    bytes[7] = 8'h0d;
    bytes[8] = 8'hc8;
    bytes[9] = 8'hc8;
    bytes[10] = 8'h21;
    foreach(bytes[i])
      $write("%h ", bytes[i]);
    $display("\n");
    q = bytes.unique_index();
    q.sort();
    foreach(q[i])
      $write("%h ", bytes[q[i]]);
  end
endmodule
module duplicateremoval;
int array[] = {1, 2, 3, 4, 5, 2, 3, 4, 6, 8, 3};

int i, j, k;
  
initial begin
  for(i=0 ; i<array.size()-1 ; i=i+1)
  begin
    for(j=i+1 ; j<array.size() ; j=j+1)         //j should be one step advanced to i
          begin
               if(array[i] == array[j])
                  begin
                       for(k=j ; k<array.size() ; k=k+1)
                            begin
                                 array[k] = array[k+1];
                             end
                     j--;
                    end
               end
    $display("array[%0d]=%0d", i, array[i]);
   end
 end        
endmodule

In this code, using for loops comparing the next value with the current value. if current value is same as next value , the current value will be skipped and next value will be assigned to current value .after replace, reduce the iterator by 1,so that it will be in current position.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM