高斯分布的随机数生成器

 实现的过程是先查找相关高斯分布随机数在vivado实现的博客,先大概认识一下,然后到知网找相关的硕士论文,总结出最简单的高斯随机数生成的实现方法,在进行仿真验证。

在查阅相关论文后把高斯分布随机数生成器分为两个模块:
模块一:基于细胞自动机生成均匀随机数,具体是采用64阶细胞自动机的均匀随机数发生器来产生均匀随机数。
模块二:通过Box-Muller算法将均匀随机数转换成为高斯随机数。

模块一:通过细胞自动机生成均匀随机数

​ 关于细胞自动机的最早的思想起源于StanislawUlam,它是一种特殊的具有时间、空间和状态离散性的有限状态机。由于细胞自动机概念的复杂性,所以早期的对于细胞自动机的研究基本上是集中于理论方面,直到20世纪80年代初,由S.Wolfram46首先对细胞自动机的概念进行了简化,从而极大推动了细胞自动机理论及其应用研究。细胞自动机是D维空间中一组细胞单元组成的阵列,一个细胞自动机可用四元组表示为:
CA=(AD,Zq,fi(o,r),B)CA = (A_D,Z_q,f_i(o,r),B) CA=(AD​,Zq​,fi​(o,r),B)

其中,空间结构A是由D维细胞单元构成的空间结构,状态空间-q是细胞自动机中细胞单元i的状态取值范围;邻域函数规则是细胞自动机的邻域半径r确定的第i个细胞单元的0阶邻域状态配置与其转移状态之间的映射: 边界条件B规定了某个细胞单元领域半径之内的邻域单元在超出细胞自动机空间结构时的处理方法。

​ 代码实现32阶细胞自动机的均匀随机数发生器来产生均匀随机数,通过给出32位细胞的初始值和规则号(90规则和150规则),将单个细胞例化32次,就可以得到32位的细胞自动机。

单个细胞如下

 module single_cell#(parameter init = 1'b0 , head = 1'b0, tail = 1'b0)
(
input clk_i,rst_n_i,
input ctrl,
input self,left,right,output out
);reg  self_next;always @(*) begincase({head,tail})2'b10 : self_next = ctrl ? self ^ right : right;2'b01 : self_next = ctrl ? self ^ left  : left;2'b00 : self_next = ctrl ? left ^ self ^ right : left ^ right;default:  self_next = ctrl ? left ^ self ^ right : left ^ right;endcase
endassign out = self_next; endmodule

例化过程:因为头尾细胞和中间细胞存在区别,分为三个部分分开例化,以中间细胞为例,只需将left ( uni_r[i-1]),更改为left (1’b0)即为头细胞,将.right (uni_r[i+1])更改为.right (1’b0)即为尾细胞

module mata#(parameter INTA_VEC = 32'b0100_1000_0001_0010_0100_1000_0001_0010,parameter RULE_VEC   = 32'b0000_1100_0100_0111_0000_1100_0000_0110,N = 32   )(input clk_i,rst_n_i,input pause_i,        //暂停output [N-1:0] out_1  //均匀随机数);reg  [N-1:0] uni_r;wire [N-1:0] uni_next;assign out_1 = uni_r;always @(posedge clk_i or negedge rst_n_i)beginif(~rst_n_i)uni_r <= INTA_VEC;else if(pause_i)uni_r <= uni_r;elseuni_r <= uni_next;endgenerategenvar i;for (i = 0; i < N; i = i + 1 )beginif( i==0 )begin//第一位single_cell#(.init (INTA_VEC[i]),.head(1'b1 ),.tail (1'b0))single_cell_first_num (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.ctrl (RULE_VEC[i] ),.left ( 1'b0),.right (uni_r[1]),.self (uni_r[i]),.out  ( uni_next[i]));endelse if(i == N - 1)begin//最后一位single_cell#(.init (INTA_VEC[i] ),.head(1'b0 ),.tail (1'b1))single_cell_num (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.ctrl (RULE_VEC[i] ),.left ( uni_r[i-1]),.right (1'b0),.self (uni_r[i]),.out  ( uni_next[i]));endelsebegin //中间位single_cell#(.init (INTA_VEC[i] ),.head(1'b0 ),.tail (1'b0))single_cell_mid_num (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.ctrl (RULE_VEC[i] ),.left ( uni_r[i-1]),.right (uni_r[i+1]),.self (uni_r[i]),.out  ( uni_next[i]));endendendgenerateendmodule

