课 程 设 计
课程设计名称: EDA课程设计
专 业 班 级 计科1601
学 生 姓 名 : 刘赫喃
学 号 : 2016317200107
目 录
摘要:
拔河游戏机由分频模块、按键扫描模块、计分模块、响铃模块、动态扫描模块、数码管选择模块以及译码模块组成,把输入20MHz时钟晶振信号分成合适频率的时钟输入进各个模块,开始游戏后,令双方按下按键,即可完成项目目标。
该设计使用Verilog HDL语言,完成拔河游戏机的实现。实用软件有QuartusII 13和ModelSim-Altera10.1d,在其环境下进行代码的编写编译以及现象仿真,而后烧写到CycloneIVE EP4CE30F23C7 FPGA实验板中,经过测试之后最终完成拔河游戏机的基本要求。
一、课程设计任务及要求
1、设计任务:
1)设计一个能进行拔河游戏的电路。
2)电路使用8个(或7个)发光二极管,开机后只有中间两个(一个)发亮,此即拔河的中心点。
3)游戏双方各持一个按钮,迅速地、不断地按动,产生脉冲,谁按得快,亮点就向谁的方向移动,每按一次,亮点移动一次。
4)亮点移到任一方终端二极管时,这一方就获胜,此时双方按钮均无作用,输出保持,只有复位后才使亮点恢复到中心。
5)用数码管显示获胜者的盘数。
6)附加,亮点移动到任意一方终点时,蜂鸣器报警提醒。
2、要求:
1)全部使用Verilog HDL硬件描述语言编写。
2)使用ModelSim-Altera软件进行仿真并对结果进行分析。
3)分析预期现象与实际现象之间产生差别的原因。
二、总体电路设计
1、拔河游戏机总体设计思想:
在20MHz的时钟信号作用下,经过分频模块分频成1KHz和10Hz的时钟信号,数码管动态扫描使用1KHz的频率,按键扫描使用10Hz的频率,通过按键扫描将双方的按键情况输入,并产生与之相对应晶体管亮点位置的位移,当位移至某一方的终点时,将按键使能端关闭,蜂鸣器报警开启,并使获胜方的分数加一,将分数通过译码在数码管上显示出来。可以通过游戏复位按键是晶体管亮点回到中心,通过分数复位按键使双方分数全部清零。
2、总体电路组成
CLK
分频模块
10Hz时钟
1KHz时钟
动态扫描模块
按键扫描模块
亮点移动
计分
数 码 管
译码
图2-1 拔河游戏机总体设计框图
三、模块设计
1、分频模块设计
设计思路:
由于FPGA芯片内部提供的时钟信号为20MHz,因此需要将其分频为10Hz,1KHz的信号,为后续的按键扫描,蜂鸣器报警以及数码管动态扫描显示提供时钟脉冲激励。通过设置模计数器cnt1khz与cnt10hz,在20MHz时钟脉冲下计数,并将输出时钟翻转,最终输出的分别是1KHz,10Hz的时钟分别名为clk1khz与clk10hz。
clk1khz
分频
cnt1khz
9999时翻转
CLK
20MHz
clk10hz
cnt10hz
999999时翻转
图3-1 分频模块框图
2、按键扫描与亮点位移模块设计
设计思路:
s1和s2是按键经过消抖后的输入变量,8位ledtemp是亮点当前位置的状态变量,初值为00011000,t是亮点位移的中间变量初值为3即亮点处在中间。配合时钟脉冲,并且游戏使能端开启的情况下,当key1按下key2不按下时,t自减1,当key1不按下key2按下时,t自加1,其他情况t保持不变。而后用case语句对应不同的t给予不同的ledtemp值,例如t=1意味着亮点应该左移了两位,给ledtemp赋值01100000。最后在always块之外用assign语句将ledtemp赋值给输出led。
clk10hz
S1/S2为0/1
不是
S1/S2为1/0
是
t = t - 1
不是
是
t保持原值
t = t + 1
t
Case(t)
ledtemp
led
图3-2 按键扫描与亮点位移框图
3、比赛计分以及游戏锁定模块
设计思路:
拔河游戏机在任意一方将亮点按动到自己那边终点后,所得分数就会加一,且此时按动游戏按键无效。按动按键使亮点到达终点时即t等于0或者等于6,0为左端终点,6为右端终点。故可以设定一个游戏使能变量k且赋初始值为1,计数使能变量j初始值为1,在k等于1时按键有效,然后每当t变化一次之后就对其进行判断,当t到达了0或者6,将游戏时能变量k置0,且对相应的分数变量left与right加一,并将计数使能变量j置0,同时在这之中放入BCD码转换模块,将二进制的left和right转换为十进制方便译码。
k=1
扫描按键
不是 t变化
t=0或t=6
是
t=0
不是
t=6
是
right=right+1
k=0
j=0
left=left+1
k=0
j=0
图3-3 比赛计分与游戏锁定框图
4、获胜报警模块
设计思路:
在时钟脉冲激励下,检测并判断t的值,若t等于0或6,蜂鸣器变量ring置1,是蜂鸣器报警。
clk1khz
t=0或t=6
是
ring保持
ring=1
图3-4 获胜报警模块框图
5、动态扫描、数码管选择与译码模块
设计思路:
通过绑定三个通选信号,对8个数码管进行扫描。在代码中设定输出q以及与其对应的中间变量qtemp,赋予初值为0,令其在1KHz的时钟下自加一,而当其等于7时置零。选择译码管使用case语句,在q所对应的数码管上赋予希望输出的值,即可完成选择。Case语句对应相应数字的段码完成译码。
qtemp=qtemp+1
1khz时钟
qtemp=0
qtemp=7
不是
是
qtemp=0
图3-5 动态扫描模块框图
6、按键消抖模块
设计思路:
按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。所以在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象我们需要将其消抖。不断地检测输入信号,与上个及上上个信号进行或运算,除非连续出现三个低电平才能说出现下降沿认为是按键按下。
四、管脚绑定
表一 管脚绑定
| Node Name | Direction | Location |
| a | output | PIN_W10 |
| b | output | PIN_V10 |
| c | output | PIN_U10 |
| d | output | PIN_T10 |
| e | output | PIN_V11 |
| f | output | PIN_U11 |
| g | output | PIN_T11 |
| led[7] | output | PIN_U8 |
| led[6] | output | PIN_AB8 |
| led[5] | output | PIN_U7 |
| led[4] | output | PIN_V7 |
| led[3] | output | PIN_W7 |
| led[2] | output | PIN_Y7 |
| led[1] | output | PIN_AA7 |
| led[0] | output | PIN_AB7 |
| Ring | output | PIN_A20 |
| q[2] | output | PIN_AA8 |
| q[1] | output | PIN_Y10 |
| q[0] | output | PIN_AA10 |
| clk | input | PIN_G22 |
| key1 | input | PIN_E12 |
| key2 | input | PIN_E13 |
| rst_n | input | PIN_T2 |
| rsts_n | input | PIN_T1 |
2、8位led对应8位发光二极管。
3、Ring为对应蜂鸣器。
4、3位q为数码管通选信号。
5、clk绑定20MHz时钟。
6、key1、key2为双方玩家输入按键。
7、rst_n、rsts_n分别为发光二级管与游戏使能端的复位以及游戏分数清零的按钮。
五、仿真及FPGA开发板调试
1、rst_n对使能端的复位
在rst_n一开始为高电平时,j、k、t变量没有给赋值所以为高阻态,而当rst_n复位为低电平之后就对他们进行了赋值,使三个变量j=1、k=1、t=3。
图5-1 rst_n复位仿真图像
2、不同按键状态的led变化
当左边玩家按下按键右边玩家没有按下时,即key1为0、key2为1则led应该一直往左移直到11000000停止,而当右边玩家按下按键左边玩家没有按下时,即key1为1、key2为0则led应该一直往右移直到00000011停止,其他情况时led保持初值00011000不变。
图5-2 key1/key2为0/1时led仿真图像
图5-3 key1/key2为1/0时led仿真图像
3、计分与蜂鸣器的报警
在rst_n置0将led复位后,再将rsts_n置0将left和right同时置0,而后移动led。当led位移到最左端或者最右端时,停止移动,并且蜂鸣器置1,最左端则left加一最右断则right加一。
图5-4 左边玩家获胜仿真图像
图5-5 右边玩家获胜仿真图像
六、学习体会与小结
参照别人的EDA课程设计让我学到了很多东西,之前的实验的内容相比课程设计实在是实验仅仅只是一个小模块,课程设计确实众多模块合成一个大的工程。不光是对EDA所学知识的检验,同时也是对我们细心程度以及耐心的极大考验。从得到课题,再到查找资料,代码编写,仿真以及烧写到板子上调试,每一步都不简单,每一步都会涉及到方方面面,总的来说最后的完工真的是不容易。
在设计过程中有一些容易忽略的小问题,可能就会使得整个项目出错。比如说时序的选择、阻塞非阻塞赋值以及if语句case语句的其他情况考虑,在代码的编写过程中经常会出现的问题比如同一个变量一会儿使用阻塞赋值一会儿使用非阻塞赋值,或者是同一个变量在不同always块中被赋值,这些都是不允许的。还有就是代码的逻辑问题,可能你的代码编译出来没有错误,仿真貌似也是正确的图像,但是烧写到开发板上就是不对,那么就要考虑代码逻辑的问题了,在几个变量当中谁的优先级更高,判断语句嵌套是到底应该先满足那个条件等等。下载本文