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