如何为事务 class 编写约束条件,其中我只需要将 50% 的数据包随机化?

How to write constraint for a transaction class in which I need only 50% packets to be randomized?

我需要编写一个事务class,使每个数据包都有一个随机的 SA[7:0] 字段、DA[7:0] 字段和一个 DATA 字段。 数据的长度在 1 字节到 64 字节之间是随机的。 DATA 字段的内容可以是随机的(或)其他一些固定模式。50% 的数据包在所有数据字节中具有随机数据。 25% 的数据包在所有数据字节中都有 8'h55。 25% 的数据包在所有数据字节中都有 8'hAA

  class my_transaction extends uvm_sequence_item;
  'uvm_object_utils(my_transaction);

  function new(string name="my_transaction")
  super.new(name);
  endfunction

  rand bit[7:0] SA;
  rand bit[7:0] DA;
  rand bit[7:0] data[];

  constraint my_c { data.size() inside [1:64] };
  ????how to write constraint for dynamic array data[] here ??

  endclass

有两件事是你的朋友:

i) 控制旋钮。控制旋钮是为了控制随机化过程而被随机化的变量。因此,让我们随机化一个变量来决定 data 数组是随机的,55 还是 AA。

typedef enum {RANDOM, FIVE_FIVE, A_A} control_knob_t;
rand control_knob_t control_knob;

constraint dist_constraint { control_knob dist {RANDOM := 2, FIVE_FIVE := 1, A_A := 1}; }

ii) post_randomize 方法。这是 SystemVerilog,不是 UVM。 post_randomize 在 class 的随机化发生后调用,并允许您在随机化发生后执行操作。在这种情况下,我们将让标准随机化随机化 data 数组的长度,然后我们将在 post_randomize 方法中填充 data 的值。

function void post_randomize;
  case (control_knob)
    RANDOM:    foreach (data[i]) 
                 data[i] = $urandom_range(0,255);
    FIVE_FIVE: foreach (data[i]) 
                 data[i] = 8'h55;
    A_A:       foreach (data[i]) 
                 data[i] = 8'haa;
  endcase
endfunction

[MCVE] :

module M;

  class C;

    rand bit[7:0] data[];

    typedef enum {RANDOM, FIVE_FIVE, A_A} control_knob_t;
    rand control_knob_t control_knob;

    constraint my_c { data.size() inside {[1:4]}; }

    constraint dist_constraint { control_knob dist {RANDOM := 2, FIVE_FIVE := 1, A_A := 1}; }

    function void post_randomize;
      case (control_knob)
        RANDOM:    foreach (data[i]) 
                     data[i] = $urandom_range(0,255);
        FIVE_FIVE: foreach (data[i]) 
                     data[i] = 8'h55;
        A_A:       foreach (data[i]) 
                     data[i] = 8'haa;
      endcase
    endfunction

  endclass

  C c;

  initial
    begin
      c = new;
      repeat (100)
        begin
          c.randomize;
          $display("c = %p", c);
        end
    end

 endmodule

https://www.edaplayground.com/x/2cPk

我正在研究与 Matthew 类似的方法,但如果很容易避免,我不希望使用 post_randomize 进行随机化

module top;
  class A;
    rand bit[7:0] data[];      
    typedef enum {RAND, h55, hAA} knob_t;
    rand knob_t knobs[];

    constraint size_c { data.size() inside {[1:64]}; data.size == knobs.size; }

    constraint dist_c { 
      foreach(knobs[i]) knobs[i] dist {RAND := 50, h55 := 25, hAA := 25}; }
    constraint data_element_c {
      foreach (data[i]) {
        knobs[i] == h55 -> data[i] == 8'h55;
        knobs[i] == hAA -> data[i] == 8'hAA;
      } }
  endclass

  A a = new;

  initial
      repeat (10)
        begin
          assert(a.randomize);
          $display("%p", a);
        end

 endmodule