基于FPGA的矩阵键盘接口电路的设计

目录

目录------------------------------------------------------------------------------------------------ 1 1.绪论--------------------------------------------------------------------------------------------- 3 1.1 FPGA概况----------------------------------------------------------------------------------- 3 1.2 本课题的研究意义 ----------------------------------------------------------------------- 4

1.3 本章小结------------------------------------------------------------------------------------ 4

2. VHDL语言 ------------------------------------------------------------------------------------ 5 2.1 VHDL语言概述----------------------------------------------------------------------------- 5 2.2 VHDL语言的优点-------------------------------------------------------------------------- 6 2.3 利用VHDL语言设计数字系统的特点------------------------------------------------- 8 2.4 VHDL语言的基本结构-------------------------------------------------------------------- 9

2.5本章小结 ------------------------------------------------------------------------------------ 9

3.矩阵键盘接口电路原理和数码管显示原理 ------------------------------------------- 10 3.1矩阵键盘接口电路的原理 -------------------------------------------------------------- 10 3.2数码管显示原理 -------------------------------------------------------------------------- 12

3.3本章小结 ----------------------------------------------------------------------------------- 12

4.总体设计和各模块设计 ------------------------------------------------------------------- 13 4.1时钟产生模块 ----------------------------------------------------------------------------- 13

4.2键盘扫描模块 ----------------------------------------------------------------------------- 13 4.3数码管显示模块 -------------------------------------------------------------------------- 14 4.4顶层电路实现 ----------------------------------------------------------------------------- 14 4.5本章小结 ----------------------------------------------------------------------------------- 14 附录1:总体设计电路原理图:------------------------------------------------------------- 15附录2:硬件实物图 -------------------------------------------------------------------------- 15附录3:EP1C3T144C8N的PCB电路图 ---------------------------------------------------- 16附录4:顶层电路实现的具体程序 -------------------------------------------------------- 16附录5:时钟产生模块实现的具体程序 -------------------------------------------------- 17附录6:键盘扫描模块实现的具体程序 -------------------------------------------------- 18附录7:数码管显示模块实现的具体程序 ----------------------------------------------- 24

5.心得体会-------------------------------------------------------------------------------------- 26

1.绪论

1.1 FPGA概况

早期的可编程逻辑器件只有可编程只读存储器(PROM)、紫外线可擦除只读存储器(EPROM)和电可擦除只读存储器(E2PROM)三种。由于结构的限制,它们只能完成简单的数字逻辑功能。

其后出现了一类结构上稍复杂的可编程芯片,即可编程逻辑器件(PLD),它能够完成各种数字逻辑功能。典型的PLD由一个“与”门和一个“或”门阵列组成,而任意一个组合逻辑都可以用“与—或”表达式来描述,所以PLD能以乘积和的形式完成大量的组合逻辑功能。

这一阶段的产品主要有PAL(可编程阵列逻辑)和GAL(通用阵列逻辑)。PAL由一个可编程的“与”平面和一个固定的“或”平面构成,或门的输出可以通过触发器有选择地被置为寄存状态。PAL器件是现场可编程的,它的实现工艺有反熔丝技术、EPROM技术和E2PROM技术。还有一类结构更为灵活的逻辑器件是可编程逻辑阵列(PLA),它也由一个“与”平面和一个“或”平面构成,但是这两个平面的连接关系是可编程的。PLA器件既有现场可编程的,也有掩膜可编程的。在PAL的基础上又发展了一种通用阵列逻辑(GAL、Generic ArrayLogic),如GAL16V8、GAL22V10等。它采用了E'PROM工艺,实现了电可擦除、电可改写,其输出结构是可编程的逻辑宏单元,因而它的设计具有很强的灵活性,至今仍有许多人使用。这些早期的PLD器件的一个共同特点是可以实现速度特性较好的逻辑功能,但其过于简单的结构也使它们只能实现规模较小的电路。

为了弥补这一缺陷,20世纪80年代中期,Altera和Xilinx分别推出了类似于PAL结构的扩展型CPLD(Complex Programmable Logic Dvice)和与标准门阵列类似的FPGA(FieldProgrammable Gate Array),它们都具有体系结构和逻辑单元灵活、集成度高以及适用范围宽等特点。这两种器件兼容了PLD和通用门阵列的优点,可实现较大规模的电路,编程也很灵活。与门阵列等其他ASIC(Application Specific IC)相比,它们又具有设计开发周期短、设计制造成本低、开发工具先进、标准产品不需测试、质量稳定以及可实时在线检验等优点,因此被广泛应用于产品的原型设计和产品生产(一般在10 000件以下)之中。几乎所有应用门阵列、PLD和中小规模通用数字集成电路的场合均可应用FPGA和CPLD器件。

1.2 本课题的研究意义

近年来EDA技术在电子领域引发的技术革命,推动着电子技术的迅猛发展,为世人所瞩目,而FPGA为代表的可编程逻辑器件的应用,更是受到业内人士的普遍关注。伴随着大规模集成电路和计算机技术的高速发展,在设计工业自动化,仪器仪表,计算机设计与应用、通信、国防等领域的电子系统中,FPGA技术的含量正以惊人的速度提升。将尽可能大的完整的电子系统在单一FPGA芯片中实现已成为现实,电子类新技术项目的开发也更多地依赖于FPGA技术的应用。

作为FPGA研究课题之一的矩阵键盘控制接口电路的设计,在FPGA设计中是一个经常被提到的话题,就像是利用PFGA设计数字中一样,虽然简单,但是却是一个很有研究意义的话题,涉及到怎么样才能是FPGA资源更加充分利用,现在很多电子产品都涉及到按键,小的有独立按键,大的有N*N的矩阵键盘,独立按键由于案件的个数少,也就没必要考虑资源的利用问题了。而矩阵键盘,由于按键多,对整个系统的影响大,所以肯定要考虑资源的利用问题,而且还要考虑一下电路里面的时序问题。本次设计要求设计一个4*9矩阵键盘,也就是行为4,列为9,一共可以设计36个按键。其中设计方法为:一般判断键盘中有没有按键按下是通过航线送入扫描信号,然后从列线中读取状态得到的,其方法是依次给行线送入低电平,检查列线的输入。如果列线信号趣味高电平,则代表低电平信号所在的行中无按键按下,反之,则有,则在低电平信号所在的行和出现低电平的交叉处有按键按下。

一共有三个模块,分别为:扫描电路模块、时钟产生模块、键盘译码电路和按键标志位产生电路。扫描模块中是为了产生扫描信号,来利用扫描信号来扫描键盘中中是否有按键按下。键盘译码电路和按键标志位产生电路是为了配合扫描模块来扫描电路中是否有按键按下,而且还要求它来产生按键标志信号,以便和外部电路握手。时钟产生电路是为了产生不同频率的信号,来驱动上面两个电路的运转。

在设计完各个模块后,还要对每个模块进行仿真,在仿真的过程中要对参数精心设计,要不然看不出结果的。

1.3 本章小结

本章首先介绍了FPGA的发展史,主要介绍了一下FPGA的发展年代,以及是怎么样发展起来的。在第二节里面介绍了以下本文的研究意义,在研究意义里

面介绍了一下矩阵键盘的设计方法以及本次设计的主要设计模块。最后介绍了一下各个模块的作用和特点。

2. VHDL语言

2.1 VHDL语言概述

VHDL 语言的英文全名是Very High Speed Integrated Circuit Hardware Description Language,即超高速集成电路硬件描述语言。HDL 发展的技术源头是:在HDL 形成发展之前,已有了许多程序设计语言,如汇编、C 、Pascal 、Fortran 、Prolog 等。这些语言运行在不同硬件平台和不同的操作环境中,它们适合于描述过程和算法,不适合作硬件描述。CAD 的出现,使人们可以利用计算机进行建筑、服装等行业的辅助设计,电子辅助设计也同步发展起来。在从CAD 工具到EDA 工具的进化过程中,电子设计工具的人机界面能力越来越高。在利用EDA 工具进行电子设计时,逻辑图、分立电子原件作为整个越来越复杂的电子系统的设计已不适应。任何一种EDA 工具,都需要一种硬件描述语言来作为EDA 工具的工作语言。这些众多的EDA 工具软件开发者,各自推出了自己的HDL 语言。

HDL发展的社会根源是:美国国防部电子系统项目有众多的承包公司,由于各公司技术路线不一致,许多产品不兼容,他们使用各自的设计语言,使得甲公司的设计不能被乙公司重复利用,造成了信息交换困难和维护困难。美国政府为了降低开发费用,避免重复设计,国防部为他们的超高速集成电路提供了一种硬件描述语言,以期望VHDL 功能强大、严格、可读性好。政府要求各公司的合同都用它来描述,以避免产生歧义。

由政府牵头,VHDL 工作小组于1981 年 6 月成立,提出了一个满足电子设计各种要求的能够作为工业标准的HDL 。1983年第 3 季度,由IBM 公司、TI 公司、Intermetrics。

公司签约,组成开发小组,工作任务是提出语言版本和开发软件环境。1986 年IEEE 标准化组织开始工作,讨论VHDL 语言标准,历时一年有余,于1987 年12 月通过标准审查,并宣布实施,即IEEE STD 1076 - 1987[LRM87]。1993 年VHDL 重新修订,形成了新的标准,即IEEE STD 1076 - 1993[LRM93]。

从此以后,美国国防部实施新的技术标准,要求电子系统开发商的合同文件一律采用VHDL 文档。即第一个官方VHDL标准得到推广、实施和普及。

HDL 语言在国外有上百种。高等学校、科研单位、EDA公司都有自己的HDL语言。现选择较有影响的作简要介绍。

Candence 公司是一家著名的EDA公司,财力雄厚。该公司的Verilog HDL 于1983 年由Gate Way Design Automatic公司的Phil Moorby首创。他在1984-1985年间成功设计了Verilog-XL仿真器,于1986年提出了快速门级仿真的XL 算法,使Verilog HDL 语言变得更加丰富和完善,从而受到了EDA工具设计公司的青睐。1989年Candence公司购买了GDA公司,Verilog HDL语言从此变为Candence 公司的“私有财产”成为Candence公司的EDA 设计环境上的硬件描述语言。经过Candence公司的努力,Verilog HDL于1995年成为IEEE 标准,也是民间公司第一个硬件描述语言标准,即Verilog HDL 1364-1995。由于Verilog HDL语言从C语言发展来,所以有C语言基础的设计人员能够较快入门。

ALTERA 公司是一家半导体器件公司,其CPLD器件在世界市场上占主导地位。这家公司不仅是硬件生产厂商,也是EDA工具开发商,它的EDA工具MAX+plus II、Quartus由于人机界面友好、易于使用、性能优良,而受到FPGA、CPLD器件设计人员的欢迎。运行在MAX+plus II环境下的VHDL语言具有C 语言设计风格,好学好用,因此被众多用户使用。

HDL语言来自不同地方,由不同语言演变而来,为了各平台之间相互转换,又推出了EDIF (Electronic Design Interchange Format)。它不是一种语言,而是用于不同数据格式的EDA 工具之间的交换设计数据。

2.2 VHDL语言的优点

传统的硬件电路设计方法是采用自下而上的设计方法,即根据系统对硬件的要求,详细编制技术规格书,并画出系统控制流图;然后根据技术规格书和系统控制流图,对系统的功能进行细化,合理地划分功能模块,并画出系统的功能框图;接着就进行各功能模块的细化和电路设计;各功能模块电路设计、调试完成后,将各功能模块的硬件电路连接起来再进行系统的调试,最后完成整个系统的硬件设计。采用传统方法设计数字系统,特别是当电路系统非常庞大时,设计者必须具备较好的设计经验,而且繁杂多样的原理图的阅读和修改也给设计者带来诸多的不便。为了提高开发的效率,增加已有开发成果的可继承性以及缩短开发周期,各ASIC研制和生产厂家相继开发了具有自己特色的电路硬件描述语言(Hardware Description Language,简称HDL)。但这些硬件描述语言差异很大,各自只能在自己的特定设计环境中使用,这给设计者之间的相互交流带来了极大

的困难。因此,开发一种强大的、标准化的硬件描述语言作为可相互交流的设计环境已势在必行。于是,美国于1981年提出了一种新的、标准化的HDL,称之为VHSIC(Very High Speed Integrated Circuit)Hardware Description Language,简称VHDL。这是一种用形式化方法来描述数字电路和设计数字逻辑系统的语言。设计者可以利用这种语言来描述自己的设计思想,然后利用电子设计自动化工具进行仿真,再自动综合到门级电路,最后用PLD实现其功能。

综合起来讲,VHDL语言具有如下优点:

(1)VHDL语言功能强大,设计方式多样。VHDL语言具有强大的语言结构, 只需采用简单明确的VHDL语言程序就可以描述十分复杂的硬件电路。同时,它还具有多层次的电路设计描述功能。此外,VHDL语言能够同时支持同步电路、异步电路和随机电路的设计实现,这是其他硬件描述语言所不能比拟的。VHDL语言设计方法灵活多样,既支持自顶向下的设计方式,也支持自底向上的设计方法;既支持模块化设计方法,也支持层次化设计方法。

(2)VHDL 语言具有强大的硬件描述能力。VHDL语言具有多层次的电路设计描述功能,既可描述系统级电路,也可以描述门级电路;描述方式既可以采用行为描述、寄存器传输描述或者结构描述,也可以采用三者的混合描述方式。同时,VHDL语言也支持惯性延迟和传输延迟,这样可以准确地建立硬件电路的模型。VHDL语言的强大描述能力还体现在它具有丰富的数据类型。VHDL语言既支持标准定义的数据类型,也支持用户定义的数据类型,这样便会给硬件描述带来较大的自由度。

(3)VHDL语言具有很强的移植能力。VHDL语言很强的移植能力主要体现在:对于同一个硬件电路的VHDL语言描述,它可以从一个模拟器移植到另一个模拟器上、从一个综合器移植到另一个综合器上或者从一个工作平台移植到另一个工作平台上去执行。

(4)VHDL语言的设计描述与器件无关。采用VHDL语言描述硬件电路时, 设计人员并不需要首先考虑选择进行设计的器件。这样做的好处是可以使设计人员集中精力进行电路设计的优化,而不需要考虑其他的问题。当硬件电路的设计描述完成以后,VHDL语言允许采用多种不同的器件结构来实现。

(5)VHDL语言程序易于共享和复用。VHDL语言采用基于库(library)

的设计方法。在设计过程中,设计人员可以建立各种可再次利用的模块,一个大规模的硬件电路的设计不可能从门级电路开始一步步地进行设计,而是一些模块的累加。这些模块可以预先设计或者使用以前设计中的存档模块,将这些模块存放在库中,就可以在以后的设计中进行复用。

2.3 利用VHDL语言设计数字系统的特点

当电路系统采用VHDL语言设计其硬件时,与传统的电路设计方法相比较,具有如下的特点:

(1)采用自上而下的设计方法。

即从系统总体要求出发,自上而下地逐步将设计的内容细化,最后完成系统硬件的整体设计。在设计的过程中,对系统自上而下分成三个层次进行设计:第一层次是行为描述。所谓行为描述,实质上就是对整个系统的数学模型的描述。一般来说,对系统进行行为描述的目的是试图在系统设计的初始阶段,通过对系统行为描述的仿真来发现设计中存在的问题。在行为描述阶段,并不真正考虑其实际的操作和算法用何种方法来实现,而是考虑系统的结构及其工作的过程是否能到达系统设计的要求。

第二层次是RTL方式描述。这一层次称为寄存器传输描述(又称数据流描述)。如前所述,用行为方式描述的系统结构的程序,其抽象程度高,是很难直接映射到具体逻辑元件结构的。要想得到硬件的具体实现,必须将行为方式描述的VHDL语言程序改写为RTL方式描述的VHDL语言程序。也就是说,系统采用RTL方式描述,才能导出系统的逻辑表达式,才能进行逻辑综合。

第三层次是逻辑综合。即利用逻辑综合工具,将RTL方式描述的程序转换成用基本逻辑元件表示的文件(门级网络表)。此时,如果需要,可将逻辑综合的结果以逻辑原理图的方式输出。此后可对综合的结果在门电路级上进行仿真,并检查其时序关系。应用逻辑综合工具产生的门级网络表,将其转换成PLD的编程码点,即可利用PLD实现硬件电路的设计。

由自上而下的设计过程可知,从总体行为设计开始到最终的逻辑综合,每一步都要进行仿真检查,这样有利于尽早发现设计中存在的问题,从而可以大大缩短系统的设计周期。

(2)系统可大量采用PLD芯片。

由于目前众多制造PLD芯片的厂家,其工具软件均支持VHDL语言的编程。所以利用VHDL语言设计数字系统时,可以根据硬件电路的设计需要,自行利

用PLD设计自用的ASIC芯片,而无须受通用元器件的限制。

(3)采用系统早期仿真。

从自上而下的设计过程中可以看到,在系统设计过程中要进行三级仿真,即行为层次仿真、RTL层次仿真和门级层次仿真。这三级仿真贯穿系统设计的全过程,从而可以在系统设计的早期发现设计中存在的问题,大大缩短系统设计的周期,节约大量的人力和物力。

(4)降低了硬件电路设计难度。

在传统的设计方法中,往往要求设计者在设计电路之前写出该电路的逻辑表达式或真值表(或时序电路的状态表)。这一工作是相当困难和繁杂的,特别是当系统比较复杂时更是如此。而利用VHDL语言设计硬件电路时,就可以使设计者免除编写逻辑表达式或真值表之苦,从而大大降低了设计的难度,也缩短了设计的周期。

(5)主要设计文件是用VHDL语言编写的源程序。

与传统的电路原理图相比,使用VHDL源程序有许多好处:其一是资料量小,便于保存。其二是可继承性好。当设计其他硬件电路时,可使用文件中的某些库、进程和过程等描述某些局部硬件电路的程序。其三是阅读方便。阅读程序比阅读电路原理图要更容易一些,阅读者很容易在程序中看出某一电路的工做原理和逻辑关系。而要从电路原理图中推知其工作原理则需要较多的硬件知识和经验。

2.4 VHDL语言的基本结构

一个完整的VHDL语言程序通常包含实体(Entity)、构造体(Architecture)、配置(Configuration)、程序包(Package)和库(Library)5个部分。前4个部分是可分别编译的源设计单元。实体用于描述所设计的系统的外接口信号;构造体用于描述系统内部的结构和行为;程序包存放各种设计模块都能共享的数据类型、常数和子程序等;配置用于从库中选取所需单元来组成系统设计的不同版本;库存放已经编译的实体、构造体、程序包和配置。库可由用户生成或由ASIC芯片制造商提供,以便于在设计中为大家所共享。

2.5本章小结

本章开始介绍了VHDL语言的设计分格以及设计中注意的问题。

目前国内IT行业快速发展,以及ASIC合了Avant!和CO-Design,Cadence

合了GDA等,形成了几大巨头的局面。而各可编程器件厂商,像Xilinx和Altera,也积极与EDA紧密合作,针对目前硬件描述语言的发展和国家芯片制造生产的发展战略,国内如何在原EDA基础薄弱的情况下迅速发展,使EDA成为一个合理,健康而必比可少产业;将基础研究活动与独立产生的作用合理地结合,建议开展如下的工作:

为了实现我国的芯片设计自主化,必须夯实基础,再结合VHDL的基础上,推广Verilog HDL设计语言,使硬件设计的底层单元库可以自主研制。

根据目前芯片系统的发展趋势,对系统级语言进行比较研究,在Superlog,SystemC等语言中作出选则,并进行相关工具的推广,以及与相关企业进行合作等。

深入HDL语言的综合和仿真等模型的研究,努力在与国外合作的基础山,建立自主知识产权的EDA公司。

积极加入EDA目前正在进行的标准化工作,做到了解、学习、应用、吸收、参与并重。

政府积极加入,重视生产、学习、研发的合作,开展卓有成效的发展模式。

3.矩阵键盘接口电路原理和数码管显示原理

3.1矩阵键盘接口电路的原理

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。

在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。

由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,列线通过电阻接正电源,并将行线所接的FPGA的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。

4*4行列式键盘的电路原理如下图所示:

图3.1 : 4*4行列式键盘的电路原理图

