總結verilog產生隨機數的$random和seed

 

 

$random(seed)是verilog中最簡單的產生隨機數的系統函數。dom

 

在調用系統函數$random(seed)時,能夠寫成三種樣式:1)$random,2)$random(),3)$random(seed)。下面分別說明:函數

1)$randomspa

這是最簡單的一種寫法,略去了seed這個傳入參數,$random會使用一個默認的seed(這個默認值爲0?)。也正所以,每次進行仿真時,$random產生的隨機數序列都是相同的。get

2)$random()it

這種寫法和寫法1)的做用是相同的,一樣是沒有給$random傳入seed。編譯

3)$random(seed)class

這種寫法與上面兩種不一樣,給$random傳入了參數seed,所以$random根據seed來產生隨機數。seed不一樣,產生的隨機數的序列也不一樣。並且,每執行一次$random(seed)產生一個隨機數,seed也自動更新一次。變量

 

下面討論seed的產生。隨機數

據我有限的知識,seed有兩種產生方式:4)直接賦值爲一個肯定數,5)利用系統函數$get_initial_random_seed得到值。下面分別討論:sed

4)直接賦值

在一個initial塊中直接將seed變量寫成某值,以下面代碼:

integer seed;

reg [7:0] rand_num;

initial  begin seed = 0; end

always @(posedge clk) begin rand_num <= $random(seed); end

在上面代碼中,seed初始值被賦爲0(也能夠是1或其它數),在第一個時鐘上升沿,rand_num取得的第一個隨機數就是$random(0)產生的,seed也隨即更新;在第二個時鐘上升沿時,rand_num取得第二個隨機數,是$random(更新後的seed)產生的,seed又隨即更新;如此下去。

值得注意的是,若是把seed賦值爲0,那麼利用$random(seed)產生的隨機數序列和直接執行$random產生的隨機數序列是相同的。這個結論是我根據經驗得出的。

5)seed = $get_initial_random_seed()

以下面代碼:

integer seed;

reg [7:0] rand_num;

initial  begin seed = $get_initial_random_seed(); end

always @(posedge clk) begin rand_num <= $random(seed); end

在上面代碼中,利用系統函數獲得的seed的值是1,此後seed更新後的值和$random(seed)產生的隨機數序列都和將seed直接賦值成1,利用$random(seed)產生隨機數的狀況相同。這也是我根據經驗得出的結論。

我在網上沒有找到關於$get_initial_random_seed的詳細介紹。

 

下面討論仿真時如何改變seed的初值:

若是seed的初值是肯定的,那麼不論進行多少次仿真,產生的隨機數的序列老是肯定的,就不能覆蓋更多的狀況。所以在仿真時,要可以改變seed的初值。目前我所知道的改變seed的初值有兩種方法:6)修改代碼;7)採用deposit方式。下面分別介紹:

6)修改代碼

這種方式最直接,缺點是每次要修改seed時都須要從新編輯一遍代碼。

好比,第一次仿真時,代碼寫成下面的樣子:

integer seed;

reg [7:0] rand_num;

initial  begin seed = 0; end

always @(posedge clk) begin rand_num <= $random(seed); end

而第二次仿真時,想修改seed的初值,就寫成下面的樣子:

integer seed;

reg [7:0] rand_num;

initial  begin seed = 1; end

always @(posedge clk) begin rand_num <= $random(seed); end

7)採用deposit的方式

這種方式比較靈活,沒必要修改代碼,也沒必要從新編譯,直接修改輸入到仿真軟件的命令便可。

下面是最簡單的一個命令:

deposit top.seed 2

run 125ns

exit

上面命令的意思是,將信號(或變量)seed的初值設成1,而後開始仿真,仿真時間爲125ns,而後結束仿真。

deposit是在仿真開始以前起做用的(若是沒有給deposit加上其它時間方面的條件),並且它只是將某個信號的初始值設爲某一個數(能夠是肯定數,也能夠是隨機數),此後便再也不干預該信號的值。若是仿真開始後有別的條件或語句改變該變量的值,則該變量就變成改變後的值。

若是代碼按下面的樣子寫:

integer seed;

reg [7:0] rand_num;

initial  begin seed = 1; end

always @(posedge clk) begin rand_num <= $random(seed); end

咱們來看一下,在仿真開始以前deposit將seed賦值爲2,然而仿真開始後的0ns時刻,initial塊又將seed賦爲1,所以至關於deposit沒有起到預期的做用。咱們想要的是,seed的初值爲2,$random(2)產生一個隨機數後,seed再由2變成其它的數;而不是$random(1)產生一個隨機數,而後seed又由1變成其它的數。

爲了達到咱們的預期目的,要把deposit命令改爲下面的樣子:

deposit top.seed 2 -after 1ns

run 125ns

exit

在仿真開始的0ns時,initial塊執行,將seed設爲1。加上"-after 1ns"後,deposit命令就會在仿真開始後的1ns時起做用,把seed的值改成2,而後做用於第一次$random(seed)的執行,而後seed再更新。

 

綜上討論,我得出如下結論:

1. 利用$random產生隨機數時最好利用上seed參數,即寫成$random(seed)樣式。

2. 沒有必要利用$get_initial_random_seed()函數給seed賦值,直接寫成一個值便可,像4)同樣。

3. 建議用deposit的方式在仿真時改變seed的初值,使$random(seed)產生不一樣的隨機數序列

相關文章
相關標籤/搜索