FPGA之PS键盘驱动_第1页
FPGA之PS键盘驱动_第2页
FPGA之PS键盘驱动_第3页
FPGA之PS键盘驱动_第4页
FPGA之PS键盘驱动_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

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

文档简介

1、小梅哥和你一起深入学习FPGA之PS2键盘驱动在我们的电子系统中,当需要用到大量的按键输入时,普通的独立按键和矩阵键盘已经无法满足我们的输入需求,这个时候,我们需要使用一种功能更加强大的键盘,来帮助我们输入更多的信息。在pc机上,我们经常使用104键的键盘,这种键盘与pc机的接口,可分为USB接口和PS2接口,我们FPGA要实现USB接口比较困难,因为USB的接口线路,不是标准的TTL电平,而PS2接口,则使用标准的TTL电平,那么我们今天就使用FPGA来解码驱动一个采用PS2接口的pc机键盘,用这个键盘来扩展我们FPGA的输入系统,以使我们能够方便的输入更多的信息。一、 实验目的实现采用PS

2、2协议的PC机键盘的解码,最终将PS2键盘作为FPGA系统的一个标准输入设备。二、 实验原理PS2键盘的内部结构我们不需要过多的去关注,我们只需要关心其接口协议,正确的解码其发送过来的按键信息即可,至于解码到的按键信息该怎么处理,不同的应用有不同的处理方式,这里就不做过多的介绍。PS2协议的简单描述如下:PS2协议总共由两根线组成,一根时钟线和一根数据线。这里我们将采用PS2协议的键盘称为从机,将控制和解码PS2协议的一方成为主机,生活中最常见的主机便是我们的PC机。PS2总线协议的两根线中,时钟线传输时钟信号,该时钟信号始终由从机,即键盘产生。PS2协议发送一个字节的数据总共有11位,分别为

3、1位起始位8位数据位1位校验位1位停止位PS2从机发送一个完整数据包的时序图如下所示:图2-1 PS2从机发送数据时序图相信熟悉UART协议的同学一眼就能看出来,PS2协议和我们最熟悉的UART通信协议非常相似,那么我们的工作就简单了,既然键盘按照这个协议发送数据,我们FPGA作为主机,只需要正确的实现该协议的解码,将其中的8位数据位读取出来即可。由图可知,数据在时钟的下降沿处是稳定的,因此我们只需要去捕获时钟信号的下降沿,并在检测到这个下降沿时去读取数据线上的电平,就能够正确的读到数据。以上是PS2协议中从机到主机的一个通讯过程,实际在PS2协议中,包含了从机到主机和主机到从机的通信时序,只

4、是在我们进行PS2键盘的解码时,可以不需要进行主机到从机的通信,因此这部分内容小梅哥就不在这里讲解了,如果大家以后要解码PS2鼠标的话,就会用到主机到从机的通信了。上面只是简单的介绍了PS2从机到主机的通信协议,我们知道了键盘是一个字节一个字节的往主机发送数据的,但是,每个字节代表了什么内容呢,我们还需要对照键盘编码对照表来查看。键盘扫描码分为第一套扫描码、第二套扫描码和第三套扫描码,我们日常生活中常见的扫描码绝大多数采用第二套扫描码,因此这里小梅哥就只附上第二套扫描码的内容。实际一个按键由按下到释放时键盘将按照如下的规定往主机发送数据:只要一个键被按下,这个键的通码(MAKE)就被发送到计算

5、机。通码只表示键盘上的一个按键,它不表示印刷在按键上的那个字符。 这就意味着在通码和ASCII码之间没有已定义好的关联, 直到主机把扫描码翻译成一个字符或命令。 虽然多数第二套通码都只有一个字节宽,但也有少数“ 扩展按键”的通码是两字节或四字节宽,这类的通码第一个字节总是为E0H(如“END”、“HOME”)。正如键按下通码就被发往计算机一样, 只要键一释放, 断码就会被发送。每个键都有它自己唯一的通码,它们也都有唯一的断码。 幸运的是,你不用总是通过查表来找出按键的断码 在通码和断码之间存在着必然的联系。 多数第二套断码有两字节长,它们的第一个字节是F0H, 第二个字节是这个键的通码。例如,

