设计效果
每按同一个按键时会随机得到一个 1—6 中的一个随机数字,并用数码管显
示得到的数值。对两次按键得到的数值进行比较,若前者大,则最低两位 LED 显
示为“亮”、“灭”,后者较大,则最后两位 LED 显示状态改为“灭”、“亮”。
设计方案
本次课程设计的实质是使数码管随机显示一个数字,以达掷骰子时随机出数
的效果,因此在小组讨论并查阅资料后我们总结出以下两种方案:
1. 查找 FPGA 中是否含有类似于 C 语言中 rand()的随机函数,并搞清楚其
用法和效果,弄清楚后进行实验,并在按下按键后使随机函数发生作用,
并显示该数据,再将数据存入内部变量,并在其内部进行比较,将比较
结果映射到 LED 最后两位进行显示。
2. 类似于老虎机一样,让数码管显示 1~6 六个数字,并高速滚动,然后通
过按键暂停并显示,由于数码管显示数字在高速滚动状态下,人眼无法
准确分清楚此时是什么数字,所以根据概率学来说六个数字每个具有等
可能性,这样就能保证暂停的数字具有随机性,存储和比较模块原理与
方案 1 相似。
方案选择
由于第一种方案在实施起来时没有像第二种的老虎机一样,使人感觉有互动
性,并且用函数随机显示数字会让人感觉突兀,并像是在“出千”。因此我们选
用第二种方案进行本次课程设计
程序模块原理介绍:
分频器
由于 cyclone IV 板载系统时钟为 50MHz,时钟频率过大,无法表现出程序效果(或
者效果不明显),所以我们需要分频。
分频器原理:以系统时钟上升沿为标准,对系统时钟的上升沿计数,并给出一个
信号变量(或普通变量)给出初值,计够一定次数以后对其变量电平反转,即通
过电平反转重新造出来一个方波,以达到分频的目的。例如:对 50MHz 时钟二
分频,就是对系统时钟上升沿计数,当机构 2499999 个数时对电平变量 chz1 进
行反转,即可得到一个以 0.5ms 为周期的方波,则分频计算公式:
f 分频后的频率 =
分频器程序:
(系统时钟)
数上升沿数出来的数字
ck:PROCESS(CLK)
BEGIN
IF RISING_EDGE(CLK) THEN
--分频器程序
IF T="0000011010111100000111111" THEN—此处数值没有具体计算
T<="0000000000000000000000000";
CLK1HZ<=NOT CLK1HZ;
ELSE
T<=T+1;
END IF;
END IF;
END PROCESS CK;
数字扫描模块
结构体中数字扫描:将数字扫描模块写在结构体中,使 FPGA 在运行程序时能够
循环扫描数字,使数码管高速滚动数字。达到每个在暂停时,停止的每个数字具
有等可能性。
结构体中数字扫描:
OUTPUT<="1111001"WHEN INPUT="0001"ELSE—本程序写在结构体的 begin 下
进程中数字扫描:定义中间变量,对其进行 1-6 的循环加一计数,然后再将其送
到数码管显示。
"0100100"WHEN INPUT="0010"ELSE
"0110000"WHEN INPUT="0011"ELSE
"0011001"WHEN INPUT="0100"ELSE
"0010010"WHEN INPUT="0101"ELSE
"0000011"WHEN INPUT="0110";
进程中数字扫描:
IF (CLK1HZ'EVENT AND CLK1HZ='1')THEN
IF (A='1' AND B='1') THEN
TMP:=TMP+1;
IF (TMP=7) THEN
TMP:=1;
END IF;
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;
END IF;
END IF;
按键暂停模块
本次课程设计我们想用拨码开关以代替按键,本以为拨码开关不需要按键消抖但
最终的实验效果却不尽如人意,仍需要按键消抖,所以本次设计时我们改了一下,
利用两个按键对其进行暂停。如果用一个按键或拨码开关,必须要加按键消抖,
否则会有一定干扰。
消抖原理:类似于 51 单片机按键消抖,先检验其是否按下,若被按下则延时一
定时间,将其电平振荡的时间“滤”掉(在 FPGA 则数 5ms 的系统时钟过滤掉电
平振荡的时间)。
按键暂停以及存储程序:
IF (A='0') THEN
TIM:=TIM+1;
IF (TIM=1) THEN
RAN1<=TMP;
ELSIF (TIM=2) THEN
RAN2<=TMP;
END IF;
END IF;
注意:本模块程序未加按键消抖程序,如用单一按键需对按键加消抖程序。
一个按键的暂停草稿程序(加有消抖,但并未实践)
IF (A='0') THEN
IF RISING_EDGE(CLK) THEN
IF T="0010011010111100000111111" THEN--此处数值没有具体计算
T<="0000000000000000000000000";
ELSE
T<=T+1;
END IF;
END IF;
WAIT UNTIL(T=”0010011010111100000111111”);
IF(A=”0”)THEN
TIM:=TIM+1;
IF (TIM=1) THEN
RAN1<=TMP;
ELSIF (TIM=2) THEN
RAN2<=TMP;
END IF;
END IF;
END IF
比较模块
在程序内部定义两个变量(由于总开关为闭合状态所以不用考虑掉电保护问题),
用于存储先后两次按键按下的数字,然后对其变量进行比较若前者较大映射到
LED 则最后两个灯显示为“亮”、“灭”,反之后者大则 LED 显示为“灭”、“亮”。
比较模块程序:
compare:PROCESS(RAN1,RAN2)
BEGIN
IF (RAN1>RAN2) THEN
LED<="01";
ELSIF (RAN1
附录(完整程序):
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY test IS
PORT(CLK,A,B: IN STD_LOGIC;
OUTPUT: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
WEI:OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
LED: OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
END test;
ARCHITECTURE behave OF test IS
SIGNAL T:STD_LOGIC_VECTOR(24 DOWNTO 0);
SIGNAL INPUT:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL CLK1HZ:STD_LOGIC;
--SIGNAL LED1:STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL RAN1:INTEGER:=0;
SIGNAL RAN2:INTEGER:=0;
--SIGNAL FLAG:INTEGER RANGE 1 TO 3;
BEGIN
WEI<="01";
OUTPUT<="1111001"WHEN INPUT="0001"ELSE
"0100100"WHEN INPUT="0010"ELSE
"0110000"WHEN INPUT="0011"ELSE
"0011001"WHEN INPUT="0100"ELSE
"0010010"WHEN INPUT="0101"ELSE
"0000011"WHEN INPUT="0110";
(CLK1HZ,A,RAN1,RAN2,B)
chouyang:PROCESS
VARIABLE TMP:INTEGER:=0;
--VARIABLE RAN1:INTEGER:=0;
--VARIABLE RAN2:INTEGER:=0;
VARIABLE TIM:INTEGER:=0;
BEGIN
IF (CLK1HZ'EVENT AND CLK1HZ='1')THEN
IF (A='1' AND B='1') THEN
TMP:=TMP+1;
IF (TMP=7) THEN
TMP:=1;
END IF;
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;
END IF;
END IF;
IF (A='0') THEN
TIM:=TIM+1;
IF (TIM=1) THEN
RAN1<=TMP;
ELSIF (TIM=2) THEN
RAN2<=TMP;
END IF;
END IF;
--END IF;
END PROCESS chouyang;
compare:PROCESS(RAN1,RAN2)
BEGIN
IF (RAN1>RAN2) THEN
ELSIF (RAN1