数字电路与逻辑设计实验(下)
实验报告
课题名称:打地鼠游戏的设计与实现
学院:电子工程学院
班级:2013211202
姓名:
学号:
一. 设计课题及任务要求
1. 课题名称:打地鼠游戏的设计及实现
2. 任务要求:
1) 设计“打地鼠”游戏,采用8X8双色点阵显示游戏界面,其中游戏边界采用绿色LED显示,随机出现的地鼠采用红色LED显示,游戏有十六个洞穴。
2) 洞穴每次随机出现一个地鼠,每个地鼠最长保持时间为2秒,2秒后随机出现下一个地鼠,以4x4键盘的按键代表锤子,16个洞穴对应16个锤子,一旦锤子在2秒内击中地鼠,则地鼠消失,数码管计分器加1分,若锤子没有击中地鼠,则两秒后地鼠消失,用两个数码管显示游戏成绩,成绩到达10分时,游戏结束,点阵显示“V”。
3) 用两个数码管对整个游戏进行倒计时,当游戏超过59秒而成绩未达到10分时,游戏失败,点阵显示“X”。
4) 按复位键重新开始游戏,并开始倒计时。
二.系统设计
1.设计思路:采用自顶向下的设计原则。
首先对游戏的状态进行判断,整个游戏共应该有四种状态,重置状态,游戏状态,游戏成功状态,游戏失败状态。然后由这四种状态对其他模块进行控制。所以控制模块置于整体框图的中心,然后再考虑这四个状态分别由什么输入控制。
·重置状态:当拨动开关置高电平时,整个游戏进行重置,此时计分数码管应该有计分的初始显示,即00分,点阵显示重置画面,而计时的数码管置数60准备开始倒计时,当拨动开关置低电平时,游戏正式开始,转入游戏状态。
·游戏状态:此时计分数码管计分,倒计时数码管进行倒计时,点阵显示游戏界面,即6x6的绿色边界以及一个随机出现的红色地鼠。若在倒计时结束之前,计分数码管显示10分,则转入游戏成功状态,若倒计时结束时,尚未达到十分,则转入游戏失败状态。
·游戏成功状态:此时倒计时数码管停止计时,计分数码管显示10分,点阵显示绿色“V”。
·游戏失败状态:此时倒计时数码管和计分数码管不再继续工作,而点阵显示红色“X”。
2.整体分析:综上分析以及结合实际,得出整个工程大致需要的模块为:分频模块、倒计时模块、计分模块、数码管显示模块、点阵显示模块、状态控制模块、随机地鼠生成模块、键盘输出模块。
3.整体设计框图:
三.分模块设计
1.分频模块设计
1)需求分析:整个工程共需要四个频率,地鼠出现的频率为2秒一个,即需要一个0.5Hz的频率,而倒计时一秒减小一个十进制数,所以需要一个1HZ的频率,数码管的扫频和点阵的扫频为1000Hz,键盘防抖模块的扫频为100Hz,所以我采用级联分频的方式,将实验室25MHz的频率先通过25000倍分频分为1000Hz,再将1000Hz频率十分频分为100Hz,再将100Hz一百分频为1Hz,再讲1Hz频率分为0.5Hz。
2)模块代码:
3)模块仿真波形
为减少仿真时长,仿真时将分频系数依次调为2,3,4,实现分频依次为3分频,4分频,5分频。仿真波形如图所示,可由仿真波形看出分频模块实现分频功能。
2.倒计时模块:
1)功能分析:倒计时模块由状态控制模块控制。
重置状态时,进行置数60,游戏状态时,进行减计数,输出分为高位和低位,由上升沿出发,每个上升沿,个位数减一,个位数减至0时,个位数变成9,十位数减一。然后高位和低位进行七段数码管译码输出,设立一个计时结束标识,以反馈控制状态,当个位十位都为0时,倒计时结束,flag=1,否则,flag=0。
2)模块代码:
entity counter is --实体定义
port(clk:instd_logic;
c_state:instd_logic_vector(1 downto 0);
nixie_1:out std_logic_vector(7 downto 0);--高位译码输出
nixie_2:out std_logic_vector(7 downto 0);--地位译码输出
gameover:outstd_logic --计时结束flag
);
end counter;
architecture counter_1 of counter is
signal count_d:integer range 0 to 6;--十位信号
signal count_o:integer range 0 to 9;--个位信号
begin
counting: --倒计时进程
process(clk)
begin
if(c_state="00") then—重置状态置数60
count_d<=6;
count_o<=0;
gameover<='0';--flag置0
elsif(c_state="01") then
if(clk'event and clk='1') then
if(count_d=0 and count_o=0) then
gameover<='1';
elsif(count_o=0) then—地位为0,高位减一,低位变9
count_d<=count_d-1;
count_o<=9;
else
count_o<=count_o-1;
end if;
end if;
end if;
end process;
nixie_present: --译码输出进程
process(count_d,count_o)
begin
if(c_state="00") then –重置状态译码显示全灭
nixie_1<="00000000";
nixie_2<="00000000";
elsif(c_state="10" or c_state="11") then—游戏结束八段全亮
nixie_1<="11111111";
nixie_2<="11111111";
elsif(c_state="01") then—游戏状态显示十进制倒计时计数
case count_d is
when 6=>nixie_1<="01111101";--高位译码
when 5=>nixie_1<="01101101";
when 4=>nixie_1<="01100110";
when 3=>nixie_1<="01001111";
when 2=>nixie_1<="01011011";
when 1=>nixie_1<="00000110";
when 0=>nixie_1<="00111111";
when others=>nixie_1<="00000000";
end case;
case count_o is
when 9=>nixie_2<="01101111";--低位译码
when 8=>nixie_2<="01111111";
when 7=>nixie_2<="00000111";
when 6=>nixie_2<="01111101";
when 5=>nixie_2<="01101101";
when 4=>nixie_2<="01100110";
when 3=>nixie_2<="01001111";
when 2=>nixie_2<="01011011";
when 1=>nixie_2<="00000110";
when 0=>nixie_2<="00111111";
when others=>nixie_2<="00000000";
end case;
else null;
end if;
end process;
end counter_1;
3)模块仿真
·重置状态下,高位输出6,由数码管译码输出可以看出高位输出正确。
·重置状态下,计时低位输出0。
·游戏失败时,计时低位输出为全亮
·游戏进行中,低位每遇到一个时钟上升沿就自减1译码输出,仿真波形中游戏状态持续的时间只有五个时钟周期,所以显示低位变换了五次,而高位没有变换,仿真实现功能。
然后看state=10状态,即游戏成功时候,译码管输出显示全亮,即停止计时。当游戏进行到失败状态时,flag置1。
由仿真波形可以看出,状态控制模块控制倒计时模块的功能得以实现。
3.计分模块
1)功能分析:计分模块由状态控制模块控制,输出反馈控制状态。
重置状态,计分数码管置零。游戏状态,当锤子敲中地鼠,计分加一,计分加至十时,反馈输出为1,控制状态模块将状态转换为游戏成功模块。时间结束时,计分不够十,反馈输出为0,结合倒计时模块的计分输出反馈为1,共同控制状态模块将状态转换为游戏失败状态。
计分模块由三部分组成,分别是判断是否得分模快,该模块将地鼠位置坐标与键盘坐标进行比较,当坐标吻合,即击中地鼠时,输出高电平,否则输出低电平,输出为一个由高低电平组成的脉冲。其次是得分计数模块,得分计数模块的输入信号为判断模块的输出信号,在游戏状态时,当有高电平输入时,计分加一,当没有高电平输入时,计分不变,同时设立一个输出flag,作为状态转换的反馈输入信号,当计分为十,则输出1,将状态转为游戏成功态,当计分不足十时,输出0,继续游戏或游戏失败。其次是显示模块,将计分的分数译码输出在数码管上显示。
2)模块代码:
·判断模块
·得分计数模块
·显示输出模块
3)模块仿真
·重置状态计分显示为00,flag=0
·游戏状态,判断击中输出一次高电平,计分输出加1,flag=0
·成功状态,flag=1,计分不变
·游戏失败状态,flag=0,计分结束
·显示模块仿真,成功实现译码功能。
由计分模块(含判断模块,得分模块,显示模块)的仿真波形可以看出,计分模块实现由不同状态控制不同计分模块的功能,在数码管上成功译码显示,并且输出flag反馈控制状态,计分模块功能得到实现。
4.数码管控制模块
1)功能分析:由题目要求可知,需要在实验板上显示4个数字,其中两个管子显示得分,两个管子显示倒计时。但由于七段数码管一次只能显示一个,所以需要一个高频的扫描控制,依次点亮每个数码管,然后利用视觉暂留的效果,使得看起来有四个数码管同时点亮。
在此设置第一二个数码管为计分显示,第三四个数码管为倒计时显示。该模块较小,由信号控制写在顶层文件中,不单独再写一个文件模块。
2)模块代码:
nixie_scan:process(link_clk_1kh)—用顶层文件定义的信号来传递
begin
if(link_clk_1kh'event and link_clk_1kh='1') then--1kHZ--时钟进行扫描
case link_out_scan_nixie is
when "011111"=>link_out_scan_nixie<="101111";out_nixie<=out_point_nixie_2;
--第二个数码管显示计分地位
when "101111"=>link_out_scan_nixie<="110111";out_nixie<=nixie_tube_1;
--第三个数码管显示计时高位
when "110111"=>link_out_scan_nixie<="111011";out_nixie<=nixie_tube_2;
--第四个数码管显示计时低位
when "111011"=>link_out_scan_nixie<="011111";out_nixie<=out_point_nixie_1;
--第一个数码管显示计分高位
when others=>link_out_scan_nixie<="011111";out_nixie<=out_point_nixie_1;
end case;
end if;
end process;
5.控制模块
1)功能分析:该模块主要实现状态转换状态,由之前的分析可以看出整体工程的点阵显示模块,计分模块和倒计时模块均受状态的控制,而状态的判断又由计分模块和倒计时模块的反馈输出共同控制。
计分/倒计时 | Reset=1 | 1/0 or 1/1 | 0/1 | 0/0 |
状态编号 | 00 | 10 | 11 | 01 |
状态 | 重置 | 游戏成功 | 游戏失败 | 游戏进行状态 |
2)模块代码
3)模块仿真
由仿真波形可以看出当reset=1时,state输出为00;
当reset=0时,由计时反馈和计分反馈决定状态的转换
计时为1,计分为0时,state输出为11,代表游戏失败。
计时为1,计分为1时,state输出为10,代表游戏成功。
计时为0,计分为0时,state输出为01,代表游戏进行中。
计时为0,计分为1时,state输出为10,代表游戏成功。
由该模块的仿真波形可以看出,该模块实现状态控制功能。
6.随机地鼠生成模块
1)功能分析:该模块需要满足最多两秒内产生一个地鼠,当地鼠被击中时,被击中的地鼠消失,在新的地方生成新的地鼠,所以此处设置一个信号new,将得分信号与2秒的时钟信号进行异或,然后通过new信号的上升沿生成新的随机序列,随机序列为7 downto 0的一组向量,由倒数两位随机决定地鼠坐标的行输出,由倒数三四位决定地鼠列坐标的输出。
需要实现的效果是得分后,即地鼠被击中后,便产生一个新的地鼠,而地鼠未被击中时,上升沿由2秒时钟信号触发,即两秒生成一个新的地鼠。
同样,该模块同样受到状态的控制。
当重置状态时,初始序列设为10011010。游戏进行状态时,则根据上述判断产生新的地鼠。
2)模块代码
entity r_series_generator is
port (
r_state:instd_logic_vector(1 downto 0); --状态控制
clk:instd_logic; --1秒的时钟信号输入
catch:instd_logic; --得分信号脉冲输入
row_out:outstd_logic_vector(3 downto 0); --地鼠坐标行输出
column_out:outstd_logic_vector(3 downto 0)); --地鼠坐标列输出
end r_series_generator;
architecture behavioral of r_series_generator is
signal r_series:std_logic_vector(7 downto 0); --随机序列
signal mice_time:std_logic; --2秒的时钟信号
signal trick:std_logic; --判断是否被击中的信号
begin
mouse_time:
process(clk) --将1秒的时钟信号分频为2秒的时钟信号
begin
if(clk'event and clk='1') then
if(mice_time='1') then
mice_time<='0';
elsif(mice_time='0') then
mice_time<='1';
else mice_time<='0';
end if;
end if;
end process;
trick<=mice_timexor catch ; --设立该信号对击中进行判断
series_generate: --生成随机序列
process(trick)
begin
if(r_state="00") then --游戏一旦被重置,随机序列进行初始
r_series<="10011010";
elsif(r_state="01") then --游戏状态,由得分信号的上升沿触发新的地鼠
if(trick'event and trick='1') then --由标识的上升沿进行触发
r_series<=r_series(6 downto 0)&(r_series(0) xorr_series(7));--随机序列的产生
end if;
end if;
output_r: --随机坐标输出序列
process(r_series) --通过随机序列随机变换的后四位随机坐标
begin
case r_series(1 downto 0)is --后两位随机行坐标
when "00"=>row_out<="0001";
when "01"=>row_out<="0010";
when "10"=>row_out<="0100";
when "11"=>row_out<="1000";
when others=>row_out<="0000";
end case;
case r_series(3 downto 2) is --倒数三四位随机列坐标
when "00"=>column_out<="0001";
when "01"=>column_out<="0010";
when "10"=>column_out<="0100";
when "11"=>column_out<="1000";
when others=>column_out<="0000";
end case;
end process;
end behavioral;
3)模块仿真:
·在重置状态下,随机序列初始化,此时行列输出值固定都0100
·游戏进行状态中,随机序列由输入时钟信号和捕捉信号异或后得到的信号触发,产生随机输出
由仿真波形可以看到该模块的功能得以实现。
7.点阵显示模块
1)功能分析:同样,由整机的状态来设计各个状态下点阵的显示界面
重置状态,设计开机画面,开机时点阵显示笑脸。
游戏进行状态,显示游戏画面,即绿色6X6边界,中间闪烁一个随机出现的地鼠。
游戏成功状态,显示胜利画面,绿色字母“V”。
游戏失败状态,显示失败画面,红色字母“X”。
2)点阵显示原理:原理图:
实验室使用的点阵为共阴点阵,当A行电平输入为0,B列电平输入为1时。对应的A行B列处的点被点亮,实验室使用的点阵为双色点阵,当输出的列为red时,点亮红色的点,当输出的列为green时,点亮绿色的点,当红绿同时输出,则显示橙色。
由于要显示的画满并不只是几个行列不交叠的点,而是复杂的图案,所以选择行扫描的方式对点阵进行显示,行不断用高频信号进行逐行扫描(此处用1KHZ),利用人眼的视觉暂留,只要周期足够小,看起来就像是一个稳定的图案。而且采用逐行扫描远比逐点扫描占用FPGA资源要少。
3)模块代码:
·实体定义部分
·开机画面显示
通过行扫描实现—重置状态
·游戏进行界面显示
·游戏胜利状态显示
·游戏失败模块
4)模块仿真
·重置状态。行输出显示为逐行扫描,列输出逐行对应一个输出向量组,组成一个笑脸图形。
·游戏状态,红色列输出由地鼠的随机坐标控制,逐行扫描,只有一个点亮,即红色的随机地鼠。实现随机地鼠的显示
·游戏状态,绿色列输出。在游戏状态下,通过逐行扫描,对应列输出6*6绿色边界。
·游戏成功状态,绿色列输出,显示“v”。
·游戏失败状态,红色列输出,显示“X”。
由该模块的仿真可以看出,在各个状态,模块实现对应功能。
8.键盘模块
1)功能分析:
该模块由两个部分组成,其一为键盘消抖模块,其二为按键确定模块。
2)原理分析
·键盘消抖:通常开关为机械开关,断开或闭合时,由于机械触点的弹性作用,在闭合和断开的瞬间有一连串的抖动,为了消除其带来的影响而进行消抖模块的设置。
·按键确定模块:为了实现判断按键的位置,以便进一步判断键盘坐标与地鼠坐标是否对应,以输出得分脉冲给计分模块。所以判断按键位置使一步非常重要的步骤,按键的确定和点阵的显示原理有着相似之处,均是逐行或逐列扫描,以确定具体坐标,此处我采用的是键盘列扫描,即通过时钟信号让列的低电平逐行变化,当有行坐标输入为低电平时,确定行与列的输出,假设第一行电平为0,则规定行输出为1110,而列输出即为当时的扫描列坐标,通过这样的方式将按键按位置转换为一个二维数组输出。
然后将确定的坐标输入到消抖模块中进行消抖,消抖后输出的坐标为最终按键坐标,输入判断得分模块与地鼠坐标进行比较。
键盘扫描原理图:
当行和列的电平均为0时,判断为该行该列的按键被按下,即可确定按键坐标。
3)模块代码:
·判断模块
·消抖模块代码
4)模块仿真
·消抖模块
·逐列扫描,列输出
在行输入为1110时,即判断出是第4行被按下时,输出行坐标为0001,输出列坐标为当前的列坐标,取反输出是为了在得分判断模块与地鼠的坐标对应,因为地鼠坐标里面只有一个高电平,而键盘坐标却只有一个低电平,所以将键盘坐标取反。
在航输入为1111时,即没有任何一行的按键被按下时,列坐标输出显示1111,行坐标输出为0000(1111取反)。
由仿真波形可以看出按键判断模块实现了该模块的需求。
9.总体模块
1)元件实例连接分析
写完各个模块之后,需要用信号来实现将各个模块连接在一起。各个模块在顶层文件中相互控制,通过反馈和加计数等方式实现整个工程的总体功能。我采用的是元件实例化的方式,让各个分模块在总工程里各司其职。内部用信号进行间接。具体逻辑为:
·分频模块的三个级联输出分别为1khz,100hz,1hz,将1khz接入点阵的扫描模块的输入,将100hz的输出接入键盘模块的扫描和防抖模块,将1hz的输出接入倒计时模块和随机地鼠生成模块,再在随机地鼠模块内部进行一次分频,将1hz分为0.5hz。
分频模块的输入为实验板的晶振输入。
·倒计时模块的输入接1Hz的分频和状态控制模块的输出,由状态模块的输出控制倒计时模块的工作。
两个输出端为数码管显示输出和游戏结束标识,两个七段数码管显示输出接入顶层文件中的数码管显示模块,通过数码管显示,游戏结束标识输出接入状态控制模块,对状态模块进行反馈控制。
·计分模块的输入为得分脉冲输入和状态输入,得分脉冲由判断模块输出,即打中就输出高电平形成脉冲在得分模块进行累加。
计分模块的输出为累加的分数输出和游戏结束标识,得分输出模块输入进得分显示模块译码转换为七段数码管输出,再输入到顶层文件的数码管扫描模块进行输出。计分模块的另一输出为游戏结束标识,输入到游戏状态控制模块对状态进行反馈控制。
·数码管控制模块,数码管控制模块置于顶层文件内部,负责将得分和计时通过扫描和视觉暂留的效果同时显示在四只数码管上。
·控制模块的输出只有一个端口,是一个1downto0的向量组,代表四种不同的状态,分别输入进随机地鼠生成模块,点阵显示模块,倒计时模块,计分模块,通过四种状态分别控制上述模块进行工作。
而控制模块的输入为复位键输入和计时模块输出的倒计时结束标识以及计分模块输出的计满十分标识,通过这三个输入判断整个工程处于何种状态,进而输出状态控制其他模块。
·随机地鼠生成模块的输入为控制模块输出的当前状态和分频模块1Khz的分频输出,以及判断模块的得分脉冲输入,在模块内将1khz分频为0.5hz,再通过异或时钟与得分脉冲产生新的脉冲的上升沿来控制新的地鼠产生。
输出为两个3downto0的向量组,分别输入进判断模块和点阵显示模块,在点阵显示模块作为地鼠坐标以显示地鼠,在判断模块用于与键盘的坐标进行比较以判断是否得分。
·点阵显示模块的输入接1KHz的分频模块输出,用作点阵显示的扫描频率,接随机地鼠显示模块输出的地鼠坐标,用于在游戏进行状态时显示地鼠坐标,接控制模块输出的状态用于切换点阵的显示画面。
点阵显示模块的输出为两个7downto0的向量组,分别接入实验板的点阵的行控制端口和列控制端口,用以控制实验板上点阵的显示。
·键盘模块的输入接100hz的分频输出用于列扫描的频率,接实验板的键盘行输入端口,当实验板上的按键被按下时,配合列扫描,便可判断出被按下的键的位置。
输出端口为键盘的坐标,将该输出接入防抖模块用于消抖后再输出,消抖模块输出的键盘坐标作为键盘坐标的最终输出,输入进判断模块,将键盘坐标与地鼠坐标进行判断,从而产生得分脉冲。
2)RTL VIEWS
·分频模块原理图
·控制模块原理图
·计分模块原理图
·消抖模块原理图
·键盘模块原理图
·判断模块原理图
·计分模块原理图
·计分显示模块原理图
·随机地鼠生成模块原理图
·点阵显示模块原理图
·总连接RTL VIEWS(由于图片过大,显示不清晰,可在工程中编译查看)
3)部分代码
·端口设置
·元件实例化之部分模块定义(其他模块同)
·内部信号定义
·数码管扫描显示部分代码
nixie_scan:process(link_clk_1kh)--数码管扫描显示模块
begin
if(link_clk_1kh'event and link_clk_1kh='1') then
case link_out_scan_nixie is
when"011111"=>link_out_scan_nixie<="101111";out_nixie<=out_point_nixie_2;
--在第二个数码管上显示计分低位
when"101111"=>link_out_scan_nixie<="110111";out_nixie<=nixie_tube_1;
--在第三个数码管上显示计时高位
when"110111"=>link_out_scan_nixie<="111011";out_nixie<=nixie_tube_2;
--在第四个数码管上显示计时低位
when"111011"=>link_out_scan_nixie<="011111";out_nixie<=out_point_nixie_1;
--在第一个数码管上显示计分高位
Whenothers=>link_out_scan_nixie<="011111";out_nixie<=out_point_nixie_1;
end case;
end if;
end process;
out_scan_nixie<=link_out_scan_nixie;--将输出赋给实验板上的cat0-cat5
·元件实例化之连接map部分代码(其他模块同)
u_counter_down: counter_down port map(clk=>wclk,--分频模块连接map
clk_1kh=>link_clk_1kh,--将分频模块端口输出赋给信号
clk_1hh=>link_clk_1hh,--以便信号带着值在各个模块之间进行传递
clk_1oh=>link_clk_1oh);
u_control: control port map(ctr_time_counter=>link_time_over,--控制模块连接map
ctr_point_counter=>link_point_over,--计分模块游戏结束标识接入控制模块
reset=>reset_or_start,--复位控制输入
state=>link_state);--输出赋给信号,以控制其他模块
u_r_series_generator: r_series_generator port map(--随机地鼠生成模块map
r_state=>link_state,--状态输入接状态控制模块状态输出
clk=>link_clk_1oh,--分频输入接分频模块输出
catch=>link_onepoint,--得分脉冲输入接得分脉冲信号
row_out=>link_r_row,--将输出行坐标赋值给行坐标输出信号
column_out=>link_r_column);--将输出列坐标赋值给列输出信号
u_counter: counter port map(clk=>link_clk_1oh,--倒计时模块连接map
c_state=>link_state,--状态输入接状态信号
nixie_1=>nixie_tube_1,--倒计时高位信号
nixie_2=>nixie_tube_2,--倒计时低位信号
gameover=>link_time_over);--输出接时间结束标识
u_screen: screen port map(s_state=>link_state,--点阵显示模块连接map
clk=>link_clk_1kh,--输入接1000Hz分频信号
r_row=>link_r_row,--输入接地鼠行坐标信号
r_column=>link_r_column,--输入接地鼠列坐标信号
column_red=>outr_pos_columns,--输出赋给点阵列红色输出信号
--接实验板的点阵列控制端口
column_green=>outg_pos_columns,--输出赋给点阵的绿色列输出信号
row_scanning=>out_pos_rows);--行扫描赋给点阵的行输出信号,接实验板点阵行控制端口
u_point_counter: point_counter port map(j_catch=>link_onepoint,--计分模块连接map
p_state=>link_state,--状态输入接状态信号
point_out=>link_points,--计分输出赋给计分信号,用于计分显示模块输入
gameover=>link_point_over);--输出游戏结束标识赋给满十分信号
u_judgment: judgment port map(r_row=>link_r_row,--判断模块连接map
r_column=>link_r_column,--输入接地鼠行坐标信号
in_row=>link_in_row,--输入接地鼠列坐标信号
in_column=>link_in_column,--键盘消抖输出列信号
one_point=>link_onepoint);--键盘消抖输出行信号
u_filter: filter port map(clk=>link_clk_1hh,--消抖模块连接map
idata_row=>link_pos_row,--输入接键盘行信号
idata_column=>link_pos_column,--输入接键盘列信号
odata_row=>link_in_row,--输出赋给消抖输出信号
odata_column=>link_in_column);
四.功能说明及资源利用情况
1.功能说明:
经下载,该工程各模块协作实现了以下功能:经下载后调至合适的频率,拨动重置开关能够显示开机画面,开机画面为绿色边界的框和红色的笑脸。此时数码管显示为00 60,分别为计分显示和倒计时显示,当按下游戏开关后,进入游戏状态。
此时,数码管的计时模块实现60秒倒计时,点阵显示6*6绿色边界,中间出现红色的随机地鼠,若不击中,则2秒消失,在下一个地方产生新的地鼠。若击中,则立刻消失,且计分数码管显示加1。若在60秒内到达十分,则切换至游戏成功状态。
此时,点阵显示绿色“V”,而数码管显示当前得分和88。
若在60秒内没有得到10分,则转入游戏失败状态,此时点阵显示红色“X”。
2.资源利用情况
编译后可以看到该工程的使用逻辑元件262个,占总逻辑元件个数的21%。
使用管脚48个,占总管脚的41%。
未使用任何UFM块。
3.总工程
五.故障及问题分析
1.问题分析:
本次试验中我依次遇到以下问题及难点
·总体框图构造及顶层实体的设计 状态的确定于设计
随机地鼠的产生 按键位置确认
下载以后点阵显示凌乱 最后下载游戏成功状态不显示
2.解决办法
1)从选题到真正着手准备这个题目,首先要先对模块需求进行分析,分析出要实现各个模块具体需要哪些模块,而这些模块又是如何相互间控制和反馈的,哪个模块的输出是哪个模块的输入,总体实体需要的输入需要接入哪里,输出由哪里控制。必须先将思路理清楚,我觉得画原理图对实现整体判断有很大帮助,首先想到2秒的地鼠1秒的倒计时,而实验室晶振是25兆,所以首先想到的是分频模块的设计。先设计分频模块的端口,输入接实验板的晶振,一开始并没有想到点阵的显示,键盘的确立以及数码管的显示都需要扫描频率,所以没有想到级联输出三个频率,后来依次确认了需要一个显示模块,了解点阵显示原理和键盘原理之后将分频模块加了一个扫频输出端。
2)再设计显示模块的时候因为想到需要一个开机画面以及需要一个游戏画面和游戏胜利失败状态的显示画面,就开始思考如何在这些界面中切换呢,于是设立了状态控制模快,而状态又是由倒计时和计分模块控制,因此便在之前设计的倒计时和计分模块分别设计了flag,输入至状态模块对状态进行控制。依次写出各个模块的名称和需要实现的端口,以及预设的输入输出管脚。
3)当大概所有小分模块设立好以后,便开始依次按功能具体实现各个小模块。分频和倒计时模块都没有遇到太大问题。问题出在随机地鼠的产生。
4)由于地鼠只有一个,所以输出的8位向量的行电平智能有一个0,列向量只能有一个1。
上网搜到的大多数方法都是通过生成一个范围为0到15的随机数,然后每个随机数依次对应一个被点亮的地鼠。但是问题在于如何在地鼠被击中的同时让地鼠消失呢。我咨询了许多同学,了解到他们使用的办法是设立一个地鼠被击中的画面,当地鼠被击中时,输出画面为只有绿色边界。我认为这种方法也可取,但对于我最初设立的四种状态来说是矛盾的,我想将这种情况包含在游戏状态中,于是我决定将得分反馈到随机序列的生成上来
设立一个New信号=point XOR clk,再由new的上升沿触发产生新的随机序列。
只要在一个时钟周期内有击中,new就会及时产生上升沿从而改变序列,产生新的地鼠,若没有击中地鼠,就由时钟上升沿触发2秒产生一个新的地鼠。
5) 还有一个在下载时常常出现的问题就是点阵和键盘的管脚设反,导致点阵显示乱了,仔细分析各个管脚对应的输出端口,看清点阵和键盘坐标,多尝试几次就解决了。
6) 程序调试到最后时,游戏重置状态和游戏进行状态和游戏失败状态都能够成功,但此时出了一个小bug,就是游戏成功状态显示的画面是绿色边界红色地鼠和“V”同时显示,即存在一个状态交叠,我分析了很久,才看出问题。
时间标记为1表示时间到,得分标记为1表示满10分
状态 | 成功 | 失败 | 进行 | 重置 |
时间标记 | 1/0 | 1 | 0 | Reset=1 |
得分标记 | 1 | 0 | 0/1 | |
分析了表格以后才发现自己设计判断状态的逻辑确实有问题,成功态和进行态确实存在一个状态的交叠,即时间为0,得分为1时,同时属于两个状态,于是点阵同时显示两个画面,于是将代码的状态判断模块进行调整,将该类情况明确归属于成功态。调试后成功。
六.总结和结论
总结:在本次实验中,通过对总体框架的设计,依据自顶向下的设计原则,确定小模块的功能需求,依次编写各个模块的代码,并仿真检验各个模块,实现各个小模块的具体功能,最后通过在实体文件中将各个小模块元件实例化,整理map。编译总工程,然后不断的调试以及修改编译错误,最后在实验室又调试了大概一周,不断的改正实际中遇到的错误,最终实现打地鼠的游戏功能,使其满足设计要求,还增加了开机画面。
尽管实验过程很艰辛,且最后也还存在部分不足,但在这一过程中,我确实有很大的收获。
首先复习与巩固了quartus的使用,并掌握了采用分模块完成设计的方法,学到了更多上学期使用quartus时没有接触的功能,大致了解了状态机,以及信号和变量的区别,了解了点阵的发光原理以及点阵显示图形的基本原理,了解了键盘的扫描原理以及消抖功能实现的原理。了解了随机地鼠产生的原理。了解了从状态来处理问题的方法。巩固了vhdl语言的使用,复习了数电的相关知识。
除了在知识方面获的的收获,更重要的是在逻辑方面得到了锻炼,锻炼了自己独立设计与解决问题的能力,培养了自己思考问题的能力加强了自己对问题的分析能力,更好的运用逻辑解决事件。
最后是自己的心理素质也得到了改善,在一次次编译无法通过和一次次下载得不到想要的效果,甚至是管脚的顺序搅乱我心时。我懂得了越是混乱,我越要学会冷静,可以尝试把问题写在纸上,然后一层一层进行分析,找到问题然后解决问题。我也明白到知识与实际的相关的重要性,我们对知识的学以致用还有待提高。
本文来源:https://www.2haoxitong.net/k/doc/b62243a37e192279168884868762caaedd33bae5.html
文档为doc格式