6、当我们按下键盘上的“A”键时,键盘就会往主机发送”A”键对应的通码(MAKE)”1C”,如果你一直按下这个按键不释放,那么在一个短暂的延时之后,键盘会再次开始,以一定的速率持续向主机发送”1C“,直到该按键被释放。在该按键被释放后,键盘将会向主机发送“A ”的断码(Break),即首先发送“F0”,然后下一个字节再马上发送“1C”。如果我们按下的是“END”、“PAGE UP”等扩展按键时,会怎么样呢?这里,以”END”键举例。当”END“键被按下后,键盘会首先向主机发送“E0”,发送完成后,又会接着发送下一个字节“69”,释放时也与前面的普通按键类似,先发送“E0”,然后发送“F0”,最后再

7、发送“69”。由上述分析可知,我们FPGA在解码到一次数据后,还需要对这个数据进行分析判断,判断该数据是否为断码标志“F0”以及扩展码标志”E0“。 三、 硬件设计PS2电路结构简单,因此这里就略去。四、 架构设计本实验我们进行PS2键盘的解码实验,并将解码到的结果显示在数码管上,同时,为了使我们更加直观的感受到按键被按下和释放,小梅哥在这里增加了一个蜂鸣器,当有按键按下或释放(包括长按时每接收到一个通码)时,蜂鸣器发出一个短暂的响声,来反馈给操作者,让我们知道我们的解码模块解码到了按键信息。设计结构如下图所示:Key_DispDig_Led_seg7:0Dig_Led_sel2:0Rst_n

8、Data23:0DIG_LED_DriverClkBeepBeep14d0Beep_EnPS2_Key_Board_DriverKey_FlagKey_Value9:0PS2_DinPS2_Clk图4-1 led实验模块组织结构图详细端口名及其意义如下端口说明端口名端口功能或意义Rst_n全局复位Clk系统时钟输入端口Dig_Led_sel数码管位选输出,接三八译码器Dig_Led_seg数码管段选输出,接数码管8个段PS2_DinPS2数据线PS2_ClkPS2时钟线表4-1 独立按键检测实验端口说明因为存在模块间的连接,因此有部分内部信号,下表为内部信号的名称和功能说明内部信号说明内部信号

9、名内部信号功能或意义Data数码管待显示数据,共24位,含每4位组成一个BCD码,对应一个数码管需要显示的数据内容,这里高14位接0,低10位接到了Key_Value上,以显示Key_Value的值。Key_Value按键检测结果输出,总共10位,其中最高位为通/断码标志位,为0表示通码,为1表示断码;次高位为短码和长码(扩展码)标志位,为0表示短码,为1表示长码;低8位为数据位。Beep_En蜂鸣器鸣叫使能信号,为高则使能一次鸣叫,这里接到了Key_Flag上,因此,只要一成功解码到一次按键事件(按下、释放或长按时的每一次数据发送)Key_Flag按键检测成功标志信号表4-2 独立按键检测实

10、验内部信号说明五、 代码分析这里,解码的关键是PS2接口的时钟信号,该时钟为异步时钟,我们需要通过边沿检测的方式来检测其下降沿,以便根据下降沿的个数来确定每个时钟我们因该做什么,边沿检测的电路,前面几个实验已经讲过很多次了,这里便不再做过多的解释,贴上代码即可:reg PS2_Clk_Tmp0,PS2_Clk_Tmp1,PS2_Clk_Tmp2,PS2_Clk_Tmp3;wire nedge_PS2_Clk;/*PS2从机时钟下降沿检测标志信号*/always (posedge Clk or negedge Rst_n)if(!Rst_n) beginPS2_Clk_Tmp0 <= 1&

11、#39;b0;PS2_Clk_Tmp1 <= 1'b0;PS2_Clk_Tmp2 <= 1'b0;PS2_Clk_Tmp3 <= 1'b0;endelse beginPS2_Clk_Tmp0 <= PS2_Clk;PS2_Clk_Tmp1 <= PS2_Clk_Tmp0;PS2_Clk_Tmp2 <= PS2_Clk_Tmp1;PS2_Clk_Tmp3 <= PS2_Clk_Tmp2;end/*-获取PS时钟信号的下降沿-*/assign nedge_PS2_Clk = !PS2_Clk_Tmp0 & !PS2_Clk_

