Verilog 中使用系统任务 $random(seed) 产生随机数,seed 为随机数种子。seed 值不同,产生的随机数也不同。如果 seed 相同,产生的随机数也是一样的。可以为 seed 赋初值,也可以忽略 seed 选项,seed 默认初始值为 0。不使用 seed 选项和指定 seed 并对其修改来调用 $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
无论是否赋初值,每产生一次随机数后,seed 值改变,随机数也随之改变。每改变一次 seed 值,当前输出的随机值会改变;但是下一个状态时,随机数的走向又恢复成系统内部产生的随机序列。
建议调用系统任务 $random 时,不指定 seed 选项,或指定 seed 选项时使用变量传递参数。不建议调用 $random 时,将常数项写到 seed 参数处。此时 seed 值被固定,可能只会产生一个随机数。例如以下写法是不建议的:
randnum_wtseed <= $random(2); //不建议将常数项指定给 seed
可以使用取余的方法,将随机数限定在一定的数据范围内。例如:
//with a range
parameter MAX_NUM = 512;
parameter MIN_NUM = 256;
reg [15:0] num_range1, num_range2, num_range3 ;
always@(posedge clk) begin
//产生的随机数范围为 -511 ~ 511, ±(MAX_NUM-1)
num_range1 <= $random() % MAX_NUM;
//产生的随机数范围为 0 ~ 511, (0 ~ MAX_NUM-1)
num_range2 <= {$random()} % MAX_NUM;
//产生的随机数范围为 MIN_NUM ~ MAX_NUM,包含边界
num_range3 <= MIN_NUM + {$random()} % (MAX_NUM-MIN_NUM+1);
end
Verilog 提供了许多按一定概率分布产生数据的系统任务,简单描述如下:
| 系统任务 | 调用格式 | 任务描述 |
|---|---|---|
| 均匀分布 | $dist_uniform(seed, start, end); | start、end 为数据的起始、结尾 |
| 正态分布 | $dist_normal (seed, mean, std_dev); | mean 为期望值,std_dev 为标准差 |
| 泊松分布 | $dist_poisson(seed, mean); | mean 为期望 (等于标准差) |
| 指数分布 | $dist_exponential(seed , mean); | mean 为单位时间内事件发生的次数 |
| 卡方分布 | $dist_chi_square(seed, free_deg); | free_deg 为自由度 |
| t 分布 | $dist_t(seed, free_deg); | free_deg 为自由度 |
| 埃尔朗分布 | $dist_erlang(seed, k_stage, mean); | k_stage 为阶数,mean 为期望 |
均匀分布在等长区间上的取值概率是相同的。
概率密度函数及概率分布图如下所示:

其实,系统任务 $random 实现的就是均匀分布。
调用 $dist_uniform 在(256,512)区间上产生均匀分布数据的代码如下:
//2.1 uniform dis
reg [15:0] data_uniform;
always@(posedge clk) begin //在 MIN_NUM ~ MAX_NUM 产生随机数
data_uniform <= $dist_uniform(seed_dis, MIN_NUM, MAX_NUM);
end
正态分布数学期望为 μ,标准差为 σ,记做 N (μ, σ²)。
数学期望为 0、标准差为 1 的正态分布称为标准正态分布。
正态分布曲线呈钟型,两边低,中间高,左右对称。
正态分布概率密度函数及分布图如下所示:

调用 $dist_normal 产生期望为 0、标准差为 1 的标准正态分布数据的代码如下:
//2.2 normal dis
reg [15:0] data_normal;
always@(posedge clk) begin //期望为0、标准差为1 的标准正态分布
data_normal <= $dist_normal(seed_dis, 0, 1);
end
泊松分布用于描述某个时间或空间范围内,某事件发生 X 次的概率。
泊松分布的数学期望和标准差相同,均为 λ,其概率密度函数及分布图如下所示:

调用 $dist_poisson 产生期望为 4 的泊松分布数据的代码如下:
//2.3 poisson dis
reg [15:0] data_poisson;
always@(posedge clk) begin
data_poisson <= $dist_poisson(seed_dis, 4);
end
指数分布用以描述泊松过程中随机事件发生的时间间隔的概率。泊松过程即事件以恒定的平均速率连续且独立地发生的过程。例如等公交车时两辆车到来的时间间隔,就符合指数分布。设 λ>0 为单位时间内事件发生的次数(又称为率参数),x 为事件发生的时间间隔,则其概率密度函数及分布图如下所示:

