Easy Tutorial
❮ Python Tower Filter Filterchain Filterconfig Intro ❯

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

❮ Python Tower Filter Filterchain Filterconfig Intro ❯