12、Tmp1 & PS2_Clk_Tmp2 & PS2_Clk_Tmp3;一个PS2的数据包总共由11位组成,因此会有11个时钟下降沿,因此我们必须对下降沿的个数准确计数,才能保证我们能够解码得到正确的数据,这里,使用我们的PS2时钟下降沿标志信号来使能我们的计数器自加,当计数器加到11后,表示一个数据包接收完成,将计数器清零,等待下一个下降沿的到来,相关代码如下:/*-PS2时钟下降沿个数计数器-*/always (posedge Clk or negedge Rst_n)if(!Rst_n)Cnt1 <= 4'd0;else if(Cnt1 = 4'd11

13、)Cnt1 <= 4'd0;else if(nedge_PS2_Clk)Cnt1 <= Cnt1 + 1'b1;接下来,就是根据时钟下降沿的计数个数,来读取对应位的数据了,因为采用了非阻塞赋值的方式,因此,PS2时钟下降沿到来时,此时Cnt1执行自加1操作,但同时如果也来用Cnt1的值来确定数据位数,就一定会造成错误,因为此时,Cnt1的加1操作并没有执行,而是会在下一个时钟上升沿到来之时才变,因此,为了保证我们使用的Cnt1的数据是已经更新了的,我们需要在Cnt1已经变化之后再来使用其值做判断,即在PS2时钟下降沿检测成功后,滞后一个系统时钟周期后再来读取PS2_

14、Din上的值,比较简单的操作方式就是将PS2时钟下降沿检测标志信号再用寄存器打一拍,对应代码如下:always (posedge Clk)nedge_PS2_Clk_Shift <= nedge_PS2_Clk;可能这里相对比较难以理解,希望大家结合仿真结果自学揣摩体会。接下来就是根据Cnt1的计数值来读取每一位的数据了,这部分代码很简单,如下所示:/*-读取8位数据位-*/always (posedge Clk or negedge Rst_n)if(!Rst_n)Data_tmp <= 8'd0;else if(nedge_PS2_Clk_Shift) begincas

15、e(Cnt1)4'd2:Data_tmp0 <= PS2_Din;4'd3:Data_tmp1 <= PS2_Din;4'd4:Data_tmp2 <= PS2_Din;4'd5:Data_tmp3 <= PS2_Din;4'd6:Data_tmp4 <= PS2_Din;4'd7:Data_tmp5 <= PS2_Din;4'd8:Data_tmp6 <= PS2_Din;4'd9:Data_tmp7 <= PS2_Din;default:Data_tmp <= Data_t

16、mp;endcaseendelseData_tmp <= Data_tmp;通过以上操作,我们就能正确的解码PS2键盘发送过来的每一个字节的数据了,但是,这些数据代表了什么呢,如果是断码标志,或者是长码标志,我们又该如何进行操作呢,这里,小梅哥先贴上我的处理代码:always (posedge Clk or negedge Rst_n)if(!Rst_n) beginBreak_r <= 1'b0;Key_Valve <= 10'd0;Key_Flag <= 1'b0;Long_Code_r <= 1'b0;endelse if(C

17、nt1 = 4'd11) beginif(Data_tmp = 8'hE0)/*判断是否为长码*/Long_Code_r <= 1'b1;/*将长码标志置1*/else if(Data_tmp = 8'hF0)/*判断是否为断码*/Break_r <= 1'b1;/*将断码标志置1*/else begin/*检测到的数据为通码*/Key_Valve <= Break_r,Long_Code_r,Data_tmp;/*将长码标志、断码标志和解码到的按键码输出*/Key_Flag <= 1'b1;/*产生解码成功标志信号*/L

18、ong_Code_r <= 1'b0;/*清零长码标志*/Break_r <= 1'b0;/*清零断码标志*/endendelse beginKey_Valve <= Key_Valve;Key_Flag <= 1'b0;Break_r <= Break_r;Long_Code_r <= Long_Code_r;end这里,小梅哥使用了两个标志寄存器,当检测数据完成后,即Cnt1=11时,就对解码到到数据进行判断,如果Data_tmp = 8'hE0,则解码到到数据为长码(扩展码)标志,此时便将长码标志寄存器置1,如果Data

