Verilog - 生成加权随机数

问题描述 投票:3回答:6

我试图生成随机单位,只要你想要一个正常的随机化,这很简单:

wire R;
assign R = $random % 2;

我正在寻找的是一种加权概率,如:

wire R;
assign R = 60%(0) || 40%(1);

请原谅我,如果它不符合标准的Verilog代码,那只是想知道我想要什么。谁能帮我吗?谢谢

verilog system-verilog
6个回答
9
投票

SystemVerilog解决方案在randomize中有一个名为dist的分发方法。重量由value_or_range := weightvalue_or_range :/ distributed_weight指定。这篇来自IEEE Std 1800-2012§18.5.4第476页的论文给出了一个明确的例子:

当权重应用于范围时,它们可以应用于范围中的每个值,或者它们可以作为整体应用于范围。例如: x dist { [100:102] := 1, 200 := 2, 300 := 5} 均值x等于100,101,102,200或300,加权比为1-1-1-2-5,和 x dist { [100:102] :/ 1, 200 := 2, 300 := 5} 装置x等于100,101,102,200或300中的一个,加权比为1 / 3-1 / 3-1 / 3-2-5。

dist用于随机化,因此它需要是randomize() with(或类constraint)的母马。 randomize返回一个成功位,因此它应该在assertvoid'()或赋值的RHS中调用。

在你我们可以设置0到6的重量和1到4的重量,总重量为10,分布为60/40。例:

reg R;
initial begin
  assert( randomize(R) with { R dist { 0 := 6, 1 := 4 }; } );
end

更多关于dist的信息,请参阅IEEE Std 1800-2012§18.5.4“分布”。


2
投票

然后根据Value返回1或0创建一个随机整数;注意,您可能希望为随机数播种,重复性使用相同的种子。这样,当测试失败时,可以调试它。

$urandom$random有点不同,它不会更新种子值,因此只应在第一次在线程中调用时播种(始终阻止)。它也是线程安全的,每个块总是独立工作。

initial begin
  $urandom(seed);
  $urandom;
  $urandom;
end

integer temp;
reg     r   ;

always @ ... begin
  temp = $urandom; //Range: +2_147_483_647 -2_147_483_648
  // weighting; 0 would be 50:50
  // real weighting is (0.1 + 0.5), 0.5 inherent from positive number.
  r =  (temp > (2_147_483_647*0.1);  
end

注意:随机函数不可合成,只能用于测试平台。如果你想要一个随机数合成检查this Question


1
投票

对于Verilog,你总是可以这样:

integer R;

R = ($dist_uniform(0,100) < 60) : $dist_uniform(0,5) : $dist_uniform(6,10)

这在SystemVerilog中与以下内容相同:

std::randomize(R) with {R dist {[0:5] :/60, [6:10] :/ 40} ;};

您也可以执行此程序代码:randcase 60:R = 1; 40:R = 0; ENDCASE


0
投票

以下代码将根据您的要求生成随机变量:

program top;
    class Packet;
        rand reg R;
        constraint percentage {R dist {1:=60,0:=40};};
        function void display;
            $display("Random Reg : %0d",this.R);
        endfunction
    endclass
    Packet P;

    initial 
    begin
        P = new;
        repeat(10)
            begin
                P.randomize();
                P.display;
            end
    end
endprogram

0
投票

在verilog看起来并不那么难。

reg [7:0] R;
reg rand_bit;
R = $random();
if (R < 76)
   rand_bit = 1'b0;
else
   rand_bit = 1'b1;

在这里我假设$ random非常统一。我认为它应该工作:)


0
投票

就像是:

wire R;
if ($random[7:0]>(40*255/100))
  assign R = 1'b0;
else
  assign R = 1'b1;

我假设$random使用的算法产生的数字与你从中获取的任何位数都是随机的。

© www.soinside.com 2019 - 2024. All rights reserved.