Paul
Paul

Reputation: 57

SystemVerilog how to perform one-hot masking

I have a bit array, let's say (src = 0011010). This array has (n = 3) bits set to 1.

I want to get a new array that has some of those bits still set to 1 (so, the number of bits set to 1 lies in a range 0...n). To do so, I use $urandom:

dest_rnd = $urandom() & src;

Now, I would like to create another array instead , let's call it dest_onehot, in which only 1 among the bits initially set to 1 in src stays at 1, and the others are all zero'd. And the bit that survives staying set is chosen randomly.

For example: dest_onehot = 0001000 (so, among the bits of src initially set to 1, only the 4th bit survives, and all the others get reset).

Is there a SystemVerilog way to achieve this?

Upvotes: 0

Views: 1205

Answers (2)

toolic
toolic

Reputation: 62019

Cycle through the input vector starting at a random position until a 1 bit is seen:

module tb;

bit [7:0] src = 'b0011_0100;
bit [7:0] dst;

initial begin
    bit [2:0] a;
    a = $urandom;
    while (!src[++a]);
    dst[a] = 1;

    $display("src=%08b", src);
    $display("dst=%08b", dst);
end

endmodule

Upvotes: 2

dave_59
dave_59

Reputation: 42623

Yes there is a simple way:

module top;
class A;
   int N = 3;
   rand bit [7:0] src, dst;
   constraint c { 
      $countones(src) == N;
      $countones(dst) == 1;
      src & dst;
   }
endclass
   A h = new;
   initial repeat (10) begin
      assert(h.randomize());
      $displayb("%p",h);
   end
endmodule

Upvotes: 1

Related Questions