19、_tmp = 8'hF0,则解码到到数据为断码标志,此时便将断码标志寄存器置1。然后,当解码到其他数据(如单字节通码或双子节通码的第二个字节)后,便将解码到的数据连同断码和长码标志寄存器的状态输出,并给出按键检测成功标志(Key_Flag置1)。六、 仿真分析为了对小梅哥设计的PS2键盘解码驱动进行验证,小梅哥编写了一个Testbench来模拟键盘发送数据,通过观察键盘解码驱动的输出来验证该解码模块的正确性,关于模拟键盘发送数据,在一份介绍PS2协议的手册中有如下描述:我推荐仿真键盘/鼠标采用下面的过程发送一字节的数据到主机:1) 等待Clock线为高电平, 即等待主机释放Clock线

20、;2) 延时50us;3) 判断Clock线是否为高电平?No 跳到第1步;4) Data线是否为高电平?No 放弃(跳到从主机读取字节的程序中) 。5) 延迟20us,输出起始位(0) , 然后延迟20us, 再拉低Clock线保持40us后释放Clock线, 形成一个脉冲;6) 延时20us, 测试Clock线是否为高电平?No 跳到第1步;7) 输出第1个数据位, 然后延时20us, 再拉低Clock线保持40us后释放Clock线, 形成一个脉冲;8) 重复6-7步发送剩下的7个数据位和校验位;9) 延时20us, 测试Clock线是否为高电平?No 跳到第1步;因此,我们的模拟键盘发

21、送数据的过程只需要依照上面的流程来即可,这里贴上小梅哥编写的testbench:timescale 1ns/1nsmodule PS2_Key_Board_Driver_tb;reg Clk;/*system clock*/reg Rst_n;/*复位信号*/reg PS2_Din;/*PS2键盘数据线*/reg PS2_Clk;/*PS2键盘时钟线*/wire Key_Flag;/*解码得到键值标志信号*/wire 9:0 Key_Valve;/*解码结果,其中最高位为通/断码识别位,0为通码,1为断码,低八位为码值*/PS2_Key_Board_Driver u1(.Clk(Clk),.R

22、st_n(Rst_n),.PS2_Din(PS2_Din),.PS2_Clk(PS2_Clk),.Key_Flag(Key_Flag),.Key_Valve(Key_Valve);initial beginClk = 1;Rst_n = 0;PS2_Din = 1;PS2_Clk = 1;#200;Rst_n = 1;Key_Event(8'h1A);/* Z */#400;Key_Event(8'h35);/* X */#800;Key_Event(8'h44);/* O */#1320;Key_Event(8'h4D);/* P */#2560;Key_Ev

23、ent(8'h24);/* E */#1230;Key_Event(8'h31);/* N */#20000;Long_Key_Event(8'h70);/* "INSERT" */#400;Long_Key_Event(8'h6c);/* "HOME" */#800;Long_Key_Event(8'h7d);/* "PAGE UP" */#1320;Long_Key_Event(8'h71);/* "DELETE" */#2560;Long_Key_Event(8

24、'h69);/* "END" */#1230;Long_Key_Event(8'h7a);/* "PAGE DOWN" */#2000000;$stop;end/*-生成工作时钟-*/always #10 Clk = Clk;/*-任务:以PS2协议发送一个字节的数据-*/task Send_data;input 7:0Data;beginPS2_Din = 0;/*发送起始位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data0;/*发送第0位*/#20000;PS2

25、_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data1;/*发送第1位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data2;/*发送第2位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data3;/*发送第3位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data4;/*发送第4位*/#20000;PS2_Clk = 0;#40000;PS2_

26、Clk = 1;#20000;PS2_Din = Data5;/*发送第5位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data6;/*发送第6位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = Data7;/*发送第7位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = 0;/*暂时忽略校验位*/#20000;PS2_Clk = 0;#40000;PS2_Clk = 1;#20000;PS2_Din = 1;/*停止位*/#20000;PS2_Clk = 0;#40000;

温馨提示

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

评论

0/150

提交评论