调用 $dist_exponential 产生率参数为 1 的指数分布数据的代码如下:
//2.4 exp dis
reg [15:0] data_exp;
always@(posedge clk) begin
data_exp <= $dist_exponential(seed_dis, 1);
end
n 个服从标准正态分布的随机变量的平方和构成新的随机变量的分布规律称为卡方分布,记做

,其中 n 称为自由度。卡方分布概率密度函数及分布图如下所示:

调用 $dist_chi_square 产生自由度为 6 的卡方分布数据的代码如下:
//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
t 分布(T-Distribution)
假设 X 服从标准正态分布 N (0, 1),Y 服从卡方分布

的分布称为自由度为 n 的 t 分布,记为 Z ~ t(n) 。t 分布用于根据小样本来估计呈正态分布且方差未知的数据变量总体的均值。如果样本数量足够多且总体方差已知,则应该用正态分布来估计总体均值。t 分布是对称的钟形分布,与正态分布类似,但尾部较重,这意味着它更容易产生远低于平均值的值。其概率密度函数及分布图如下所示:

调用 $dist_t 产生自由度为 5 的 t 分布数据的代码如下:
//2.6 t dis
reg [15:0] data_t;
always@(posedge clk) begin
data_t <= $dist_t(seed_dis, 5);
end
埃尔朗分布(Erlang Distribution)
设参数为 λ 泊松过程 V1, V2, ..., V3, Vn 相互独立,N (t) 表示 [0, t) 内随机点出现的个数,则 N (t) = V1 + V2 + ... + Vn 的分布称为 Erlang 分布。
Erlang 分布与指数分布一样,多用来表示独立随机事件发生的时间间隔。遵循 Erlang 分布的随机变量可以被分解为多个相同参数的指数分布的随机变量之和,使得 Erlang 分布被广泛应用于可靠性理论和排队论中。
Erlang 分布概率密度函数及分布图如下所示:

Why The Face? 你竟然拿这样的水果 idea 来充数 Erlang 分布?
上述概率分布任务都只列举了调用方法,并没有对数据进行分析验证。下面有介绍借助 Matlab 画图工具,自己动手去分析概率分布任务 $dist_erlang 所产生数据的特性。
调用 $dist_erlang 产生阶数为 3、期望为 6 的 Erlang 分布数据的代码如下:
//2.7 Erlang dis
reg [15:0] data_erlang;
always@(posedge clk) begin
data_erlang <= $dist_erlang(seed_dis, 3, 6);
end
现实证明,还是熟知的分布数据分析起来比较方便。一些平台关于 Erlang 分布相关的可参考性集成函数是少之又少。明知没有爱(尔朗),偏向爱而行!
首先,在 Verilog 模型中产生 4 组服从 Erlang 分布的数据,并打印到文件中。
//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个数据分析
@(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 中可以使用柱状图函数 hist 直接对各个数据进行统计画图显示,但对于概率分布情况该函数实际画图效果并不是很好(欢迎提供良好的画图方法)。这里使用 Matlab 数量统计函数 tabulate 对各个数据进行统计,然后使用普通画图函数 plot 显示其百分比。
Matlab 读取 Verilog 模块产生的数据并对其进行分布图显示的代码如下。
clear all;close all;clc;
%=======================================================
% data analysis from $dist_erlang in Verilog
%=======================================================
%按字符串读取,再进行十六进制到十进制的转换
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);
%统计数据数量,并画图显示
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 模型产生的 Erlang 数据分布图如下所示。

千万要注意的是,λ 参数是泊松分布的期望,而不是 Erlang 分布的期望。Verilog 系统任务 $dist_erlang(seed, k_stage, mean) 中第三个参数为期望值。如果直接将期望值带入到 λ 参数,将得到错误的分布结果。下面简(偷)单(懒)推(参)导(考)下 Erlang 分布的数学期望。

附 Erlang 分布方差的推导过程。

使用 Matlab 内置函数 random,可以产生多种类型的分布数据,然而偏偏没有 Erlang 分布。
下面利用概率密度分布函数产生服从 Erlang 分布的数据。
其中,Verilog 模型中期望值为 6,则实际参数 λ = n/6 。
Matlab 产生 Erlang 分布数据的代码如下。
clear all;close all;clc;
%=======================================================
% generating data of Erlang distribution
%=======================================================
NUM = 400 ;
EXPECT = 6 ;
for n=[1, 2, 3, 30] //产生4组数据
lamda = n/EXPECT; //期望值转换
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 产生 Erlang 的数据分布图如下所示。
对比 Verilog 模型产生的数据,两者的分布区间、分布概率及分布曲线走势基本是一致的。只是 Verilog 中产生的是时间间隔较大的数据,分布图不是平滑的曲线。

