Verilog 中使用系統(tǒng)任務(wù) ?$random
?(seed) 產(chǎn)生隨機數(shù),seed 為隨機數(shù)種子。
seed 值不同,產(chǎn)生的隨機數(shù)也不同。如果 seed 相同,產(chǎn)生的隨機數(shù)也是一樣的。
可以為 seed 賦初值,也可以忽略 seed 選項,seed 默認初始值為 0。
不使用 seed 選項和指定 seed 并對其修改來調(diào)用 ?$random
? 的代碼如下所示:
//seed var
integer seed ;
initial begin
seed = 2 ;
#30 ;
seed = 10 ;
end
//no seed
reg [15:0] randnum_noseed ;
always@(posedge clk) begin
randnum_noseed <= $random(); //不指定隨機種子
end
//with seed
reg [15:0] randnum_wtseed ;
always@(posedge clk) begin
randnum_wtseed <= $random(seed); //指定隨機種子
end
仿真波形圖如下。
無論是否賦初值,每產(chǎn)生一次隨機數(shù)后,seed 值改變,隨機數(shù)也隨之改變。
每改變一次 seed 值,當(dāng)前輸出的隨機值會改變;但是下一個狀態(tài)時,隨機數(shù)的走向又恢復(fù)成系統(tǒng)內(nèi)部產(chǎn)生的隨機序列。
例如仿真圖中 t1 和 t2 時刻隨機種子不同,產(chǎn)生是隨機數(shù)也不同。但是其他時鐘周期,產(chǎn)生的隨機數(shù)都是相同的。
建議調(diào)用系統(tǒng)任務(wù) ?$random
? 時,不指定 seed 選項,或指定 seed 選項時使用變量傳遞參數(shù)。
不建議調(diào)用 ?$random
? 時,將常數(shù)項寫到 seed 參數(shù)處。此時 seed 值被固定,可能只會產(chǎn)生一個隨機數(shù)。例如以下寫法是不建議的:
randnum_wtseed <= $random(2); //不建議將常數(shù)項指定給 seed
可以使用取余的方法,將隨機數(shù)限定在一定的數(shù)據(jù)范圍內(nèi)。例如:
//with a range
parameter MAX_NUM = 512;
parameter MIN_NUM = 256;
reg [15:0] num_range1, num_range2, num_range3 ;
always@(posedge clk) begin
//產(chǎn)生的隨機數(shù)范圍為 -511 ~ 511, ±(MAX_NUM-1)
num_range1 <= $random() % MAX_NUM;
//產(chǎn)生的隨機數(shù)范圍為 0 ~ 511, (0 ~ MAX_NUM-1)
num_range2 <= {$random()} % MAX_NUM;
//產(chǎn)生的隨機數(shù)范圍為 MIN_NUM ~ MAX_NUM,包含邊界
num_range3 <= MIN_NUM + {$random()} % (MAX_NUM-MIN_NUM+1);
end
隨機數(shù)按照有符號、十進制格式顯示,前幾個數(shù)據(jù)結(jié)果如下:
Verilog 提供了許多按一定概率分布產(chǎn)生數(shù)據(jù)的系統(tǒng)任務(wù),簡單描述如下:
系統(tǒng)任務(wù) | 調(diào)用格式 | 任務(wù)描述 |
---|---|---|
均勻分布 | $dist_uniform(seed, start, end); | start、end 為數(shù)據(jù)的起始、結(jié)尾 |
正態(tài)分布 | $dist_normal (seed, mean, std_dev); | mean 為期望值,std_dev 為標(biāo)準(zhǔn)差 |
泊松分布 | $dist_poisson(seed, mean); | mean 為期望 (等于標(biāo)準(zhǔn)差) |
指數(shù)分布 | $dist_exponential(seed , mean); | mean 為單位時間內(nèi)事件發(fā)生的次數(shù) |
卡方分布 | $dist_chi_square(seed, free_deg); | free_deg 為自由度 |
t 分布 | $dist_t(seed, free_deg); | free_deg 為自由度 |
埃爾朗分布 | $dist_erlang(seed, k_stage, mean); | k_stage 為階數(shù),mean 為期望 |
均勻分布在等長區(qū)間上的取值概率是相同的。
概率密度函數(shù)及概率分布圖如下所示:
其實,系統(tǒng)任務(wù) ?$random
? 實現(xiàn)的就是均勻分布。
調(diào)用 ?$dist_uniform
? 在(256,512)區(qū)間上產(chǎn)生均勻分布數(shù)據(jù)的代碼如下:
//2.1 uniform dis
reg [15:0] data_uniform;
always@(posedge clk) begin //在 MIN_NUM ~ MAX_NUM 產(chǎn)生隨機數(shù)
data_uniform <= $dist_uniform(seed_dis, MIN_NUM, MAX_NUM);
end
正態(tài)分布數(shù)學(xué)期望為 μ,標(biāo)準(zhǔn)差為 σ,記做 N (μ, σ2)。
數(shù)學(xué)期望為 0、標(biāo)準(zhǔn)差為 1 的正態(tài)分布稱為標(biāo)準(zhǔn)正態(tài)分布。
正態(tài)分布曲線呈鐘型,兩邊低,中間高,左右對稱。
正態(tài)分布概率密度函數(shù)及分布圖如下所示:
調(diào)用 ?$dist_normal
? 產(chǎn)生期望為 0、標(biāo)準(zhǔn)差為 1 的標(biāo)準(zhǔn)正態(tài)分布數(shù)據(jù)的代碼如下:
//2.2 normal dis
reg [15:0] data_normal;
always@(posedge clk) begin //期望為0、標(biāo)準(zhǔn)差為1 的標(biāo)準(zhǔn)正態(tài)分布
data_normal <= $dist_normal(seed_dis, 0, 1);
end
泊松分布用于描述某個時間或空間范圍內(nèi),某事件發(fā)生 X 次的概率。
泊松分布的數(shù)學(xué)期望和標(biāo)準(zhǔn)差相同,均為 λ,其概率密度函數(shù)及分布圖如下所示:
調(diào)用 ?$dist_poisson
? 產(chǎn)生期望為 4 的泊松分布數(shù)據(jù)的代碼如下:
//2.3 poisson dis
reg [15:0] data_poisson;
always@(posedge clk) begin
data_poisson <= $dist_poisson(seed_dis, 4);
end
指數(shù)分布用以描述泊松過程中隨機事件發(fā)生的時間間隔的概率。泊松過程即事件以恒定的平均速率連續(xù)且獨立地發(fā)生的過程。例如等公交車時兩輛車到來的時間間隔,就符合指數(shù)分布。
設(shè) λ>0 為單位時間內(nèi)事件發(fā)生的次數(shù)(又稱為率參數(shù)),x 為事件發(fā)生的時間間隔,則其概率密度函數(shù)及分布圖如下所示:
調(diào)用 ?$dist_exponential
? 產(chǎn)生率參數(shù)為 1 的指數(shù)分布數(shù)據(jù)的代碼如下:
//2.4 exp dis
reg [15:0] data_exp;
always@(posedge clk) begin
data_exp <= $dist_exponential(seed_dis, 1);
end
n 個服從標(biāo)準(zhǔn)正態(tài)分布的隨機變量的平方和構(gòu)成新的隨機變量的分布規(guī)律稱為卡方分布,記做,其中 n 稱為自由度。
卡方分布概率密度函數(shù)及分布圖如下所示:
調(diào)用 ?$dist_chi_square
? 產(chǎn)生自由度為 6 的卡方分布數(shù)據(jù)的代碼如下:
//2.5 chi-square dis
reg [15:0] data_chi_sq;
always@(posedge clk) begin
data_chi_sq <= $dist_chi_square(seed_dis, 6);
end
假設(shè) X 服從標(biāo)準(zhǔn)正態(tài)分布 N (0, 1),Y 服從卡方分布的分布稱為自由度為 n 的 t 分布,記為 Z ~ t(n) 。
t 分布用于根據(jù)小樣本來估計呈正態(tài)分布且方差未知的數(shù)據(jù)變量總體的均值。如果樣本數(shù)量足夠多且總體方差已知,則應(yīng)該用正態(tài)分布來估計總體均值。
t 分布是對稱的鐘形分布,與正態(tài)分布類似,但尾部較重,這意味著它更容易產(chǎn)生遠低于平均值的值。其概率密度函數(shù)及分布圖如下所示:
調(diào)用 ?$dist_t
? 產(chǎn)生自由度為 5 的 t 分布數(shù)據(jù)的代碼如下:
//2.6 t dis
reg [15:0] data_t;
always@(posedge clk) begin
data_t <= $dist_t(seed_dis, 5);
end
設(shè)參數(shù)為 λ 泊松過程 V1, V2, ..., V3, Vn 相互獨立,N (t) 表示 [0, t) 內(nèi)隨機點出現(xiàn)的個數(shù),則 N (t) = V1 + V2 + ... + Vn 的分布稱為 Erlang 分布。
Erlang 分布與指數(shù)分布一樣,多用來表示獨立隨機事件發(fā)生的時間間隔。遵循 Erlang 分布的隨機變量可以被分解為多個相同參數(shù)的指數(shù)分布的隨機變量之和,使得 Erlang 分布被廣泛應(yīng)用于可靠性理論和排隊論中。
Erlang 分布概率密度函數(shù)及分布圖如下所示:
Why The Face? 你竟然拿這樣的水果 idea 來充數(shù) Erlang 分布?
上述概率分布任務(wù)都只列舉了調(diào)用方法,并沒有對數(shù)據(jù)進行分析驗證。下面有介紹借助 Matlab 畫圖工具,自己動手去分析概率分布任務(wù) ?$dist_erlang
? 所產(chǎn)生數(shù)據(jù)的特性。
調(diào)用 ?$dist_erlang
? 產(chǎn)生階數(shù)為 3、期望為 6 的 Erlang 分布數(shù)據(jù)的代碼如下:
//2.7 Erlang dis
reg [15:0] data_erlang;
always@(posedge clk) begin
data_erlang <= $dist_erlang(seed_dis, 3, 6);
end
現(xiàn)實證明,還是熟知的分布數(shù)據(jù)分析起來比較方便。一些平臺關(guān)于 Erlang 分布相關(guān)的可參考性集成函數(shù)是少之又少。明知沒有愛(爾朗),偏向愛而行!
首先,在 Verilog 模型中產(chǎn)生 4 組服從 Erlang 分布的數(shù)據(jù),并打印到文件中。
//generating data file of Erlang dis
integer fd1, fd2, fd3, fd30 ;
initial begin
fd1 = $fopen("data_erlang1.hex", "w");
fd2 = $fopen("data_erlang2.hex", "w");
fd3 = $fopen("data_erlang3.hex", "w");
fd30 = $fopen("data_erlang30.hex", "w");
repeat(1000) begin //取1000個數(shù)據(jù)分析
@(posedge clk) ;
#1 ;
$fdisplay(fd1, "%h", data_erlang1);
$fdisplay(fd2, "%h", data_erlang2);
$fdisplay(fd3, "%h", data_erlang3);
$fdisplay(fd30, "%h", data_erlang30);
end
$fclose(fd1);
$fclose(fd2);
$fclose(fd3);
$fclose(fd30);
end
reg [15:0] data_erlang1;
reg [15:0] data_erlang2;
reg [15:0] data_erlang3;
reg [15:0] data_erlang30;
always@(posedge clk) begin
data_erlang1 <= $dist_erlang(seed_dis, 1, 6);
data_erlang2 <= $dist_erlang(seed_dis, 2, 6);
data_erlang3 <= $dist_erlang(seed_dis, 3, 6);
data_erlang30 <= $dist_erlang(seed_dis, 30, 6);
end
Matlab 中可以使用柱狀圖函數(shù) hist 直接對各個數(shù)據(jù)進行統(tǒng)計畫圖顯示,但對于概率分布情況該函數(shù)實際畫圖效果并不是很好(歡迎提供良好的畫圖方法)。這里使用 Matlab 數(shù)量統(tǒng)計函數(shù) tabulate 對各個數(shù)據(jù)進行統(tǒng)計,然后使用普通畫圖函數(shù) plot 顯示其百分比。
Matlab 讀取 Verilog 模塊產(chǎn)生的數(shù)據(jù)并對其進行分布圖顯示的代碼如下。
clear all;close all;clc;
%=======================================================
% data analysis from $dist_erlang in Verilog
%=======================================================
%按字符串讀取,再進行十六進制到十進制的轉(zhuǎn)換
data_erlang1_hex = textread('data_erlang1.hex', '%s') ;
data_erlang2_hex = textread('data_erlang2.hex', '%s') ;
data_erlang3_hex = textread('data_erlang3.hex', '%s') ;
data_erlang30_hex = textread('data_erlang30.hex', '%s') ;
data_erlang1 = hex2dec(data_erlang1_hex);
data_erlang2 = hex2dec(data_erlang2_hex);
data_erlang3 = hex2dec(data_erlang3_hex);
data_erlang30 = hex2dec(data_erlang30_hex);
%統(tǒng)計數(shù)據(jù)數(shù)量,并畫圖顯示
num_erlang1 = tabulate(data_erlang1) ;
num_erlang2 = tabulate(data_erlang2) ;
num_erlang3 = tabulate(data_erlang3) ;
num_erlang30 = tabulate(data_erlang30) ;
figure; plot(num_erlang1(:,1)/6, num_erlang1(:,3));
hold on; plot(num_erlang2(:,1)/6, num_erlang2(:,3), 'r');
hold on; plot(num_erlang3(:,1)/6, num_erlang3(:,3), 'g');
hold on; plot(num_erlang30(:,1)/6, num_erlang30(:,3), 'y');
legend('n=1', 'n=2', 'n=3', 'n=30');
Verilog 模型產(chǎn)生的 Erlang 數(shù)據(jù)分布圖如下所示。
千萬要注意的是,λ 參數(shù)是泊松分布的期望,而不是 Erlang 分布的期望。
Verilog 系統(tǒng)任務(wù) ?$dist_erlang(seed, k_stage, mean)
? 中第三個參數(shù)為期望值。如果直接將期望值帶入到 λ 參數(shù),將得到錯誤的分布結(jié)果。
下面簡(偷)單(懶)推(參)導(dǎo)(考)下 Erlang 分布的數(shù)學(xué)期望。
附 Erlang 分布方差的推導(dǎo)過程。
使用 Matlab 內(nèi)置函數(shù) random,可以產(chǎn)生多種類型的分布數(shù)據(jù),然而偏偏沒有 Erlang 分布。
下面利用概率密度分布函數(shù)產(chǎn)生服從 Erlang 分布的數(shù)據(jù)。
其中,Verilog 模型中期望值為 6,則實際參數(shù) λ = n/6 。
Matlab 產(chǎn)生 Erlang 分布數(shù)據(jù)的代碼如下。
clear all;close all;clc;
%=======================================================
% generating data of Erlang distribution
%=======================================================
NUM = 400 ;
EXPECT = 6 ;
for n=[1, 2, 3, 30] //產(chǎn)生4組數(shù)據(jù)
lamda = n/EXPECT; //期望值轉(zhuǎn)換
t = (0:NUM-1)*0.1 ;
pt(n,:) = (lamda).^n *(t).^(n-1)/factorial(n-1) .* exp(-lamda * t) ;
end
figure; plot(t, pt(1,:)*100);
hold on;plot(t, pt(2,:)*100, 'r');
hold on;plot(t, pt(3,:)*100, 'g');
hold on;plot(t, pt(n,:)*100, 'y');
xlabel('t');
ylabel('f(t) / 100%');
legend('n=1', 'n=2', 'n=3', 'n=30');
Matlab 產(chǎn)生 Erlang 的數(shù)據(jù)分布圖如下所示。
對比 Verilog 模型產(chǎn)生的數(shù)據(jù),兩者的分布區(qū)間、分布概率及分布曲線走勢基本是一致的。只是 Verilog 中產(chǎn)生的是時間間隔較大的數(shù)據(jù),分布圖不是平滑的曲線。
點擊這里下載源碼
更多建議: