键盘扫描及计算器VHDL仿真_第1页
键盘扫描及计算器VHDL仿真_第2页
键盘扫描及计算器VHDL仿真_第3页
键盘扫描及计算器VHDL仿真_第4页
键盘扫描及计算器VHDL仿真_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

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

文档简介

1、电子设计自动化EDA简易计算器设计简易计算器设计 EDA实验报告 一、 实验内容实验要求:完成个位数的加减乘运算,输入用矩阵键盘,输出用数码管显示,每输入一次数据要显示在数码管上。矩阵键盘共16个按键,用其中10个做个位数的输入,用3个分别做加减乘运算,用其中1个做等于操作,各位数的运算结果最多两位,用动态扫描数码管显示运算结果。二、 小组成员三、 实现方法系统组成及连接原理如图所示,主要由由七个功能模块组成:分频模块(为键盘扫描模块和防抖模块提供时钟)、键盘扫描驱动模块(依次置零)、键盘按键值编码模块、键盘编码值防抖模块、运算模块,数码管显示驱动模块、动态扫描驱动模块。分频键值编码防抖键盘矩

2、阵行驱动时钟数码管显示运算数码管动态显示1.分频模块由于FPGA实验板的原始时钟频率高达33.8688MHz,所以不能直接接入设计模块中使用,就需要用到分频模块。将33.8688MHz分频到4KHz和10Hz来使用,一个用于行驱动扫描时钟,一个用于防抖模块。所以,采用写一个可变分频元件来调用。元件视图:主要代码如下(完整代码见附录,下同):architecture RTL of freq_division iscomponent fredivn isgeneric(n:positive); Port ( clkin:in STD_LOGIC; clkout:out STD_LOGIC);end

3、 component;beginU1:fredivngeneric map(n=>3)port map(clkin=>clk,clkout=>clkout_kb);end RTL;仿真结果如下图:达到预期的目的2.行驱动模块(依次对行置零):键盘扫描的原理就是检测行列信号然后判断出具体是按下了哪一个按键。所以,对行依次置零,当置零频率较快时,按下某一个按键后,一定能得到某一列的信号输出为零,如下图:当行信号为1110时,若按下了0键,就会得到1110的列信号,立马就快可以译码出按键值,若按下4键、8键、C键则都不会有输出。主要代码如下:process(clkin)begini

4、f clr='1' thencount<="00" elsif rising_edge(clkin) thenif count="11" thencount<="00"elsecount<=count+1;end if;end if;end process;process(count)beginif count="01" thenkeydrv<="1110"elsif count="10" thenkeydrv<="11

5、01"elsif count="11" then keydrv<="1011" elsif count="00" thenkeydrv<="0111"end if;end process;仿真结果如下图:达到预期的目的3.键值编码模块依据行驱动模块,当按下某一个按键后,立马可以根据行列和并位信号得到唯一的键盘编码值,用5位矢量来保存结果,当没有按键按下时,编码值一直保持着11111不变,并在后端的模块中不对其做任何处理。以下列出部分编码表(完整编码表见附录):十进制数行&列HEX七段码

6、HEX011101110EE11111107E411011110DE011001133511011101DD10110115B主要代码如下:process(clk)beginif clr='0' thenif rising_edge(clk) thenif temp1="11101110" thenkeyvalue1<="00000" -0elsif temp1="11101101" thenkeyvalue1<="00001" -1elsif temp1="11101011&

7、quot; thenkeyvalue1<="00010" -2elsif temp1="11100111" thenkeyvalue1<="00011" -3elsif temp1="11011110" thenkeyvalue1<="00100" -4elsif temp1="11011101" thenkeyvalue1<="00101" -5elsif temp1="11011011" thenkeyval

8、ue1<="00110" -6elsif temp1="11010111" thenkeyvalue1<="00111" -7elsif temp1="10111110" thenkeyvalue1<="01000" -8elsif temp1="10111101" thenkeyvalue1<="01001" -9elsif temp1="10111011" thenkeyvalue1<="01

9、010" -10elsif temp1="10110111" thenkeyvalue1<="01011" -11elsif temp1="01111110" thenkeyvalue1<="01100" -12elsif temp1="01111101" thenkeyvalue1<="01101" -13elsif temp1="01111011" thenkeyvalue1<="01110" -1

10、4elsif temp1="01110111" thenkeyvalue1<="01111" -15end if;end if;end if;end process;波形仿真如下图:4.防抖模块键盘按键物理模型如下:通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。抖动时间的长短由按键的机械特性决定,一般为5ms10ms。一般来说,软件消抖的方法是不断检测按键值,直到