我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想在ruby中生成一个64位整数。我知道在Java中你有很多渴望,但我不确定你会如何在Ruby中做到这一点。另外,64位数字中有多少个字符?这是我正在谈论的示例......123456789999。@num=Random.rand(9000)+Random.rand(9000)+Random.rand(9000)但我认为这是非常低效的,必须有一种更简单、更简洁的方法来做到这一点。谢谢! 最佳答案 rand可以将范围作为参数:pa=rand(2**32..2**64-1)#=>11093913376345012184putsa.
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:HowdoIgeneratealistofnuniquerandomnumbersinRuby?我想做的事:Random.rand(0..10).timesdoputsRandom.rand(0..10)end但如果随机数已经显示过,则无法再次显示。如何最轻松地做到这一点?
我试图在每次运行时以随机顺序将一个名称数组拆分为多个数组。我知道如何拆分它们:name_array=["bob","john","rob","nate","nelly","michael"]array=name_array.each_slice(2).to_a=>[["bob","john"],["rob","nate"],["nelly","michael"]]但是,如果我希望它每次都以随机顺序吐出它们怎么办? 最佳答案 在做同样的事情之前,打乱数组。(Array#shuffle)name_array.shuffle.each_s
目录一、inout在设计文件中的使用方法1.1、inout的第一种使用方法1.2、inout实现的第二种使用方法1.3、inout使用总结 二、inout在仿真测试中的使用方法一、inout在设计文件中的使用方法在FPGA的设计过程中,有时候会遇到双向信号(既能作为输出,也能作为输入的信号叫双向信号)。比如,IIC总线中的SDA信号就是一个双向信号,QSPIFlash的四线操作的时候四根信号线均为双向信号。在Verilog中用关键字inout定义双向信号,这里总结一下双向信号的处理方法。1.1、inout的第一种使用方法 实际上,双向信号的本质是由一个三态门组成的,三态门可以输出高电平,低电
有没有办法在ruby中生成介于1-100但不包括20、30和40之间的随机数?我可以做类似的事情defrandom_numberrandom_number=rand(100)whilerandom_number==20||30||40random_number=rand(100)endreturnrandom_numberend...但这似乎不是很有效(再加上那个特定的例子可能根本行不通)。有没有更简单的方法?任何帮助深表感谢! 最佳答案 创建一个1到100的数组。从该数组中删除不需要的元素。然后从数组中选择一个随机数。([*1
我想生成一个包含数字、字母和特殊字符的给定(长度可能不同)长度的完全随机的“唯一”(我将确保使用我的模型)标识符例如:161551960578281|2.AQAIPhEcKsDLOVJZ.3600.1310065200.0-514191032|有人可以建议在RubyonRails中最有效的方法吗?编辑:重要:如果可能,请评论您提出的解决方案的效率,因为每次用户进入网站时都会使用它!谢谢 最佳答案 将其用于访问token与UUID不同。您不仅需要伪随机性,而且还需要加密安全PRNG.如果您真的不关心您使用的是什么字符(它们不会增加任何
所以基本上是为了好玩,我试图生成一列数字(7位数字只有0和1)我的代码很短:a=rand(0000000-1111111)b=220a1=rand(0000000-1111111)a2=rand(0000000-1111111)a3=rand(0000000-1111111)a4=rand(0000000-1111111)a5=rand(0000000-1111111)whileb!=0putsaputsa2putsa3putsa4putsa5end我的问题是,不是生成随机的0和1列,而是所有,而是使用了数字。 最佳答案 这是惯用的
我有一个启动DRb服务的脚本,然后生成处理程序对象并通过DRb.thread.join等待。我希望脚本一直运行直到被明确杀死,所以我添加了trap"INT"doDRb.stop_serviceend在Ruby1.8下成功停止DRb服务并退出,但在1.9下似乎死锁(在OSX10.6.7上)。对该进程进行采样显示在semaphore_wait_signal_trap中有几个线程在旋转。我假设我在调用stop_service时做错了什么,但我不确定是什么。谁能给我任何关于如何正确处理它的指示? 最佳答案 好的,我想我已经找到了解决方案。如