北邮数字电路实验下猜数字l.docx_第1页
北邮数字电路实验下猜数字l.docx_第2页
北邮数字电路实验下猜数字l.docx_第3页
北邮数字电路实验下猜数字l.docx_第4页
北邮数字电路实验下猜数字l.docx_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

数字电路与逻辑设计实验(下)实验报告简易猜数字游戏机的设计与实现 班级: 姓名: 学号: 班内序号: 2015 年11 月 05 日一、 简易猜数字游戏机设计与实现的任务要求3二、 简易猜数字游戏机系统设计41. 设计思路2. 总体框图3. 分块设计三、 仿真波形及波形分析5四、 源程序(要有注释)81. 顶层源码(guessnum.vnd)2. 键盘源码(keyboard.vhd)3. 消抖源码(xiaodou.vhd)4. 点阵源码(dotmatrix.vhd)5. 数码管源码(display.vhd)6. 随机数源码(random.vhd)7. 蜂鸣器源码(beep_t.vhd)五、 功能说明及资源利用情况26六、 故障及问题分析27七、 实验总结30一、 简易猜数字游戏机设计与实现的任务要求实验基本要求: 1. 游戏规则:通常由两个人玩,一方出数字,另一方猜。出数字的人要想好一个没有重复数字的4 位数,不能让猜的人知道。 2. 数字设置:通过 4*4键盘进行 4位数字输入,在数码管(disp0disp3)上显示当前所输入的数字。通过设置确定键(btn1键)进行锁定,此时数码管上的数值消失,同时用点阵开始倒计时,即:初始状态点阵全亮,然后从右下角开始,由右到左、由下到上逐点逐排依次熄灭,间隔时间为 1s,共计64s。 3. 猜数字:可以通过 4*4 键盘进行 4 位数字输入进行猜数字,且每输入一位数字在数码管(disp0disp3)上显示当前所输入的数字,按确定键(btn2键)进行确认,此时要根据输入的这组数字给出几a几 b,其中: a前面的数字表示位置正确的数的个数,用disp5显示 b前的数字表示数字正确而位置不对的数的个数,用disp4显示 如正确答案为2134,而猜的人猜5314,则是1a2b,其中有一个4的位置对了,记为1a,而1和3这三个数字对了,而位置没对,因此记为2b,合起来就是1a2b; 接着猜的人再根据出题者的几a几b继续猜,直到猜中(即 4a0b)为止。 4. 若数字正确则显示猜数字成功,点阵显示“”笑脸;若输入数字错误系统仍然处于猜数字状态,点阵显示“x” ,并用蜂鸣器或led闪烁报警。 5. 若到点阵全灭时(64s结束)仍未猜出正确数字,游戏失败,点阵显示“囧” 。 6. 设置游戏机开关。 实验提高要求: 1. 若数字正确则显示猜数字成功,用蜂鸣器播放一段乐曲。 2. 随机产生数字,并不在数码管上显示,进行猜数字游戏,用点阵进行 64s计时,即点阵轮询熄灭两次,其他要求同基本功能 3、4 和5。 3. 自拟其他功能。二、 简易猜数字游戏机系统设计1. 设计思路这次实验主要用到了44键盘、88点阵、七段显示数码管及蜂鸣器。实验整体设计流程是:step1:编写并调试键盘;step2:编写并调试数码管和键盘;step3: 编写并调试点阵;step4:遍写并调试随机数;step5:编写并调试比较(随机数测);step6:编写顶层并调试。2. 总体框图顶层44键盘七段译码管显示88点阵随机数蜂鸣器消抖输入控制信号3. 分块设计首先,键盘输入数字(顶层文件获取键盘输入的数字并根据不同的输入信号做出相关判断与处理操作),通过列扫描(扫描频率为10k)的方式检测键盘的输入信号,根据扫描频率做一个计数器,计数周期为4,依次扫描列(1110、1101、1011、0111),列与行合并为一个八位数组,当八位数组中出现两个0时,表示键盘输入了数字,此时需将key_pressed(数码管显示信号)置1,对比出现八位数组中两个0出现的位置,可得出输入的数值。其次是防抖,由于按键按下,理想状态会根据按键时间的长短产生一个方波,但是实际上会产生很多毛刺,不利于检测按键的输入信号,对此需要做消抖处理。这部分代码的书写参考了网络上的资料,通过rs触发器,对按键输入信号做消抖处理。在本次试验中,按键均用到了消抖。第三个则是,数码管显示六位数字(顶层文件发送给数码管disp0-5六个数字,六位数码管分别显示六个数字),数码管扫描频率为10k,根据扫描频率做一个计数器,计数周期为8,当计数器数值为0-5时,分别显示0-5六个数码管的值,其他两个状态数码管不工作。数码管部分的另一功能则是对数字做七段译码处理。点阵模块(扫描频率10k,倒计时频率1hz),输入信号有dz、start、 wrong、 success(均由顶层文件赋值)。其中,dz为点阵开始工作的信号(持续高电平),由顶层文件赋值,start为一个只有一段为1的冲激,与dz信号同步。点阵开始工作后,64s倒计时开始,与此同时给列一个64位的数组,初始值都是1,每过1s,数组左移一位,赋值为0。点阵一共有四个状态,64s倒计时,从右到左,从下到上依次熄灭;成功显示“笑脸”;错误显示“x”;64s之后显示“囧”。点阵采用行扫描的显示方式,也是用扫描频率控制一个周期为8的计数器,每一个计数状态对应单个行工作,也对应着此时点阵显示效果中列需要的数值。随机数部分(伪随机),程序主要部分是随机产生0-15这16个数字,由于实验只需要0-9十个数字,在取值之后使用case对10-15这六个数字分别赋成0-9中的数值,并将二进制数字转换成bcd码。最后是蜂鸣器,顶层发送给蜂鸣器的信号,控制蜂鸣器的输出与否。三、 仿真波形及波形分析1. 键盘clk_50m上升沿到来时,列赋值以4为周期变化。当行&列=“11100111”对应44键盘输入数字1;当行&列=“11010111”对应44键盘输入数字2由上述仿真图可以看出键盘只支持输入0-9十个数字,其他情况不输出数字。2. 点阵 点阵行跟列都是根据clk_scan的上升沿变化的在dz=0时,点阵并不现实,行=“11111111”,列=“00000000”;dz=1时点阵开始工作,同时start有了冲激,64s倒计时开始:64s倒计时点阵全亮64s倒计时点阵熄灭一个64s倒计时点阵熄灭9个64s倒计时点阵熄灭17个64s倒计时点阵熄灭63个64s倒计时结束,点阵全部熄灭倒计时结束,游戏失败,显示“囧”猜对数字,显示“smile”猜错数字,显示“x”。3. 数码管 cat取值每八个clk_50m的上升沿为一周期,其中两个计数状态下cat取值为“111111”,其他情况下保持每次一个数码管工作。图片中cat为“110111”时,显示数字disp3,对应的七段译码为“1101101”。4. 随机数 由上图,当重置信号为1时,随机数置0,重新开始产生m序列。共产生了0、1、2、3、4、5、6、7、8、9十位数字。四、 源程序(要有注释)1. 顶层源码(guessnum.vnd)library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all; -库文件entity guessnum is -实体端口定义port (clk : in std_logic; -clk(50m)state: in std_logic; -sw7btn_0, btn_1, btn_2, btn_5: in std_logic; -clear, ans , gus , randommatrix_col : out std_logic_vector(7 downto 0); -点阵matrix_row : out std_logic_vector(7 downto 0);disp_seg : out std_logic_vector(6 downto 0); -数码管disp_bit : out std_logic_vector(5 downto 0);beep:out std_logic; -蜂鸣器key_scan : out std_logic_vector(3 downto 0); -键盘key_in : in std_logic_vector(3 downto 0);end guessnum;architecture a of guessnum is-定义中间变量signal counter : std_logic_vector(31 downto 0); -divsignal signal_success, signal_fail, signal_wrong, signal_start, mode, t, tmp, key_pressed, t2, dz : std_logic;signal disp5, disp4, disp3,disp2,disp1,disp0 : integer range -1 to 9; -displaysignal num1 ,num2 : integer range 0 to 10;signal num, disp3_set, disp2_set, disp1_set, disp0_set : integer range 0 to 9;signal bit_counter : std_logic_vector(1 downto 0);signal btn_0_s, btn_1_s, btn_2_s, btn_5_s, clk_f : std_logic;component keyboard port (clk_50m : in std_logic;num : out integer range 0 to 9;key_in : in std_logic_vector(3 downto 0);key_scan : out std_logic_vector(3 downto 0);key_pressed : out std_logic);end component;component display port (disp5, disp4, disp3, disp2, disp1, disp0 : in integer range -1 to 9;clk_50m : in std_logic;disp_seg : out std_logic_vector(6 downto 0);disp_bit : out std_logic_vector(5 downto 0);end component;component dotmatrixport (clk_50m, start, wrong, success : in std_logic;dz : in std_logic;fail : out std_logic;row, col : out std_logic_vector(7 downto 0);end component;component xiaodou isport( d_in,xk_clk : in std_logic; d_out : out std_logic);end component; component random is port( clk_50m: in std_logic; btn5_s: in std_logic; clear: in std_logic; num1: out integer range 0 to 10); end component;component beep_tport( clk: in std_logic; clear: in std_logic; success:in std_logic; wrong: in std_logic; beep:out std_logic);end component;begin-调用display.vhdu0 : display port map(disp5, disp4, disp3, disp2, disp1, disp0, clk, disp_seg, disp_bit);-调用keyboard.vhdu1 : keyboard port map(clk, num2, key_in, key_scan, key_pressed);-调用dotmatrix.vhd u2 : dotmatrixport map(clk, signal_start, signal_wrong, signal_success, dz, signal_fail, matrix_row, matrix_col);-对btn_0做消抖处理u3 : xiaodou port map(xk_clk=clk_f,d_in=btn_0,d_out=btn_0_s);-对btn_1做消抖处理u4 : xiaodou port map(xk_clk=clk_f,d_in=btn_1,d_out=btn_1_s);-对btn_2做消抖处理u5 : xiaodou port map(xk_clk=clk_f,d_in=btn_2,d_out=btn_2_s);-对btn_5做消抖处理u7 : xiaodou port map(xk_clk=clk_f,d_in=btn_5,d_out=btn_5_s);-调用random.vhdu6 : random port map(clk_50m = clk,btn5_s=btn_5_s, clear =btn_0_s, num1 = num1);-调用beep_t.vhdu8 : beep_t port map(clk,btn_0_s, signal_success, signal_wrong,beep);process(state) -根据拨码开关的值选择输入被猜数字的方式beginif state=1 then -“1”时,随机数输入num = num1;else -“0”时,键盘输入num = num2;end if;end process;freq_div:process(clk) -分频器(消抖频率)beginif clkevent and clk = 1 thencounter = counter + 1;end if;end process;clk_f = counter(8); -100khzprocess(btn_1_s,btn_0_s) -domatrix control begin or notbeginif btn_0_s=1 then -clear dz =0;elsif (btn_1_sevent and btn_1_s=1) then dz =1;end if;end process ; test:process(clk) -比较variable a, b : integer range 0 to 4;variable num_hash, num_hash_set : std_logic_vector(9 downto 0);beginif clkevent and clk = 1 thenif btn_0_s = 1 then -重置 disp3 = -1; disp2 = -1; disp1 = -1; disp0 = -1; disp4 = -1; disp5 = -1; -数码管不显示bit_counter = 00; -还没有输入数字num_hash := 0000000000; -还没有输入数字mode = 0; -进入输入被猜数模式t2 = 0;signal_success = 0; -成功信号置0elseif btn_1_s = 1 then -存储被猜的数字if t = 0 thenif bit_counter = 00 then -数码管显示 disp0_set = disp0; disp1_set = disp1; disp2_set = disp2; disp3_set = disp3;-将输入数字对应位置电平数组赋值 num_hash_set := num_hash; -数码管不再显示输入的数字 disp3 = -1; disp2 = -1; disp1 = -1; disp0 = -1; num_hash := 0000000000; -数组置0 a := 0; b := 0; -开始显示a、b signal_start = 1; -点阵开始倒计时mode = 1; -进入输入猜数字模式t2 = 1;t = 1;end if;end if;elset = 0; -输入被猜的数字if mode = 0 then if (key_pressed = 1 or state=1) then -数字输入 if num_hash(num) = 0 then -不能输入重复数字 -计数器控制输入数字的位置 bit_counter disp3 disp2 disp1 disp0 = num; end case; -将数组中该数字的位置1,不能再输入该数字 num_hash(num) := 1; end if;end if;else -在64s内if signal_fail = 0 then -猜数字if btn_2_s = 1 then -判断信号if tmp = 0 then -判断a、b 当位置相同,数字也相同时,a加1 如果这个信号对应电平数组该位置值为1,b加1if disp0 = disp0_set then a := a + 1;elsif num_hash_set(disp0) = 1 then b := b + 1;end if;if disp1 = disp1_set then a := a + 1;elsif num_hash_set(disp1) = 1 then b := b + 1;end if;if disp2 = disp2_set then a := a + 1; elsif num_hash_set(disp2) = 1 then b := b + 1;end if;if disp3 = disp3_set then a := a + 1; elsif num_hash_set(disp3) = 1 then b := b + 1; end if;disp5 = a;disp4 = b;if a = 4 then -a=5 猜数字成功,游戏结束 signal_success = 1;elsesignal_wrong = 1; -猜错,不显示disp3 = -1; disp2 = -1; disp1 = -1; disp0 = -1;bit_counter = 00;num_hash := 0000000000;a := 0; b := 0;end if;tmp = 1;end if;else -输入要猜的数字tmp = 0;signal_wrong = 0;signal_start = 0;if key_pressed = 1 thenif num_hash(num) = 0 thenbit_counter disp3 disp2 disp1 disp0 = num;end case;num_hash(num) := 1; end if;end if;end if;end if;end if;end if;end if;end if;end process test;end a;2. 键盘源码(keyboard.vhd)library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity keyboard isport(clk_50m : in std_logic;num : out integer range 0 to 9;key_in : in std_logic_vector(3 downto 0);key_scan : buffer std_logic_vector(3 downto 0);key_pressed : out std_logic);end;architecture a of keyboard issignal counter : std_logic_vector(31 downto 0);signal clk_scan, clk_filter : std_logic;signal scan_pointer : std_logic_vector(1 downto 0);signal key_in_filter : std_logic_vector(3 downto 0);signal key_state : std_logic_vector(7 downto 0);component xiaodou isport( d_in,xk_clk : in std_logic; d_out : out std_logic ); end component;beginfreq_div:process(clk_50m) -分频器beginif clk_50mevent and clk_50m = 1 thencounter = counter + 1;end if;end process;clk_filter = counter(8); -消抖频率clk_scan clk_filter,d_in=key_in(i),d_out=key_in_filter(i);end generate cp1;scan:process(clk_scan)beginif clk_scanevent and clk_scan = 1 then -扫描计数器scan_pointer key_scan key_scan key_scan key_scan = 0111;end case;end process scan;decode:process(clk_scan) -键盘编码beginkey_state num = 1; key_pressed num = 2; key_pressed num = 3; key_pressed num = 4; key_pressed num = 5; key_pressed num = 6; key_pressed num = 7; key_pressed num = 8; key_pressed num = 9; key_pressed num = 0; key_pressed key_pressed = 0;end case;end if;end process decode;end;3. 消抖源码(xiaodou.vhd)library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;library altera;use altera.maxplus2.all; - 少了它,无法使用d,sr触发器entity xiaodou is port( d_in,xk_clk : in std_logic; -xk_clk消抖动时钟 d_out: out std_logic);end ;architecture xd of xiaodou is signal vcc : std_logic; signal q0,q1,q2 : std_logic; -消抖动 signal s,r,srq : std_logic; -sr触发器 signal q3,q4 : std_logic; -微分电路begin-* 注意一般消抖动信号是频率必须比其它的电路使用的脉冲信号频率更高-*例如:一般消抖动频率是键盘扫描或led频率的4倍或更高。 vccd_in ,q=q0, clk=xk_clk, clrn=vcc, prn=vcc);dff2:dff port map(d=q0,q=q1, clk=xk_clk, clrn=vcc, prn=vcc);dff3:dff port map(d=q1,q=q2, clk=xk_clk, clrn=vcc, prn=vcc);-rs触发器sr1 :srff port map(s=(q0 and q1 and q2),r=not (q0 and q1 and q2),q=srq,clk=xk_clk,clrn=vcc, prn=vcc); -* -此处rs触发器的前端连接与非门的处理原则是: - 1、因为一般人的按键速度至多是10次/秒,亦即一次按键时间是100ms,所以按下的时间可估算为50ms。 -以取样信号cp频率为8ms(125hz),则可取样到6次。 - 2、对于不稳定的噪声在4ms以下,则至多只抽样一次 -* d_out=srq; end ;4. 点阵源码(dotmatrix.vhd)library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity dotmatrix isport (clk_50m, start, wrong, success : in std_logic;dz : in std_logic;fail : buffer std_logic;row, col : out std_logic_vector(7 downto 0);end dotmatrix;architecture behave of dotmatrix issignal timer : integer range 64 downto 0;signal c : integer range 0 to 49;signal counter : std_logic_vector(31 downto 0);signal clk_1, clk_scan, clk_50 : std_logic;signal row_pointer : std_logic_vector(2 downto 0);signal led_t : std_logic_vector(63 downto 0);signal col_1, col_2, col_3, col_4, col_5, col_6, col_7, col_8 : std_logic_vector(7 downto 0);beginfreq_div:process(clk_50m) -分频器beginif clk_50mevent and clk_50m = 1 thencounter = counter + 1;end if;end process freq_div;clk_50 = counter(18); - clk_scan = counter(11); -点阵扫描频率p2:process(clk_50) -1sbeginif clk_50event and clk_50 = 1 thenif c = 49 thenc = 0;clk_1 = not clk_1;else c = c + 1;end if;end if;end process p2;scan:process(clk_1, start)beginif start = 1 then -start=1数组重置led_t = 1111111111111111111111111111111111111111111111111111111111111111;timer = 64;fail = 0;elsif (clk_1event and clk_1 = 1) then -开始倒计时led_t = led_t(62 downto 0) & 0; -每1s数组左移一位timer = timer - 1; if timer = 0 thenfail = 1; -64s结束,尝试失败信号end if;end if;end process scan;p1:process(clk_scan, wrong, success, fail, dz)begin if dz=0 then -点阵不工作 row = 11111111; col = 00000000; else -点阵开始工作if clk_scanevent and clk_scan = 1 thenrow_pointer = row_pointer + 1;end if;if success = 1 then -成功显示smilecol_8 = 00000000;col_7 = 01100110;col_6 = 01100110;col_5 = 00000000;col_4 = 00000000;col_3 = 10000001;col_2 = 01000010;col_1 = 00111100;elsif fail = 1 then -失败显示囧col_8 = 11111111;col_7 = 10011001;col_6 = 10100101;col_5 = 10000001;col_4 = 10111101;col_3 = 10100101;col_2 = 10100101;col_1 = 11111111;elsif wrong = 1 then -猜错显示xcol_1 = 10000001;col_2 = 01000010;col_3 = 00100100;col_4 = 00011000;col_5 = 00011000;col_6 = 00100100;col_7 = 01000010;col_8 = 10000001;else -64s倒计时col_1 = led_t(7 downto 0);col_2 = led_t(15 downto 8);col_3 = led_t(23 downto 16);col_4 = led_t(31 downto 24);col_5 = led_t(39 downto 32);col_6 = led_t(47 downto 40);col_7 = led_t(55 downto 48);col_8 row = 01111111; col row = 10111111; col row = 11011111; col row = 11101111; col row = 11110111; col row = 11111011; col row = 11111101; col row = 11111110; col = col_8;end case; end if;end process p1;end;5. 数码管源码(d

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论