11、按键值稳定。实现方法:假设未按键时输入1,按键后输入为0,抖动时不定。可以做以下检测:检测到按键输入为0之后,延时5ms10ms,再次检测,如果按键还为0,那么就认为有按键输入。延时的5ms10ms恰好避开了抖动期。本模块是采用多次采样来达到防抖的,只有在给定的采样次数内,都保证采样结果一致时才会输出按键编码值。主要代码如下:case count iswhen "0000"=> test1<=temp;when "0001"=> test2<=temp;when "0010"=> test3<=te

12、mp;when "0011"=> test4<=temp;when "0100"=> test5<=temp;when "0101"=> test6<=temp;when "0110"=> test7<=temp;when "0111"=> test8<=temp;when "1000"=> test9<=temp;when "1001"=> test10<=temp;wh

13、en "1010"=> test11<=temp;when "1011"=> test12<=temp;when "1100"=> test13<=temp;when "1101"=> test14<=temp;when "1110"=> test15<=temp;when "1111"=> test16<=temp;when others=>null;end case;if test1=test5

14、 and test2=test6 and test3=test7 and test4=test8 and test5=test9 and test6=test10 and test7=test11 and test8=test12 and test9=test13 and test10=test14 and test11=test15 and test12=test16 and test1 /= "UUUUUUUU" then仿真波形如下:从图中可以看出最终temp1从临时信号temp得到最终输出,达到防抖:5.运算模块当前段的模块经过防抖处理以后得到稳定的按键信号,比如1

15、+2=3,转化为编码值就是11101101 10111011 01111101 11100111 => ED BB EB 7D E7(具体编码表见附录)主要代码如下:if ysfh=0 then result<=first+second; elsif ysfh=1 then result<=first-second; elsif ysfh=2 then result<=first*second; end if; n<=n+'1'elsif n="100" then n<="000"end if;end

16、if; end process; process (n) begin if n="001"then keyvaluein<=conv_std_logic_vector(first,8); elsif n="011"then keyvaluein<=conv_std_logic_vector(second,8); elsif n="100"then keyvaluein<=conv_std_logic_vector(result,8); end if; end process;仿真波形如下:以1+3=4 和 5x6=3

17、0为例:编码:01 + 03 =04 05 X 06 =1E6.数码管显示模块以及动态扫描模块由于次两个模块是密切相关的,所以统一到一起验证。经过运算得到最终的显示结果后,要在七段数码管中显示,就必须有每一个数的七段码,同时,由于前面的运算模块的结果最大可以达到81,也就是需要8位二进制,两位十进制来表示,所以就必须通过显示模块来分离出十位和个位。分离出十位和个位以后,就必须要利用动态扫描使两个数都能显示出来。因为8个七段数码管的abcdefg位是连在一起的,只有利用分时间隔来显示,一次使能一个数码管,显示一位数,当频率较高时,就可以得到两位数的显示效果。数码管显示模块主要代码如下:if nu

18、m=0 thenten:=0;one:=10;elsif num<10 and num>0thenten:=0;one:=num;elsif num<20 and num>9 thenten:=1;one:=num-10;elsif num<30 and num>19 thenten:=2;one:=num-20;elsif num<40 and num>29 thenten:=3;one:=num-30;elsif num<50 and num>39 thenten:=4;one:=num-40;elsif num<60 an

19、d num>49 thenten:=5;one:=num-50;elsif num<70 and num>59 thenten:=6;one:=num-60;elsif num<80 and num>69 thenten:=7;one:=num-70;elsif num<90 and num>79 thenten:=8;one:=num-80;elsif num<100 and num>89 thenten:=9;one:=num-90;end if;t<=conv_std_logic_vector(ten,4);o<=conv

20、_std_logic_vector(one,4);动态扫描模块主要代码如下:if count="00" thenshowout<=show1;en<="00000010"elsif count="01" thenshowout<=show2;en<="00000001"end if;仿真波形如下:数码显示模块Show1是十位数,show2是个位数,分别为7E(七段码十六进制)和30,即01。扫描显示模块数码管使能信号en依次在01和02中变化,翻译成八段码就是00000001和0000001

