Complex randomization constraint

I have a 32-bit source select line which is encoded using one-hot encoding.

Every 4 bit nibble is the select line of a different output, and can get only the values 0,1,2,4,8 (since it is one-hot)
In the module 4 inputs are multiplexed to 8 outputs.

Since 1 input cannot be directed to multiple outputs I need to create a constraint that will force 1,2,4 and 8 occur once or none at all, and other nibbles will be set to 0.

I thought to create a nibbles vector and randomize each element and concatenate it to my target register in post_randomization phase.

Does someone know what is the best solution to my situation?

class ciif_sync_test_config extends uvm_object;
   
    // Test fields
    bit [8*4-1:0]       ipe_stream_src_sel;
    rand bit [3:0]      src_sel[8];

    constraint src_sel_c
    {
        foreach(src_sel[i])
            src_sel[i] inside {0,1,2,4,8};
                      // dist {0 := 5, 1 := 1, 2 := 1, 4 := 1, 8 := 1};

    };

    function void post_randomize();
        ipe_stream_src_sel = {src_sel[7], src_sel[6], src_sel[5], src_sel[4], src_sel[3], src_sel[2], src_sel[1], src_sel[0]};
    endfunction

endclass // inu_ciif_config

In reply to chenm:

In reply to chenm:

A dist constraint is a statistical distribution and not a hard constraint. You can use the sum reduction method to constrain that an output appears at most once.

module top;
  class test;
    // Test fields
    rand bit [8*4-1:0]       ipe_stream_src_sel;
    rand bit [3:0]      src_sel[8];
    const bit [3:0] one_hot[] = {0,1,2,4,8};
 
    constraint src_sel_c {
      foreach(src_sel[i]) {
        src_sel[i] inside {one_hot};
        ipe_stream_src_sel[i+:4] == src_sel[i]; // use instead of post_randomize
      }
      foreach(one_hot[sel])
        sel != 0 -> src_sel.sum() with ( int'(item==one_hot[sel]) ) <= 1;
    }
  endclass : test
   
  test t = new;
  initial repeat (5) begin
    assert(t.randomize);
    $displayh("%p",t);
  end
endmodule

In reply to chenm:

assuming I got It properly is this what you are looking for?


class ciif_sync_test_config;

  // Test fields
  bit [31:0] ipe_stream_src_sel;
  rand bit [3:0] r_src_sel[8];
  bit [3:0] src_sel[8];
  
  constraint src_sel_c {
    unique {r_src_sel};
    foreach(r_src_sel[i]){
      r_src_sel[i] <= 8};}
  
  function void post_randomize();
    foreach(r_src_sel[jj]) begin
      if(r_src_sel[jj] inside {0,1,2,4,8})
        src_sel[jj] = r_src_sel[jj];
      else src_sel[jj] = 0;
    end
  endfunction

  function void print();
    foreach(src_sel[ii]) begin
      $display("ciif_sync_test_config: value of src_sel[%0d] is: %0h",ii,src_sel[ii]);
    end
  endfunction

endclass // inu_ciif_config

correct me if I not properly got it