对32阶的细胞自动机进行仿真

给出32位细胞的初始值和规则号,给定时钟,采集数据写入new_data_b.txt文本,方便接下来在matlab上进行仿真。

module tb_celluar_auto();// Parameterslocalparam  INTA_VEC = 32'b0100_1000_0001_0010_0100_1000_0001_0010;localparam  RULE_VEC = 32'b0000_1100_0100_0111_0000_1100_0000_0110;localparam  N = 32;localparam  period = 10; //100Mhz// Portsreg clk_i = 0;reg rst_n_i = 1;reg pause_i = 0;wire [N-1:0] out_1;mata #(.INTA_VEC(INTA_VEC ),.RULE_VEC(RULE_VEC ),.N (N))mata_dut (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.pause_i (pause_i ),.out_1  ( out_1));parameter M = 200_000;
reg [N-1:0] men [M:1];
integer index = 1;
initial begin //复位begin#(period*2) rst_n_i = 1'b0;#(period*10) rst_n_i = 1'b1;#(period*201_000);$writememb("new_data_b.txt",men);$finish;endendinitial //采集数据begin#(period*100);forever begin#(period);men[index] = out_1;index = (index >= M) ? 1 : index + 1;endendalways //生成时钟#(period)  clk_i = ! clk_i ;endmodule

将txt文本的数据导入到matlab上可以看到仿真结果基本符合在0到1之间均匀分布。
附上matlab的代码

clc;
fid = fopen('D:\BaiduNetdiskDownload\new_data_b.txt');
data = textscan(fid, '%b');
fclose(fid);
data = cell2mat(data);
data = double(data) / double(max(data));
%29 -> [0,1] -> data / max(data);%h = histogram(data,16);
h = histogram (data, 100,'BinLimits',[0,1]);

模块一结束下面进行模块二,Box-Muller算法部分

​ Box-Muller算法是最早的产生高斯白噪声的算法之一,它是利用均匀随机数来分别计算出高斯随机数的幅度和相位值从而产生高斯随机数的算法, Box-Muller算法可以同时将两个均匀随机数转换成为两个高斯随机数。其隐含的原理非常深奥,但结果却是相当简单。假设x和x为相互独立的零均值的服从标准正态分布的高斯随机变量,那么可知R=√x2+x20=arctan(x2/x)分别服从瑞利分布和均匀分布。利用这一事实,可以通过将一对服从瑞利分布的随机变量和一对服从均匀分布的随机变量进行变换,产生出一对高斯变量来。具体算法如下:

​ 其中,u1和u2是在[01]上均匀分布的均匀随机变量,u1用来产生高斯随机数的幅度值,u2则产生高斯随机数的相位值。因为算法涉及自定义对数函数和三角函数,对于其中的自定义对数函数我采用查找表的方式实现,首先在matlab里生成对数函数对应自变量和因变量映射关系存放在ROM IP核里,通过查找自变量得到因变量。

使用matlab产生数据并生成.coe文件

clear all;
clc;N = 16;
out_N = 16;
x = linspace(0.000001,1,pow2(N));
y = sqrt(-2*log(x));
y_fix = round(y/max(y)*(2^out_N));
y_fix(1) = y_fix(1) - 1;
y_qua = y_fix;
width = 16;
depth = pow2(N);plot(x,y_qua);fid = fopen("f.coe","w");   % 创建coe文件;
fprintf(fid,"memory_initialization_radix=16;\n");
fprintf(fid,"memory_initialization_vector=\n");for num = 0 : (depth-1)fprintf(fid,"%02X,\n",y_qua(num+1));
endfseek(fid,-2,1);
fprintf(fid,";");fclose(fid);

