systemverilog 隨機化操作


在進行驗證已編寫過的模塊時,我們往往需要一些隨機的測試方法來檢測隱藏的漏洞。

sv相比於verilog而言,在隨機化上則是非常有力,有許多關於隨機化的操作。

===================================================

一 隨機數據:

一般而言隨機化的操作都是需要封裝成為類的。

class Bus;
    rand  bit[15:0] addr;
    rand  bit[31:0] data;
    constraint word_align {addr[1:0] == 2’b0;}
endclass

這是個簡單的例子,只要在類的數據類型前加上了rand或者randc,那么只要對這個類的實例化

對象調用randomize()方法,這些帶有rand與randc的數據類型則是會被隨機化。

但往往隨機化並非完全的隨機化,很多時候需要有一定的限制,所以還需要使用constraint語句

構造約束條件。

其中約束有很多種:

(1)表達式約束:

constraint word_align {addr[1:0] == 2’b0;   data < 32 }

(2)條件約束:

class MyBus extends Bus;
    rand AddrType atype;
    constraint addr_range
   {
        (atype == low ) -> addr inside { [0 : 15] };
        (atype == mid ) -> addr inside { [16 : 127]};
        (atype == high) -> addr inside {[128 : 255]};
        //   (  先前的條件 )-> (相應的約束)
   }
endclass

條件約束可以使用->的方式也可以使用if-else的方式。只有當先前的條件滿足時才可以進行后面的約束。

(3)嵌套約束:

task    exercise_bus (MyBus bus);
    int  res;
    // EXAMPLE 1: restrict to low addresses 
    res = bus.randomize() with {atype == low;}; 
    // EXAMPLE 2: restrict to address between 10 and 20
    res = bus.randomize() with {10 <= addr && addr <= 20;};
   // EXAMPLE 3: restrict data values to powers-of-two
    res = bus.randomize() with {data & (data - 1) == 0;};
endtask

在randomize()方法后使用with { } 加入約束的條件。

(4)權重約束:

x dist { [100:102] := 1, 200 := 2, 300 := 5}   //    其中在:=前的每個元素的權重值都為:=后的值
x dist { [100:102] :/ 1, 200 :/ 2, 300 :/ 5}     //    其中在:/前的每個元素平分:/后的權重值

二 隨機序列:

 

randsequence ( main )
main     : first second done ;   //   從main處順序執行 first second done
first    : add | dec ;           //   執行add  或者 dec
second    : pop | push ;
done     : { $display("done"); } ;
add      : { $display("add");  } ;
dec      : { $display("dec");  } ;
pop      : { $display("pop");  } ;
push     : { $display("push"); } ;
endsequence

三 決策樹:

randcase
    3 : x = 1;     //    :前的值為相應的權重
    1 : x = 2;
    4 : x = 3;
    6 : randcase 
            4 :  x = 4 ;
            5 :  x = 5 ;
        endcase
endcase


CONTRAINT 約束

本篇主要介紹一些 systemverilog 中的 constraint。

我們可以用> < >= <=等符號來對變量進行簡單的約束, 注意的是當要把某個變量設為定值時, 需要使用==符號。

比如下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class myClass;
rand bit [3:0] min, typ, max;
rand bit [3:0] fixed;
constraint my_range { 3 < min;
typ < max;
typ > min;
max < 14; }
constraint c_fixed { fixed == 5; }
function string display ();
return $sformatf ("min=%0d typ=%0d max=%0d fixed=%d", min, typ, max, fixed);
endfunction
endclass
module tb;
initial begin
for (int i = 0; i < 10; i++) begin
myClass cls = new ();
cls.randomize();
$display ("itr=%0d %s", i, cls.display());
end
end
endmodule

那么運行的結果就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
 source ../edaTools/cadence/INCISIV131/tools/inca/files/ncsimrc
