伪随机数生成器(LFSR),使用中心极限定理的均匀正态分布无法正常工作?

问题描述 投票:0回答:1

作为更大项目的一部分,我在生成正态随机变量时遇到困难,需要一些帮助。 首先,是的,我知道 AWGN 方法、Box-Muller 等以及其他更好的随机数生成器,是的,我选择了一个相当无效的 RNG 解决方案,但这是我的第一个大型 verilog 项目,我可以慢慢地做它因为我正在努力学习,所以请不要只是通过告诉我应该采取的所有不同方式来回应......除非我做错了什么!现在,问题来了。

这个想法是通过使用 LFSR,我们可以生成均匀的伪随机变量,然后通过中心极限定理,如果我们对许多独立均匀变量的平均值进行采样,我们将得到正态分布。

我读过一个类似的 VHDL 解决方案,它似乎相对成功,所以我相信该方法应该可行(尽管不是最准确的) - VHDL 方法

我相信我的错误在于未能收集每个时钟周期的所有 32 个 LFSR 输出的平均值,因为我已经检查了 LFSR 模块的波形,并且仅此一项似乎工作正常,但是当我检查 python 中的输出时,我发现仍然得到均匀分布...不是正态分布。

下面是我的模块,用于累积来自每个时钟周期 32 个 LFSR 的统一伪随机变量(具有不同的种子 - 在 python 中“随机”生成,哈哈),然后取它们的平均值(除以 32)。

`timescale 1ns / 1ps

module CLTuniformToNormal(output [31:0] o_Mean, input i_Clock, input i_Reset);
    reg [36:0] r_Accumulator = 0;
    wire [31:0] o_LFSR_Out[31:0];
    parameter c_SEED0 = 32'h2b5f712d; parameter c_SEED1 = 32'h1834a06b; parameter c_SEED2 = 32'h9c82b0a3; parameter c_SEED3 = 32'hf33e3930;
    parameter c_SEED4 = 32'hf5cc2528; parameter c_SEED5 = 32'h6b21a119; parameter c_SEED6 = 32'hf874c4ea; parameter c_SEED7 = 32'h8b5d0748;
    parameter c_SEED8 = 32'hdf4c754a; parameter c_SEED9 = 32'hc1cfb4b8; parameter c_SEED10 = 32'h2097bf95; parameter c_SEED11 = 32'h9bc45a55;
    parameter c_SEED12 = 32'hb49c15c4; parameter c_SEED13 = 32'h0a7b9340; parameter c_SEED14 = 32'h7f658627; parameter c_SEED15 = 32'hee57af5a;
    parameter c_SEED16 = 32'hd8b427bb; parameter c_SEED17 = 32'he793836a; parameter c_SEED18 = 32'hf4e3e39f; parameter c_SEED19 = 32'h2987b38b;
    parameter c_SEED20 = 32'h173ac4ce; parameter c_SEED21 = 32'hdb53d09e; parameter c_SEED22 = 32'h5af5fd7f; parameter c_SEED23 = 32'h1352a672;
    parameter c_SEED24 = 32'h2ab03e34; parameter c_SEED25 = 32'hdd03bb9b; parameter c_SEED26 = 32'h6b72eaca; parameter c_SEED27 = 32'hb5e22b2e;
    parameter c_SEED28 = 32'hfa232aea; parameter c_SEED29 = 32'h067db0f8; parameter c_SEED30 = 32'hed09559a; parameter c_SEED31 = 32'hfacf5eaa;
      
    // Instantiate 32 LFSR modules
    genvar i;
    generate
        for (i = 0; i < 32; i = i + 1) begin : INST_LFSR
            LFSR #(.c_SEED((i==0) ? c_SEED0 : (i==1) ? c_SEED1 : (i==2) ? c_SEED2 : (i==3) ? c_SEED3 : (i==4) ? c_SEED4 :
            (i==5) ? c_SEED5 : (i==6) ? c_SEED6 : (i==7) ? c_SEED7 : (i==8) ? c_SEED8 :
            (i==9) ? c_SEED9 : (i==10) ? c_SEED10 : (i==11) ? c_SEED11 : (i==12) ? c_SEED12 :
            (i==13) ? c_SEED13 : (i==14) ? c_SEED14 : (i==15) ? c_SEED15 : (i==16) ? c_SEED16 :
            (i==17) ? c_SEED17 : (i==18) ? c_SEED18 : (i==19) ? c_SEED19 : (i==20) ? c_SEED20 :
            (i==21) ? c_SEED21 : (i==22) ? c_SEED22 : (i==23) ? c_SEED23 : (i==24) ? c_SEED24 : 
            (i==25) ? c_SEED25 : (i==26) ? c_SEED26 : (i==27) ? c_SEED27 : (i==28) ? c_SEED28 :
            (i==29) ? c_SEED29 : (i==30) ? c_SEED30 : c_SEED31))
            LFSR_inst (
                .o_LFSR_Out(o_LFSR_Out[i]),
                .i_Clock(i_Clock),
                .i_Reset(r_Reset)
            );
        end
    endgenerate

    always @(posedge i_Clock or posedge i_Reset) begin
        if (i_Reset) begin
            r_Accumulator <= 0;
        end else begin
            // Accumulate outputs
            r_Accumulator <= r_Accumulator + o_LFSR_Out[0] + o_LFSR_Out[1] + o_LFSR_Out[2] + o_LFSR_Out[3] + o_LFSR_Out[4] + o_LFSR_Out[5] +
            o_LFSR_Out[6] + o_LFSR_Out[7] + o_LFSR_Out[8] + o_LFSR_Out[9] + o_LFSR_Out[10] +
            o_LFSR_Out[11] + o_LFSR_Out[12] + o_LFSR_Out[13] + o_LFSR_Out[14] + o_LFSR_Out[15] +
            o_LFSR_Out[16] + o_LFSR_Out[17] + o_LFSR_Out[18] + o_LFSR_Out[19] + o_LFSR_Out[20] +
            o_LFSR_Out[21] + o_LFSR_Out[22] + o_LFSR_Out[23] + o_LFSR_Out[24] + o_LFSR_Out[25] +
            o_LFSR_Out[26] + o_LFSR_Out[27] + o_LFSR_Out[28] + o_LFSR_Out[29] + o_LFSR_Out[30] +             
            o_LFSR_Out[31];
        end
    end

    // Calculate mean
    assign o_Mean = (r_Accumulator >> 5);// - 2**31; // Divide by 32 and shift mean to 0
    
endmodule

我的测试平台将每个时钟周期的 o_Mean 写入一个文本文件,然后用 python 绘制直方图。 希望有人能看到我哪里出错了。谢谢。

verilog normal-distribution uniform-distribution lfsr
1个回答
0
投票

啊,我意识到我不需要在每个时钟周期将 r_Accumulator 添加到自身。

抱歉,简单的解决方案,但我已经为此摸不着头脑了几个小时。

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