SystemVerilog的constrain的理解

我们知道virtual来修饰子函数,可以让基类的指针指向扩展类,从而利用基类中的virtual函数可以复用扩展类中的同名函数。但是constrain呢?本小结就来详细说明一下constrain。

我们通过一个例子来简单声明一下:

情况一:

    class bird;
    rand bit [1:0] src;
    rand bit [1:0] drc;
    constraint src_stim{src ==3;}
    constraint drc_stim{drc ==1;};
    endclass

    class parrot extends bird;
    constraint drc_stim{drc ==2;};
    endclass

     program ex6_14_tb;
      bird A;
      parrot B;
     
       initial begin
          A = new();
          B = new();
          assert(A.randomize());
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
          assert(B.randomize());
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
       end
      endprogram

打印结果是:
A:src=3,drc=1
B:src=3,drc=2

  • 如果B extends A的话,那么约束其实是可以重写和继承的。

情况二:

    class bird;
    rand bit [1:0] src;
    rand bit [1:0] drc;
    constraint src_stim{src ==3;}
    constraint drc_stim{drc ==1;};
    endclass

    class parrot extends bird;
    constraint drc_stim{drc ==2;};
    endclass

     program ex6_14_tb;
      bird A;
      parrot B;
     
       initial begin
          A = new();
          B = new();
          A = B;
          assert(A.randomize());
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
          assert(B.randomize());
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
       end
      endprogram

打印结果:
A:src=3,drc=2
B:src=3,drc=2

  • constrain,类似于virtual task,基类=扩展类;
  • 如果改成B = A,即扩展类=基类,那么编译就会报错!!

情况三:

    class bird;
    rand bit [1:0] src;
    rand bit [1:0] drc;
    constraint src_stim{src ==3;}
    constraint drc_stim{drc > 1;
                        drc < 6;};
    endclass

    class parrot extends bird;
    constraint drc_stim{drc ==2;};
    endclass

     program ex6_14_tb;
      bird A;
      parrot B;
     
       initial begin
          A = new();
          B = new();
    
          assert(A.randomize() with {drc ==3;});
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
          assert(B.randomize());
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
       end
      endprogram

打印结果:
A:src=3,drc=3
B:src=3,drc=2

  • randomize() with {} 是求解drc>1;drc<6;以及drc == 3的交集;

  • 如果with里面的东西与原来的约束没有交集的话,那么会显示约束求解错误。
    那么比如说我就有这样的需求呢?有两种解决方案:
    方案一:

     class bird;
      rand bit [5:0] src;
      rand bit [5:0] drc;
      constraint src_stim{src ==3;}
      constraint drc_stim{
                          drc > 1;
                          soft drc < 6;}; //******************
      endclass
    
      class parrot extends bird;
      constraint drc_stim{drc ==2;};
      endclass
    
       program ex6_14_tb;
        bird A;
        parrot B;
       
         initial begin
            A = new();
            B = new();
      
            assert(A.randomize() with {drc ==7;});
            $display("A:src=%0d,drc=%0d",A.src,A.drc);
            assert(B.randomize());
            $display("A:src=%0d,drc=%0d",A.src,A.drc);
         end
        endprogram
    

打印结果:
A:src=3,drc=7
B:src=3,drc=2

  • 用soft来修饰约束,这样当with的约束和内部约束有冲突的时候,我们是以with里面的约束为准。

方案二:

   class bird;
    rand bit [5:0] src;
    rand bit [5:0] drc;
    constraint src_stim{src ==3;}
    constraint drc_stim{
                        drc > 1;
                        drc < 6;};
    endclass

    class parrot extends bird;
    constraint drc_stim{drc ==2;};
    endclass

     program ex6_14_tb;
      bird A;
      parrot B;
     
       initial begin
          A = new();
          B = new();
          A.drc_stim.constraint_mode(0); //*****************//
          assert(A.randomize() with {drc ==7;});
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
          assert(B.randomize());
          $display("A:src=%0d,drc=%0d",A.src,A.drc);
       end
      endprogram

打印结果:
A:src=3,drc=7
B:src=3,drc=2

  • constraint_mode来关闭对应的约束,然后with里面的约束是最终的约束。

如果大家依次把这些code敲一遍的话,你就会发现每次随机的值都是一样的,为什么呢?因为new(),以后seed的默认值都是1。所以必须要用+ntb_random_seed=value or by +ntb_random_seed_automatic来设置seed.通过下面的例子来进行分析。

摘自VCS_userguid-----$get_initial_random_seed(用于get随机种子的值)
Returns the integer number used as the seed for a simulation run, if the seed was set by +ntb_random_seed=value or by +ntb_random_seed_automatic or returns the default random seed value if the seed was not set using one of those two options. The default random seed value is 1.

posted on 2021-05-15 17:50  猪肉白菜_125  阅读(1025)  评论(0编辑  收藏  举报