设置扫描信号为keydrv3~keydrv0,列线按键输入信号keyin3~keyin0与按键位置的关系如表3.1所示:

表3.1 : 扫描信号和列线按键输入信号与按键之间的关系表

key_x 3~ key_x 0 key_y 3~ key_y 0 对应的按键

1110 1110 0 1101 1 1011 2 0111 3 1110 4

1101 1101 5

1011 6

0111 7

1011 1110 8 1101 9 1011 A 0111 B 1110 C

0111 1101 D

1011 E

0111 F

3.2数码管显示原理

数码管的显示数据的方式有静态显示和动态显示之分。

所谓静态显示,就是将被显示的数据的BCD码通过各自的4—7/8显示译码器译码后,分别接到显示译码器的显示驱动端a—g(p),而公共端COM则根据数码管的类型(共阴/共阳)分别接GND/VCC。

所谓动态显示,就是将被显示的数据的BCD码按照一定的变化频率,在不同的时刻周期性地分别送到一个数据总线上,再通过一个公共的4—7/8显示译码器译码后,接到多个显示译码的公共显示驱动端口a—g(p)上,同时,在不同的时刻周期性的选通对应的数码管的公共端口COM。

本设计采用的是共阴极数码管,采用的显示方式是静态显示,其电路中只用到一个数码管,当有键按下时,数码管将显示出对应的键码值。

3.3本章小结

本章首先介绍了一下矩阵键盘的设计思路,总体来说行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。最后介绍了一下4*4键盘的总体设计思路。另外还简单地介绍了一下数码管的显示原理。

4.总体设计和各模块设计

系统结构的总体设计如下:

由行列式键盘原理就可以知道,要正确的完成键盘输入工作必须有按键扫描电路产生key_x3~ key_x0信号。同时还必须有按键译码电路从key_y3~key_y0信号和key_x3~ key_x0信号中译码出按键的值。

由于各个模块需要的时钟频率是不一样的,因此时钟产生模块就是用于产生各个模块需要的时钟信号。因此得到接盘接口电路的结构如上图所示。

4.1时钟产生模块

本设计中设计了一个带 参数的时钟分频模块,只要 在软件中设置要分频的参数 就可以得到预分的频率。从 而实现了模块复用和代码的 灵活性。

时钟产生模块是用于扫

描时钟的,它的输出共给键盘扫描模块和数码管显示模块。

时钟产生模块的具体程序请在附录程序里查阅。

4.2键盘扫描模块

键盘扫描模块是用于产生key_x3~key_x0信号,其变化的顺序依次是

1110-----1101-----1011-----0111--- ……周而复始地扫描。其停留 在某个状态的时间大约为10ms

。 更短的停留时间是没有必要的,

因为人按键的时间大约为10ms ,

不可能有更快的按键动作发生;

另外,更短的停留时间还容易采集到抖动信号,会干扰判断。而太长的停留时间则会使某 些较快的按键东走丢失。键盘扫描模块的具体程序请在附录里查阅。

4.3数码管显示模块

本设计采用1为数码管静态扫描显示 矩阵键盘输出的键值,具体程序请在附录 里查阅。

4.4顶层电路实现

本设计采用元件例化语句,在顶层电 路模块里综合的调用时钟产生模块、键盘 扫描模块和数码管显示模块,从而实现矩 阵键盘接口电路的设计。顶层电路实现的 具体程序请在附录里查阅。

4.5本章小结

本章具体介绍了矩阵键盘接口电路的总体设计和各模块的具体设计及其外部接口电路。具体阐述了,矩阵键盘接口电路的总体设计思路和各个模块是如何有机的组成一个实现矩阵键盘接口电路的系统。

附录1:总体设计电路原理图:

附录2:硬件实物图

附录3:EP1C3T144C8N的PCB电路图

附录4:顶层电路实现的具体程序

module TOP_file (

input clk,

input rst_n,

input [3:0]key_x,

output wire [3:0]key_y,

//output wire wei,

output wire[7:0] duan

);

wire clk_50K,clk_50HZ;

//************** 分频例化*********************** clkdiv #(.M(1000)) //1000分频--->50KHZ

clkdiv_50K (.clk(clk),

.clk_div_M(clk_50K));

clkdiv #(.M(1000)) //1000分频--->50HZ,给键盘扫描clkdiv_50HZ (.clk(clk_50K),

.clk_div_M(clk_50HZ));

//************** 键盘例化***********************

wire [3:0]keyboard_val;

SCAN SCAN_1 (

.key_clk(clk_50HZ), //键盘扫描时钟,20ms

.rst_n(rst_n), //异步复位

.key_y(key_y), //矩阵键盘的列,FPGA输出

.key_x(key_x), //矩阵键盘的行,FPGA输入

.keyboard_val(keyboard_val)); //最终的键值

//************** 数码管例化***********************

/***** 数码管设计例化*********/

SMG SMG_1 (.clk(clk_50K),

.data_in(keyboard_val),

.duan(duan));

endmodule

附录5:时钟产生模块实现的具体程序

module clkdiv

#(parameter M = 50) //参数定义,默认为50,即50分频

(input wire clk,

output wire clk_div_M);

localparam N = log2(M/2);//M/2值所需位数

reg clk_div_r = 0;

assign clk_div_M = clk_div_r;

reg[N-1:0] cnt = 0; //分频计数器

always @ (posedge clk)

begin

if(cnt == (M/2-1) )

begin

cnt <= 0;

clk_div_r = ~clk_div_r;

end

else cnt <= cnt + 1'b1;

end

//log2 constant function

function integer log2(input integer n);

integer i;

begin

log2 = 1;

for(i=0; 2**i

log2 = i+1;

end

endfunction

endmodule

该程序中设计了一个带参数的时钟分频模块,只要在软件中设置要分频的参数就可以得到预分的频率。从而实现了模块复用和代码的灵活性。

其中定义了一个函数log2用于求分频系数的模。当分频计数器cnt计数到M/2-1时令cnt清零并使clk_div_r翻转,从而得到clk/M的时钟频率。

附录6:键盘扫描模块实现的具体程序

module SCAN (

key_clk, //键盘扫描时钟,20ms

rst_n, //异步复位

key_y, //矩阵键盘的列,FPGA输出

key_x, //矩阵键盘的行,输入FPGA

keyboard_val); //最终的键值

input key_clk;

input rst_n;

input [3:0] key_x; //行,输入

output reg [3:0] key_y; //列,输出

output reg [3:0] keyboard_val;//键值

//*******************************************

// 可插入键盘扫描的时钟产生代码

//*******************************************

//********** 状态机开始,采用三段式状态机********

reg [5:0] current_state,next_state; //定义现态,次态

// 状态的定义,因状态数较少,故使用独热码,以使系统更稳定

parameter NO_KEY_PRESSED = 6'b000_001; // 没有按键按下

parameter SCAN_COL0 = 6'b000_010; // 扫描第0列

parameter SCAN_COL1 = 6'b000_100; // 扫描第1列

parameter SCAN_COL2 = 6'b001_000; // 扫描第2列

parameter SCAN_COL3 = 6'b010_000; // 扫描第3列

parameter KEY_PRESSED = 6'b100_000; // 有按键按下

always @ (posedge key_clk or negedge rst_n) begin //第一段:次态--->现态

if(!rst_n)

current_state <= NO_KEY_PRESSED;

else

current_state <= next_state;

end

always @ * begin //第二段:根据现态,确定次态(current_state)

case(current_state)

NO_KEY_PRESSED: //无键按下状态

键盘扫描

next_state = SCAN_COL0;

else begin

next_state = NO_KEY_PRESSED;

end

SCAN_COL0:

if (key_x != 4'hF)

next_state = KEY_PRESSED;

else

next_state = SCAN_COL1;

SCAN_COL1:

if (key_x != 4'hF)

next_state = KEY_PRESSED;

else

next_state = SCAN_COL2;

SCAN_COL2:

if (key_x != 4'hF)

next_state = KEY_PRESSED;

else

next_state = SCAN_COL3;

SCAN_COL3:

if (key_x != 4'hF)

next_state = KEY_PRESSED;

else

next_state = NO_KEY_PRESSED;

KEY_PRESSED:

相关文档
最新文档