FPGA模拟掷骰子

设计效果

       每按同一个按键时会随机得到一个1—6中的一个随机数字,并用数码管显示得到的数值。对两次按键得到的数值进行比较,若前者大,则最低两位LED显示为“亮”、“灭”,后者较大,则最后两位LED显示状态改为“灭”、“亮”。

设计方案

       本次课程设计的实质是使数码管随机显示一个数字,以达掷骰子时随机出数的效果,因此在小组讨论并查阅资料后我们总结出以下两种方案:

1.     查找FPGA中是否含有类似于C语言中rand()的随机函数,并搞清楚其用法和效果,弄清楚后进行实验,并在按下按键后使随机函数发生作用,并显示该数据,再将数据存入内部变量,并在其内部进行比较,将比较结果映射到LED最后两位进行显示。

2.     类似于老虎机一样,让数码管显示1~6六个数字,并高速滚动,然后通过按键暂停并显示,由于数码管显示数字在高速滚动状态下,人眼无法准确分清楚此时是什么数字,所以根据概率学来说六个数字每个具有等可能性,这样就能保证暂停的数字具有随机性,存储和比较模块原理与方案1相似。

方案选择

       由于第一种方案在实施起来时没有像第二种的老虎机一样,使人感觉有互动性,并且用函数随机显示数字会让人感觉突兀,并像是在“出千”。因此我们选用第二种方案进行本次课程设计

程序模块原理介绍:

分频器

由于cyclone IV板载系统时钟为50MHz,时钟频率过大,无法表现出程序效果(或者效果不明显),所以我们需要分频。

分频器原理:以系统时钟上升沿为标准,对系统时钟的上升沿计数,并给出一个信号变量(或普通变量)给出初值,计够一定次数以后对其变量电平反转,即通过电平反转重新造出来一个方波,以达到分频的目的。例如:对50MHz时钟二分频,就是对系统时钟上升沿计数,当机构2499999个数时对电平变量chz1进行反转,即可得到一个以0.5ms为周期的方波,则分频计算公式:

分频器程序:

       ck:PROCESS(CLK)                            --分频器程序

       BEGIN

       IFRISING_EDGE(CLK) THEN

              IFT="0000011010111100000111111" THEN—此处数值没有具体计算

                 T<="0000000000000000000000000";

                            CLK1HZ<=NOTCLK1HZ;

              ELSE

                     T<=T+1;

              ENDIF;

       ENDIF;

END PROCESS CK;

数字扫描模块

结构体中数字扫描:将数字扫描模块写在结构体中,使FPGA在运行程序时能够循环扫描数字,使数码管高速滚动数字。达到每个在暂停时,停止的每个数字具有等可能性。

结构体中数字扫描:

OUTPUT<="1111001"WHENINPUT="0001"ELSE—本程序写在结构体的begin下

              "0100100"WHENINPUT="0010"ELSE

              "0110000"WHENINPUT="0011"ELSE

              "0011001"WHENINPUT="0100"ELSE

              "0010010"WHENINPUT="0101"ELSE

              "0000011"WHENINPUT="0110";

进程中数字扫描:定义中间变量,对其进行1-6的循环加一计数,然后再将其送到数码管显示。

进程中数字扫描:

IF (CLK1HZ'EVENT AND CLK1HZ='1')THEN

       IF(A='1' AND B='1') THEN

              TMP:=TMP+1;

              IF(TMP=7) THEN

              TMP:=1;

              ENDIF;

          CASE TMP IS

                WHEN 1=> INPUT<="0001";

                WHEN 2=> INPUT<="0010";

                WHEN 3=> INPUT<="0011";

                                    WHEN 4=> INPUT <="0100";

                WHEN 5=> INPUT<="0101";

                WHEN 6=> INPUT<="0110";

                WHEN OTHERS => INPUT<="0000";

          END CASE;

       ENDIF;

END IF;

按键暂停模块

本次课程设计我们想用拨码开关以代替按键,本以为拨码开关不需要按键消抖但最终的实验效果却不尽如人意,仍需要按键消抖,所以本次设计时我们改了一下,利用两个按键对其进行暂停。如果用一个按键或拨码开关,必须要加按键消抖,否则会有一定干扰。

消抖原理:类似于51单片机按键消抖,先检验其是否按下,若被按下则延时一定时间,将其电平振荡的时间“滤”掉(在FPGA则数5ms的系统时钟过滤掉电平振荡的时间)。

按键暂停以及存储程序:

       IF(A='0') THEN

       TIM:=TIM+1;

              IF(TIM=1) THEN

                     RAN1<=TMP;

              ELSIF(TIM=2) THEN

                     RAN2<=TMP;

              ENDIF;

       ENDIF;

注意:本模块程序未加按键消抖程序,如用单一按键需对按键加消抖程序。

一个按键的暂停草稿程序(加有消抖,但并未实践)

       IF(A='0') THEN

              IFRISING_EDGE(CLK) THEN

                     IFT="0010011010111100000111111" THEN--此处数值没有具体计算

                       T<="0000000000000000000000000";

              ELSE

                     T<=T+1;

              ENDIF;

       ENDIF;

       WAITUNTIL(T=”0010011010111100000111111”);

       IF(A=”0”)THEN

       TIM:=TIM+1;

              IF(TIM=1) THEN

                     RAN1<=TMP;

              ELSIF(TIM=2) THEN

                     RAN2<=TMP;

              ENDIF;

       ENDIF;

END IF

比较模块

在程序内部定义两个变量(由于总开关为闭合状态所以不用考虑掉电保护问题),用于存储先后两次按键按下的数字,然后对其变量进行比较若前者较大映射到LED则最后两个灯显示为“亮”、“灭”,反之后者大则LED显示为“灭”、“亮”。

比较模块程序:

compare:PROCESS(RAN1,RAN2)

BEGIN

IF (RAN1>RAN2) THEN

       LED<="01";

ELSIF (RAN1<RAN2) THEN

       LED<="10";

ELSIF (RAN1=RAN2) THEN

       LED<="00";

END IF;

END PROCESS compare;

反思

在本次设计中,我们对两种方案进行考量,最终选择较为方便实现的方案,并且具有一定互动性。个人认为该方案的实现效果更好,但唯一的遗憾就是没有用一个按键实现数字暂停。因为在当时的情况下本人事情较多,无法考虑更多的情况,对于消抖的延时没有想清楚原理,所以没有大胆的实践。时间紧任务重只能选择最优方案。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值