可以產生受約束的隨機激勵是sv驗證語言中最主要的feature,這里有一個常常會被驗證工程師忽視的問題,就是隨機化種子(seed)。
我們知道,用verilog里面的$random或者sv里面的$urandom產生的都只是偽隨機數,也就是說,如果不改變seed,每次仿真產生的隨機數都一樣。
sv的受約束的隨機化方法與上述情況其實也有點相同。sv中,每個對象維持自身的內部RNG,排他地用於randomize()方法,這使得對象的隨機化保持各自獨立。當生成對象時,創建它的線程的RNG的下一個值被用於設置成它的RNG的隨機化種子。此時對象的new函數()默認的seed為1,如果不改變seed的值,則每次run仿真時,仍舊會產生相同的激勵數據。
因此,我們需要手動設置new()函數中的隨機化seed,使得每次run仿真時可以得到真正意義上的隨機激勵。
手動設置對象RNG的隨機化seed的方法是:使用srandom()將種子傳給隨機的變量seed,這能確保在任意類成員變量被randomize之前,為對象的RNG設置新的隨機化seed。舉例如下:
1 class Packet;
2 rand bit[15:0] header;
3 ...
4 function new (int seed);
5 this.srandom(seed);
6 ...
7 endfunction
8 endclass
這樣,我們便從外部對RNG設置新的隨機化seed了:
1 Packet p = new(200); //create p with seed 200.
2 p.srandom(300); //re-seed p with seed 300.
實際代碼中,我們可以將seed宏定義為不同的值,還可以使用系統時間作為seed,我們先定義變量seed:
1 module test ;
2 integer seed ;
3 initial begin
4 if(!$value$plusargs("seed=%d",seed))
5 seed = 10 ;
6 ...
7 end
8 endmodule
使用仿真命令即可將系統時間作為seed:
vcs -R test.v +plusargs_save +seed=`date +%N
另外一種經常用到的方法是只需在仿真命令中加入+ntb_random_seed_automatic,代碼中不需要出現變量seed,只需要有隨機約束:
1 `timescale 1ns/1ns
2 program test ;
3 integer i ;
4 class rc ;
5 rand int a ;
6 constraint con {a >0;}
7 endclass
8
9 initial begin
10 rc ua = new();
11 for(i=0;i<10;i++) begin
12 ua.randomize();
13 $display("%d",ua.a);
14 end
15 $display("%d",$urandom);
16 end
17 endprogram
仿真命令如下:
vcs -sverilog -R test.sv +plusarg_save +ntb_random_seed_automatic
最后,說點一家之言,僅供參考。
個人認為做隨機化的時候,最好能使用一個file來記錄之前每次你使用過的seed,原因是你可以在每次run仿真之前都把當前你設置的seed和file里記錄的之前的所有seed比較,若不一樣就可以用了,以此讓隨機性更加隨機;此外,保存下來的seed,可以使仿真重現,便於debug。