Verilog - 生成加权随机数

时间:2013-11-22 07:33:31

标签: verilog system-verilog

我正在尝试生成随机单个位,只要您想要正常的随机化,这很简单:

wire R;
assign R = $random % 2;

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

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

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

6 个答案:

答案 0 :(得分: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“发布”。

答案 1 :(得分:2)

然后根据值返回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

答案 2 :(得分: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

答案 3 :(得分:0)

类似的东西:

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

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

答案 4 :(得分: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

答案 5 :(得分:0)

verilog似乎没那么难。

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

这里我假设$ random非常统一。我认为它应该有效:)