21、0四、 模块调用将上述模块按照层次调用,就可以得到最顶层的文件,完成计算器的所有要求功能。调用图如下:扫描显示数码管显示运算模块后端处理防抖模块键盘编码行驱动顶层文件时钟模块:分频键盘最终的仿真波形如下:01 => showout 0110000 3002 => showout 1101101 6D03 => showout 1111001 79由以上波形可以看出:01 + 02 = 03的计算完成了。五、 总结本次EDA设计实践,完成了从VHDL代码编写到硬件实现的整个流程,掌握了一些FPGA的相关概念以及ISE软件和Active-HDL软件的使用方法。最重要的就是组员之间

22、的合作,因为VHDL程序是模块化编写的,所以不同模块是由不同人来完成编译的,要达到各个模块之间能够良好的衔接通信,就必须有一个很好的沟通交流,把大家的思路集中起来,一起讨论、编写、调试程序。【附录一】完整程序:分频:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity fredivn is generic(n:integer:=3); Port ( clkin:in STD_LOGIC; clkout:out STD_LOGIC);

23、end fredivn;architecture Behavioral of fredivn issignal clk1:std_logic:='0'signal counter:integer range 0 to n; beginprocess(clkin) begin if rising_edge(clkin)then if counter=(n-1)/2 then clk1<=not clk1; counter<=0; else counter<=counter+1; end if; end if; end process; clkout<=cl