添加ROM IP核
在IP Catalog里搜索ROM,选择Bloke Memory Generator
在IP核配置界面basic选择单端输入rom即Single Port ROM

将matlab生成的coe文件导入到ROM IP核中,并对IP核进行命名,注意.coe文件的路径不能有中文,否者会标红。

添加DDS IP核
三角函数用DDS IP核实现,下图包含IP核配置情况

接下来再添加乘法器的ip核,并且命名。

在IP Sources里可以看到已添加的IP核

例化IP核,完成Box-Muller算法部分。
module box_muller(input clk_i ,rst_n_i,//复位input [63:0] uni_i,output [31:0] gau1_o,output [31:0] gau2_o);wire [15:0] uni_g= uni_i [63:48];wire [15:0] uni_f= uni_i [31:16];wire [15:0] fun_f_o;wire [15:0] g1_sin_o;wire [15:0] g2_cos_o;wire m_axis_data_tvalid;//wire [15:0] g1_sin_o,g2_cos_o;dds_g12 dds_g12_inst (.aclk(clk_i),                                // input wire aclk.aresetn(rst_n_i),                          // input wire aresetn.s_axis_phase_tvalid(1'b1),  // input wire s_axis_phase_tvalid.s_axis_phase_tdata(uni_g),    // input wire [15 : 0] s_axis_phase_tdata.m_axis_data_tvalid(m_axis_data_tvalid),    // output wire m_axis_data_tvalid.m_axis_data_tdata({g1_sin_o,g2_cos_o})      // output wire [31 : 0] m_axis_data_tdata);bram_fun_f bram_fun_f_inst (                           //ROM.clka(clk_i),    // input wire clka.addra(uni_f),  // input wire [15 : 0] addra.douta(fun_f_o)  // output wire [15 : 0] douta
);multi_box_muller multi_box_muller_inst_1 (             //两个乘法器.CLK(clk_i),  // input wire CLK.A(g1_sin_o),      // input wire [15 : 0] A.B(fun_f_o),      // input wire [15 : 0] B.P(gau1_o)      // output wire [31 : 0] P
);multi_box_muller multi_box_muller_inst_2 (.CLK(clk_i),  // input wire CLK.A(g2_cos_o),      // input wire [15 : 0] A.B(fun_f_o),      // input wire [15 : 0] B.P(gau2_o)      // output wire [31 : 0] P
);endmodule
接下来进行仿真,例化Box-Muller算法模块。
module tb_box_muller();// Parameters// Portsreg clk_i = 0;reg rst_n_i = 1;reg [63:0] uni_i = 64'd0;wire [15:0] g1_sin_o;wire [15:0] g2_cos_o;wire [15:0] fun_f_o;localparam  period = 10; box_muller box_muller_dut (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.uni_i (uni_i ),.g1_sin_o (g1_sin_o ),.g2_cos_o (g2_cos_o ),.fun_f_o  ( fun_f_o));initial beginbegin#(period*2) rst_n_i = 1'b0;#(period*10) rst_n_i = 1'b1;#(period*201_000);$finish;endendalways#(period) uni_i = uni_i +  64'd1;always#(period/2)  clk_i = ! clk_i ;endmodule

然后进行Box-Muller算法模块的仿真,仿真结果如图可以看到自定义对数函数和三角函数均已实现

实现高斯随机数的生成

创建顶层模块Top例化细胞自动机和Box-Muller算法模块

module gauss_top((* io_buffer_type = "none" *)input clk_i ,rst_n_i,//复位(* io_buffer_type = "none" *)output [31:0] gau1_o,(* io_buffer_type = "none" *)output [31:0] gau2_o);wire [31:0] out_1;wire [31:0] out_2;mata#(.INTA_VEC(32'b0000_1100_0100_0111_0000_1100_0000_0110 ),.RULE_VEC(32'b0000_1100_0100_0111_0000_1100_0000_0110 ),.N ( 32 ))mata_u1 (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.pause_i (1'b0 ),.out_1  ( out_1));mata #(.INTA_VEC(32'b0100_0110_0000_1001_1011_1011_1101_0101 ),.RULE_VEC(32'b0100_0110_0000_1001_1011_1011_1101_0101 ),.N ( 32 ))mata_u2 (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.pause_i (1'b0 ),.out_1  ( out_2));box_muller box_muller_dut (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.uni_i ( {out_1,out_2} ),.gau1_o (gau1_o ),.gau2_o  ( gau2_o));
endmodule

将细胞自动机模块与Box-Muller算法模块例化到tb_top, 将采集仿真的数据g1 g2并且导入到new_data_g1.txt new_data_g2.txt文本里。

module tb_top();
// Parameters
localparam  period = 10; //100Mhz
// Portsreg clk_i = 0;reg rst_n_i = 1;wire [31:0] gau1_o;wire [31:0] gau2_o;gauss_top gauss_top_dut (.clk_i (clk_i ),.rst_n_i (rst_n_i ),.gau1_o (gau1_o ),.gau2_o  ( gau2_o));parameter M = 200_000;parameter N = 32;reg [N-1:0] mem1 [M:1];reg [N-1:0] mem2 [M:1];integer index = 1;initial begin //复位begin#(period*2) rst_n_i = 1'b0;#(period*10) rst_n_i = 1'b1;#(period*201_000);$writememb("new_data_g1.txt",mem1);$writememb("new_data_g2.txt",mem2);$finish;endendinitial //采集数据begin#(period*100);forever begin#(period);mem1[index] = gau1_o;mem2[index] = gau2_o;index = (index >= M) ? 1 : index + 1;endendalways#(period/2)  clk_i = ! clk_i ;
endmodule
最后将txt文本里的数据导入到maltab上验证一下,可以看到仿真结果基本是符合了高斯分布的随机数。

附上matlab验证代码

clear all;
clc;fid = fopen('D:\FPGA\Vivado projects\winter exercise\project_matlab\new_data_g1.txt');
data = textscan(fid,'%bs32');
fclose(fid);
data = cell2mat(data);data = double(data)/pow2(31);
num_point = 1000;% h = histogram(data,16);
h = histogram(data,num_point,'BinLimits',[-1,1]);counts = hist(data,num_point,'BinLimits',[-1,1]);
counts = counts/max(counts);f = fittype('a*exp(-((x-b)/c)^2)');
x = linspace(-1,1,num_point);
y = counts;
plot(x,y,'.')[cfun,gof] = fit(x(:),y(:),f);
yy = cfun.a*exp(-((x-cfun.b)/cfun.c).^2);
hold on;
plot(x,yy,'r','LineWidth',2);
A = cfun.a;%幅值
mu = cfun.b;%期望
sigma = cfun.c;%标准差

![img](https://img-blog.csdnimg.cn/2a0f859d02a14e5a9e2c8fab0dc6d367.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzUzNzEyMTQ4,size_19,color_FFFFFF,t_70,g_se,x_16

高斯分布的随机数生成器相关推荐

  1. c++产生均匀分布随机数赋值_不随机的随机数:高斯随机数生成器综述

    随机数的使用非常广泛,例如在从统计总体中抽取有代表性的样本时,或者在将实验动物分配到不同的试验组的过程中,或者在进行蒙特卡洛模拟法计算的时候等等.事实上,这些统计技术中使用的随机数均为"伪随 ...

  2. luogu P3306 [SDOI2013] 随机数生成器(BSGS,数列求通项,毒瘤特判)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 发个水题的 题解证明我还在() luogu P3306 [SDOI2013] 随机数生成器 Webli ...

  3. Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom

    Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom 文中的 Random即:java.util.Random, ThreadLocalRandom 即 ...

  4. 开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器

    原文:[原创]开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器                本博客所有文章分类的总目录:http://www.cnblogs.com/asxiny ...

  5. P5147 随机数生成器 [数列]

    P5147 随机数生成器 数学老师看不懂系列 看题目这一片代码就很晕: int work(int x) {if(x==1)return 0;else return work(rand(1,x))+1; ...

  6. UA STAT675 统计计算I 随机数生成1 随机数生成器的一般理论

    UA STAT675 统计计算I 随机数生成1 随机数生成器的一般理论 RNG的抽象表示 RNG的质量指标 RNG的统计检测 在统计计算中,从某个分布中进行采样通常分为两个步骤: 生成随机数z1,z2 ...

  7. boost::sort模块实现提供多种分布的灵活随机数生成器的测试程序

    boost::sort模块实现提供多种分布的灵活随机数生成器的测试程序 实现功能 C++实现代码 实现功能 boost::sort模块实现提供多种分布的灵活随机数生成器的测试程序 C++实现代码 #i ...

  8. boost::sort模块实现支持不同分布的随机数生成器的测试程序

    boost::sort模块实现支持不同分布的随机数生成器的测试程序 实现功能 C++实现代码 实现功能 boost::sort模块实现支持不同分布的随机数生成器的测试程序 C++实现代码 #inclu ...

  9. ITK:Mersenne Twister随机数生成器

    ITK:Mersenne Twister随机数生成器 内容提要 C++实现代码 内容提要 产生一个随机数 C++实现代码 #include "itkMersenneTwisterRandom ...

最新文章

  1. 会说话的狗狗本电脑版_会说话的电脑有点酷!惠普星14帮你解锁“偷懒”新姿势_惠普 星 14 2020(i5 1135G7/16GB/512GB/MX450)_笔记本新闻...
  2. lstm 文本纠错_中文文本纠错算法错别字纠正的二三事
  3. 工大附中、铁一太牛了,2019年高分段人数令人震惊!
  4. Xshell连接服务器桌面调用服务器的图形==Xmanager的===Xbrowser===XDMCP远程桌面===调用virt-mannager管理工具;、Xshell用普通用户调用图形
  5. 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 3
  6. C语言中不检查数组下标是否越界。
  7. batchplot插件用法_Batchplot批量打印怎么用?Batchplot批量打印教程
  8. NOI 08 石头剪刀布
  9. 一图看懂什么是集成电路?
  10. 库存管理一般用什么软件比较好?
  11. 微信公众号、微信小程序的详细介绍
  12. easyui datagrid 多列排序,该如何处理[多列同时order,只针对某一列order]
  13. ThinkAdmin漏洞(CVE-2020-25540 )复现
  14. slack下载 csdn、_找出老板是否可以下载Slack DM
  15. mysql 行转列查询优化_行转列及列转行查询
  16. 如何设置使用Windows系统自带的图片查看器打开图片?
  17. 2020东京奥运会奖牌排行--数据可视化
  18. 对《移动互联网白皮书(2013年)》的几个解读
  19. (转)程序员专属壁纸
  20. 【计算机网络】从零开始的个人网站1 从部署轻量应用服务器到搭建简易网站(持续更新中!)

热门文章

  1. 怎么禁止计算机安装程序,电脑如何禁止安装软件,教你win10电脑禁止安装软件的设置教程...
  2. 重新配置Tomcat
  3. 大数模板——来自jxy师兄
  4. 实现单点登录(伪登录)
  5. 来自#Devoxx 2014的WebSocket螺母和螺栓的幻灯片
  6. Python——> 一二维数据的格式化和处理
  7. CocosCreator中游戏摇杆的实现
  8. Linux(CentOS7)查看虚拟机IP
  9. 用HTML5和JavaScript做一个轮播图
  10. Windows Phone周岁背后的喜和忧