基于FPGA的随机数生成器
| 属性 | 内容 |
| 名称 | 随机数生成系统 Verilog QuartusII |
| 开发软件 | QuartusII |
| 编程语言 | Verilog |
代码功能
该系统实现了一个基于FPGA的随机数生成器,能够在1-99范围内生成不重复的随机数。系统支持用户通过按键控制开始和取数操作,生成的随机数会在7段数码管上显示。整个系统设计包含了完整的状态控制、防重复机制和直观的显示功能,适合用于抽奖、随机选择等场景。
代码实现思路
系统采用模块化设计,通过有限状态机控制整体流程。核心思想是利用高速时钟驱动计数器循环计数,当用户按下取数按键时,将当前计数器值作为随机数获取。为了保证随机数不重复,系统实现了两个关键机制:
1.自动跳过机制:在counter模块中记录已生成的随机数,计数时自动跳过这些值
2.重复检测机制:在random_num模块中检测新生成的随机数是否与已存储的重复,若重复则将值加1
整个系统工作在5个状态:空闲(s_idle)、计数(s_count)、取随机数(s_random)、显示(s_display)和结束(s_end),通过状态控制器协调各个模块的工作。
系统架构图
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 分频模块 │────>│ 状态控制模块 │<────│ 按键输入 │
└─────────────┘ └─────┬───────┘ └─────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 计数器模块 │─>│ 随机数模块 │─>│ 显示模块 │
└─────────────┘ └─────────────┘ └─────────────┘
│
┌────────┴────────┐
│ 7段数码管 │
└─────────────────┘
代码结构
| 模块名称 | 文件名 | 功能描述 |
| 顶层模块 | top.v | 连接所有子模块,是系统的总入口 |
| 分频模块 | div.v | 将50MHz时钟信号分频为1Hz,用于计时 |
| 状态控制模块 | state_ctrl.v | 管理系统在不同状态间的转换,协调各模块工作 |
| 计数器模块 | counter.v | 实现1-99的循环计数,并自动跳过已生成的随机数 |
| 随机数模块 | random_num.v | 存储生成的随机数并处理可能的重复情况 |
| 显示模块 | display.v | 将数字转换为7段数码管的显示码,控制数码管显示 |
关键技术亮点
1.防重复随机数生成:通过双重机制确保生成的6个随机数互不重复
2.模块化设计:各功能模块职责明确,便于维护和扩展
3.有限状态机控制:使用状态机管理系统流程,逻辑清晰可靠
4.用户交互设计:简单直观的按键操作,清晰的数码管显示
应用场景
该随机数生成系统可广泛应用于需要公平随机选择的场景,如抽奖活动、随机点名、游戏随机事件触发等。在教育实验中也可作为FPGA数字系统设计的教学案例。
演示视频:
设计文档:
1.工程文件
状态机图
2.程序文件
3.程序编译
4.RTL图
5.管脚分配
6.Testbench
7.仿真图
整体仿真图
分频模块
计数模块
随机数模块
状态机模块
显示模块
部分代码展示:
//随机数生成模块 module random_num( input clk,//50MHz input key_0,//开始,按下低电平 input [2:0] state,//输入的状态 input [4:0] repeat_cnt,//重复次数计数 input [6:0] count,//计数器值 output reg [6:0]data_temp1, output reg [6:0]data_temp2, output reg [6:0]data_temp3, output reg [6:0]data_temp4, output reg [6:0]data_temp5, output reg [6:0]data_temp6 ); parameter s_idle=3'd0; parameter s_count=3'd1; parameter s_random=3'd2; parameter s_display=3'd3; parameter s_end=3'd4; //data_temp1~6存储6次随机数,便于跳过 always@(posedge clk or negedge key_0) if(key_0==0)begin//复位 data_temp1<=7'd0; data_temp2<=7'd0; data_temp3<=7'd0; data_temp4<=7'd0; data_temp5<=7'd0; data_temp6<=7'd0; end else if(state==s_random && repeat_cnt==5'd0)//计数状态,随机数1 data_temp1<=count;//取计数器count值幅值到随机数data_temp1存储起来 else if(state==s_random && repeat_cnt==5'd1)//计数状态 if(count==data_temp1) data_temp2<=count+6'd1;//若count与之前随机数重复,将计数器再加1
138