24、k1; end Behavioral;library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity keyscan is Port ( clr:in std_logic; clkin : in STD_LOGIC; keydrv :out STD_LOGIC_VECTOR(3 downto 0);end keyscan;architecture behavioral of keyscan issignal count : std_logic

25、_vector(1 downto 0); beginprocess(clkin)beginif clr='1' then count<="00"elsif rising_edge(clkin) thenif count="11" thencount<="00" elsecount<=count+1;end if;end if;end process;process(count)beginif count="01" thenkeydrv<="1110"els

26、if count="10" thenkeydrv<="1101"elsif count="11" thenkeydrv<="1011" elsif count="00" thenkeydrv<="0111"end if;end process;end behavioral;键值编码:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_

27、UNSIGNED.ALL;entity keydecoder is Port ( clkin,clk,clr: in std_logic;keyin : in STD_LOGIC_VECTOR (3 downto 0); keycode : out STD_LOGIC_VECTOR (4 downto 0) );end keydecoder;architecture Rtl of keydecoder issignal temp:STD_LOGIC_VECTOR (7 downto 0); signal keydrv1:STD_LOGIC_VECTOR (3 downto 0);signal

28、keyvalue1:STD_LOGIC_VECTOR (4 downto 0);signal temp1:STD_LOGIC_VECTOR (7 downto 0);component keyscanPort ( clkin ,clr: in STD_LOGIC; keydrv : out STD_LOGIC_VECTOR(3 downto 0);end component; component fandou1Port ( clkin ,clr: in STD_LOGIC;temp:in std_logic_vector(7 downto 0);temp1: out STD_LOGIC_VEC

29、TOR(7 downto 0); end component;beginu1: keyscan port map(clkin=>clkin,keydrv=>keydrv1,clr=>clr); temp<=keydrv1&keyin; u2:fandou1 port map(clkin=>clkin,temp=>temp,temp1=>temp1,clr=>clr);process(clk)beginif clr='0' thenif rising_edge(clk) thenif temp1="11101110

30、" thenkeyvalue1<="00000"elsif temp1="11101101" thenkeyvalue1<="00001"elsif temp1="11101011" thenkeyvalue1<="00010"elsif temp1="11100111" thenkeyvalue1<="00011"elsif temp1="11011110" then keyvalue1<=&q

31、uot;00100" elsif temp1="11011101" thenkeyvalue1<="00101"elsif temp1="11011011" thenkeyvalue1<="00110"elsif temp1="11010111" thenkeyvalue1<="00111"elsif temp1="10111110" then keyvalue1<="01000"elsif temp1

32、="10111101" thenkeyvalue1<="01001"elsif temp1="10111011" thenkeyvalue1<="01010"elsif temp1="10110111" thenkeyvalue1<="01011"elsif temp1="01111110" thenkeyvalue1<="01100"elsif temp1="01111101" thenke

33、yvalue1<="01101"elsif temp1="01111011" then keyvalue1<="01110"elsif temp1="01110111" thenkeyvalue1<="01111"end if;end if;end if;end process;keycode<=keyvalue1;end rtl;防抖:library IEEE;use IEEE.STD_LOGIC_1164.all;use IEEE.STD_LOGIC_ARITH.AL

34、L;use IEEE.STD_LOGIC_UNSIGNED.ALL;use ieee.numeric_std.all;entity fangdou is port(keycode:in std_logic_vector(4 downto 0);keycode1:out std_logic_vector(4 downto 0);start:out std_logic;clk_f,clr:in std_logic);end fangdou;architecture fangdou of fangdou issignal count1:std_logic_vector(2 downto 0);sig

35、nal key1:std_logic_vector(4 downto 0);signal key2:std_logic_vector(4 downto 0);signal key3:std_logic_vector(4 downto 0);signal key4:std_logic_vector(4 downto 0);signal key5:std_logic_vector(4 downto 0);signal key6:std_logic_vector(4 downto 0);signal key7:std_logic_vector(4 downto 0);signal key8:std_

36、logic_vector(4 downto 0);signal start_1:std_logic;begin process(clk_f)beginif clr='1' thenkey1<="00000"key2<="00001"key3<="00010"key4<="00011"key5<="00100"key6<="00101"key7<="00110"key8<="00111

37、"count1<="000"start_1<='1'elseif rising_edge(clk_f) then if count1="111" thencount1<="000" else count1<=count1+'1'end if;end if;end if;case count1 iswhen "000"=>key1<=keycode;when "001"=>key2<=keycode;when

38、 "010"=>key3<=keycode;when "011"=>key4<=keycode;when "100"=>key5<=keycode;when "101"=>key6<=keycode;when "110"=>key7<=keycode;when "111"=>key8<=keycode;when others =>null;end case;if key1=key2 and key2

39、=key3 and key3=key4 and key4=key5 and key5=key6 and key6=key7 and key7=key8 and key1/="UUUUU"thenkeycode1<=key1;start_1<='0' after 5ns;end if;end process;start<=start_1;end fangdou;运算:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_

40、UNSIGNED.ALL;use ieee.numeric_std.all;entity yunsuan isport(start: in std_logic;keycode1:in std_logic_vector(4 downto 0);keyvaluein:out std_logic_vector(7 downto 0);end yunsuan;architecture Behavioral of yunsuan issignal first,second,result,ysfh: integer range 0 to 99;signal n:std_logic_vector(2 dow

41、nto 0);begin process(start,keycode1)beginif start='1' thenn<="000"else if n="000" thenif keycode1="00001"then first<=1;elsif keycode1="00010"then first<=2;elsif keycode1="00011"then first<=3;elsif keycode1="00100"then fi

42、rst<=4;elsif keycode1="00101"then first<=5;elsif keycode1="00110"then first<=6;elsif keycode1="00111"then first<=7;elsif keycode1="01000"then first<=8;elsif keycode1="01001"then first<=9;elsif keycode1="00000" then first&l

43、t;=0;end if;n<=n+'1'elsif n="001" then if keycode1="01010"then ysfh<=0; elsif keycode1="01011"then ysfh<=1; elsif keycode1="01100"then ysfh<=2;end if; n<=n+'1'elsif n="010" thenif keycode1="00001"then second&l

44、t;=1;elsif keycode1="00010"then second<=2;elsif keycode1="00011"then second<=3;elsif keycode1="00100"then second<=4;elsif keycode1="00101"then second<=5;elsif keycode1="00110"then second<=6;elsif keycode1="00111"then second&l

45、t;=7;elsif keycode1="01000"then second<=8;elsif keycode1="01001"then second<=9;elsif keycode1="00000"then second<=0;end if;n<=n+'1'elsif n="011" and keycode1="01101" then if ysfh=0 then result<=first+second;elsif ysfh=1 then re

46、sult<=first-second;elsif ysfh=2 then result<=first*second; end if; n<=n+'1'elsif n="100" thenn<="000"end if;end if;end process;process (n)beginif n="001"then keyvaluein<=conv_std_logic_vector(first,8);elsif n="011"then keyvaluein<=con

47、v_std_logic_vector(second,8); elsif n="100"then keyvaluein<=conv_std_logic_vector(result,8);end if; end process;end Behavioral;数码管显示:library IEEE;use IEEE.STD_LOGIC_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity shumaguanxianshi isport(keyvaluein:in std_log

48、ic_vector(7 downto 0);clk:in std_logic;show1,show2:out std_logic_vector(6 downto 0);end shumaguanxianshi ;architecture shumaguanxianshi of shumaguanxianshi issignal t:std_logic_vector(3 downto 0); signal o:std_logic_vector(3 downto 0);beginprocess(clk)variable num:integer range 0 to 99;variable ten,

49、one: integer range 0 to 15;beginif rising_edge(clk) thennum:=conv_integer(keyvaluein);if num=0 thenten:=0;one:=10;elsif num<10 and num>0then ten:=0;one:=num;elsif num<20 and num>9 then ten:=1;one:=num-10;elsif num<30 and num>19then ten:=2;one:=num-20;elsif num<40 and num>29th

50、en ten:=3;one:=num-30;elsif num<50 and num>39then ten:=4;one:=num-40;elsif num<60 and num>49 then ten:=5;one:=num-50;elsif num<70 and num>59then ten:=6;one:=num-60;elsif num<80 and num>69 then ten:=7;one:=num-70;elsif num<90 and num>79then ten:=8;one:=num-80;elsif num&l

51、t;100 and num>89 then ten:=9;one:=num-90;end if;t<=conv_std_logic_vector(ten,4); o<=conv_std_logic_vector(one,4);case t iswhen "0000"=>show1<="0000000"when "0001"=>show1<="0110000"when "0010"=>show1<="1101101"when

52、 "0011"=>show1<="1111001"when "0100"=>show1<="0110011"when "0101"=>show1<="1011011"when "0110"=>show1<="0011111"when "0111"=>show1<="1110000"when "1000"=>sho

53、w1<="1111111"when "1001"=>show1<="1110011"when others=>show1<="0000000"end case;case o iswhen "0000"=>show2<="1111110"when "0001"=>show2<="0110000"when "0010"=>show2<="1101

54、101"when "0011"=>show2<="1111001"when "0100"=>show2<="0110011"when "0101"=>show2<="1011011"when "0110"=>show2<="0011111"when "0111"=>show2<="1110000"when "1000&

55、quot;=>show2<="1111111"when "1001"=>show2<="1110011"when others=>show2<="0000000"end case;end if;end process;end shumaguanxianshi ;动态显示:library IEEE;use IEEE.STD_LOGIC_1164.all;use IEEE.STD_LOGIC_UNSIGNED.ALL;use ieee.numeric_std.all;entity s

56、haomiaoxianshi isport(clk,clr:in std_logic;show1:in std_logic_vector(6 downto 0);show2:in std_logic_vector(6 downto 0);showout:out std_logic_vector(6 downto 0);en:out std_logic_vector(7 downto 0);end shaomiaoxianshi;architecture shaomiaoxianshi of shaomiaoxianshi issignal count:std_logic_vector(1 do

57、wnto 0);beginprocess(clk)beginif clr='1' then count<="00"elseif clk'event and clk='1' then if count="01"thencount<="00"else count<=count+'1'end if;end if;if count="00" thenshowout<=show1;en<="00000010"elsif

58、count="01" thenshowout<=show2;en<="00000001"end if;end if;end process;end shaomiaoxianshi;键盘:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity keyboard isPort ( clr: in std_logic; clk : in STD_LOGIC; keyin : in STD_

59、LOGIC_VECTOR (3 downto 0);keydrv1:out std_logic_vector(3 downto 0);keyvalue :out STD_LOGIC_VECTOR(4 downto 0);start:out std_logic);end keyboard;architecture RTL of keyboard is component keyscanPort ( clkin ,clr: in STD_LOGIC; keydrv : out STD_LOGIC_VECTOR(3 downto 0);end component; component keydeco

60、derPort ( clkin,clk,clr:in std_logic;keyin : in STD_LOGIC_VECTOR (3 downto 0);keycode : out STD_LOGIC_VECTOR (4 downto 0);end component; component fangdou port(keycode:in std_logic_vector(4 downto 0);keycode1:out std_logic_vector(4 downto 0);start:out std_logic;clk_f,clr:in std_logic);end component;

61、component fredivngeneric(n:integer:=3); Port ( clkin:in STD_LOGIC; clkout:out STD_LOGIC);end component;signal key2:std_logic_vector(4 downto 0);signal clk_temp1:std_logic;signal key1:std_logic_vector(4 downto 0); signal clk_temp2:std_logic; signal start1:std_logic;beginU1:keyscanport map(clkin=>clk_temp1,keydrv=>keydrv1,clr=>clr);U2:keydecoderport map(clkin=>clk_temp1,keyin=>keyin,keycode=>key1,clk=>clk,clr=>clr);U3:fredivngene

温馨提示

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

评论

0/150

提交评论