run
itr=0 min=5 typ=6 max=7 fixed= 5
itr=1 min=5 typ=7 max=13 fixed= 5
itr=2 min=7 typ=11 max=12 fixed= 5
itr=3 min=4 typ=10 max=13 fixed= 5
itr=4 min=6 typ=8 max=13 fixed= 5
itr=5 min=4 typ=8 max=11 fixed= 5
itr=6 min=5 typ=10 max=11 fixed= 5
itr=7 min=4 typ=8 max=12 fixed= 5
itr=8 min=4 typ=8 max=10 fixed= 5
itr=9 min=4 typ=12 max=13 fixed= 5
ncsim: *W,RNQUIE: Simulation is complete.

 

2. inside 表達式

(1) 也可以使用inside關鍵字申明變量的范圍或者申明變量只能取某些特定的值, 比如:

1
2
3
4
5
6
7
constraint my_range { typ > 32;
typ < 256; }

constraint new_range { typ inside {[32:256]}; }

// Choose from the following values
constraint spec_range { type inside {32, 64, 128}; }

(2) 如果加上符號!表示變量不在某個范圍內

1
2
rand bit [2:0] typ;
constraint inv_range { ! (typ inside {[3:6]}); }

 

3. 權重分布

當在隨機化變量的時候, 需要某些值出現的更加頻繁一些。 就可以用關鍵字dist進行權重的約束。

:=表示的是, 對於指定范圍的值, 權重都一樣, 比如 [1:5]:=50;表示的是 [1:5] 范圍的任何一個值, 其權重都是 50;

:/表示的是, 對於指定范圍的值, 權重均分, 比如 [1:5]:=50;表示的是 [1:5] 范圍的任何一個值, 其權重都是 10;

1
2
rand bit [2:0] typ;
constraint dist1 { typ dist { 0:=20, [1:5]:=50, 6:=40, 7:=10}; }

上面約束表示的含義是: 0 的權重是 20, 6 是 40, 7 是 10, 1:5 中的每個數都是 50. 總共 320, 那么選擇 0 的概率就是 20/320

1
2
rand bit [2:0] typ;
constraint dist2 { typ dist { 0:/20, [1:5]:=50, 6:/10, 7:/20}; }

這個約束表示的含義就不同了, 選中 0 的概率就是 20/100

 

4. 多重約束

多重約束存在時, 取的是交集:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class myClass;
rand bit [3:0] val;
constraint c1 { val > 3;
val < 12; }

constraint c2 {val >= 10; }
endclass

module tb;
initial begin
for (int i = 0; i < 10; i++) begin
myClass cls = new ();
cls.randomize();
$display ("itr=%0d typ=%0d", i, cls.val);
end
end
endmodule

比如上面的例子, val 的值被約束在了 [10, 12)

 

5. implication 約束

implication 約束使用的符號是->, 代表的是某兩個或者多個變量之間的關系。 有些類似於if - else申明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ABC;
rand bit [3:0] mode;
rand bit mod_en;

// If 5 <= mode <= 11, mod_en should be 1
constraint c_mode { mode inside {[4'h5:4'hB]} -> mod_en == 1; }

endclass

module tb;
initial begin
ABC abc = new;
for (int i = 0; i < 10; i++) begin
abc.randomize();
$display ("mode=0x%0h mod_en=0x%0h", abc.mode, abc.mod_en);
end
end

endmodule

上面例子的運行結果為:

1
2
3
4
5
6
7
8
9
10
11
12
ncsim> run
mode=0xf mod_en=0x1
mode=0x9 mod_en=0x1
mode=0x3 mod_en=0x1
mode=0xe mod_en=0x1
mode=0x1 mod_en=0x1
mode=0x0 mod_en=0x0
mode=0x1 mod_en=0x0
mode=0xe mod_en=0x0
mode=0x5 mod_en=0x1
mode=0x0 mod_en=0x0
ncsim: *W,RNQUIE: Simulation is complete.
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM