$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)產生不一樣的隨機數序列