7.3 Verilog Random Numbers and Probability Distributions
Category Verilog Tutorial Advanced
Random Numbers
In Verilog, random numbers are generated using the system task $random(seed), where seed is the random number seed.
Different seed values produce different random numbers. If the seed is the same, the generated random numbers are also the same.
You can assign an initial value to the seed or omit the seed option, which defaults to an initial value of 0.
Examples of calling $random without using the seed option and modifying the seed are shown below:
Example
//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(); //no specified random seed
end
//with seed
reg [15:0] randnum_wtseed;
always@(posedge clk) begin
randnum_wtseed <= $random(seed); //specified random seed
end
The simulation waveform is as follows.
Regardless of whether an initial value is assigned, the seed value changes after each random number generation, and the random number also changes accordingly.
Every time the seed value is changed, the current output random value changes; however, in the next state, the direction of the random number reverts to the random sequence generated internally by the system.
For example, in the simulation diagram, the random seeds at times t1 and t2 are different, resulting in different random numbers. However, in other clock cycles, the generated random numbers are the same.
It is recommended to call the system task $random without specifying the seed option, or to use a variable to pass parameters when specifying the seed option.
It is not recommended to write a constant to the seed parameter when calling $random. In this case, the seed value is fixed, and only one random number may be generated. For example, the following writing method is not recommended:
randnum_wtseed <= $random(2); //it is not recommended to specify a constant to the seed
You can use the modulo operation to limit the random number within a certain data range. For example:
Example
//with a range
parameter MAX_NUM = 512;
parameter MIN_NUM = 256;
reg [15:0] num_range1, num_range2, num_range3;
always@(posedge clk) begin
//the range of the generated random number is -511 ~ 511, ±(MAX_NUM-1)
num_range1 <= $random() % MAX_NUM;
//the range of the generated random number is 0 ~ 511, (0 ~ MAX_NUM-1)
num_range2 <= {$random()} % MAX_NUM;
//the range of the generated random number is MIN_NUM ~ MAX_NUM, including boundaries
num_range3 <= MIN_NUM + {$random()} % (MAX_NUM-MIN_NUM+1);
end
Random numbers are displayed in signed, decimal format, and the first few data results are as follows:
Probability Distributions
Verilog provides many system tasks to generate data according to certain probability distributions, briefly described as follows:
System Task | Invocation Format | Task Description |
---|---|---|
Uniform Distribution | $dist_uniform(seed, start, end); | start, end are the start and end of the data |
Normal Distribution | $dist_normal(seed, mean, std_dev); | mean is the expected value, std_dev is the standard deviation |
Poisson Distribution | $dist_poisson(seed, mean); | mean is the expectation (equal to the standard deviation) |
Exponential Distribution | $dist_exponential(seed, mean); | mean is the number of events per unit time |
Chi-Square Distribution | $dist_chi_square(seed, free_deg); | free_deg is the degrees of freedom |
t Distribution | $dist_t(seed, free_deg); | free_deg is the degrees of freedom |
Erlang Distribution | $dist_erlang(seed, k_stage, mean); | k_stage is the order, mean is the expectation |
Uniform Distribution
The probability of a uniform distribution is the same on an interval of equal length.
The probability density function and probability distribution graph are shown below:
In fact, the system task $random implements a uniform distribution.
The code to call $dist_uniform to generate uniformly distributed data in the (256,512) interval is as follows:
Example
//2.1 uniform dis
reg [15:0] data_uniform;
always@(posedge clk) begin //generate random numbers between MIN_NUM and MAX_NUM
data_uniform <= $dist_uniform(seed
$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
### Verilog Data Analysis
In Matlab, the histogram function hist can be used to directly plot the statistical graphs of various data, but the actual drawing effect of this function is not very good for the probability distribution (welcome to provide a good drawing method). Here, the Matlab quantity statistics function tabulate is used to count the data, and then the ordinary drawing function plot is used to display the percentage.
The code for reading the data generated by the Verilog module and displaying its distribution graph in Matlab is as follows.
## Example
clear all;close all;clc; %======================================================= % data analysis from $dist_erlang in Verilog %=======================================================
%Read in strings and then convert from hexadecimal to decimal 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);
%Count the number of data and plot it 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');
The distribution graph of Erlang data generated by the Verilog model is shown below.
### Expectation of Erlang Distribution
It is important to note that the λ parameter is the expectation of the Poisson distribution, not the expectation of the Erlang distribution.
In the Verilog system task $dist_erlang(seed, k_stage, mean), the third parameter is the expected value. If the expected value is directly used as the λ parameter, an incorrect distribution result will be obtained.
Here is a simple (lazy) derivation of the mathematical expectation of the Erlang distribution.
Attached is the derivation process of the variance of the Erlang distribution.
### Theoretical Distribution in Matlab
Matlab's built-in function random can generate various types of distributed data, but there is no Erlang distribution.
The following uses the probability density function to generate data that conforms to the Erlang distribution.
Among them, the expected value in the Verilog model is 6, and the actual parameter λ = n/6.
The code for generating Erlang distribution data in Matlab is as follows.
## Example
clear all;close all;clc; %======================================================= % generating data of Erlang distribution %======================================================= NUM = 400; EXPECT = 6; for n=[1, 2, 3, 30] //Generate 4 sets of data lamda = n/EXPECT; //Expected value conversion t = (0:NUM-1)*0