ps2接口主要应用与计算机的键盘与鼠标的接口,但由于不支持热插拔,使用的时候需要关机插上,所以现在很多的鼠标键盘已经都改用USB接口了,但我们之所以要学习ps2接口的原因很简单,还是为了学习FPGA,练习我们设计数字电路的能力。
ps2的接口如下图所示:
其中,1是数据线DATA;
2是预留N/C;
3是GND;
4是VCC(+5V);
5是时钟信号线CLK;
6是预留N/C;
数据传输的时序图如下图所示:
一般的ps2接口,都是ps2产生时钟信号,而且是在上升沿的时候把数据发送出去,而在下降沿的时候被采样,大多数的ps2设备的发送数据的时钟频率是15Khz-20Khz。每一帧的数据有11位或者12位数据,其中包括:
1位起始位:总为逻辑0;
8位数据位:低位在前;
1位奇偶校验位;
1位停止位:总为逻辑1;
1位答应位:仅用于主机对设备通信中(在本次键盘接口设计中不用)
没错,我们回到时序,主要的目的是从时序中得到数据,也就是第2-9个时钟。在这里大家有没有注意到一点,就是我们的数据顺序是D0、D1、D2、D3、D4、D5、D6、D7这表明我们ps2一帧发送过来的数据是8位,数据是先发送低位再发送高位。查找资料可以知道ps2在不工作时时钟线和数据线都是高电平。所以在设计ps2接收模块的时候,我们首先要做一个下降沿检测的小模块,来检测信号什么时候开始发送。
其中数据发送模式如下,当键盘的某一个按键被按下的时候,键盘会往外发送那一个按键的通码,当按键松开的时候,键盘就会往外发送那一个按键的的断码+通码,需要注意的是,如果按着一个按键不放的话,键盘会以一定的频率发送那一个按键的通码。键盘的通码与断码表如下图所示:
由于工程量的关系,我们这次仅仅做识别右侧小键盘的0-9的10个按键识别,只要把这几个按键识别出来了,其他按键的识别都是一样的。而右侧小键盘的0-9的通码与断码如下图所示:
现在我们具体来举一个例子来说明ps2接口的工作原理,比如我现在按下按键小键盘中的0键,再按下按键9,然后把按键0松开,最后再松开按键9,ps2往FPGA发送的数据就会如下,先发0按键的通码8’h70,再发9按键的通码8’h7d,接着发0按键的断码8’hf0,然后再发0按键的通码8’h70,接着再发9按键的断码8’hf0,最后再发9按键的通码8’h7d,发送数据的顺序如下: 8’h70→8’h7d→8’hf0→8’h70→8’hf0→8’h7d。
现在我们已经理解了键盘ps2的数据发送时序跟键盘的编码方式,我们就可以设计一个数字电路来把ps2键盘的数据给接收了,设计的思想是这样的,首先我们要设计一个ps2接收模块,其中ps2接收模块要包括有下降沿检测,11位寄存器(用于保存数据),数据有效标志位(用于标记一个完整数据发送完毕);ps2接收模块完成之后,我们还有设计一个解码模块,解码模块之间用查表法来完成即可;解码模块之后,我们还需要一个状态机,把解码后的数据做整理;最后还需要一个数码管显示模块,用于实时显示状态机发送的数据。
设计的模块架构图如下:
其中PLL模块是一个锁相环,用于把FPGA输入的50Mhz时钟信号分频成1Mhz的系统时钟。
Rst_delay模块是一个复位延时模块,FPGA刚上电的时候,锁相环还有进入稳定的工作,所以通过Rst_delay模块来实现,在锁相环未进入稳定工作之前,让整个系统处于复位状态。
ps2_scan模块是不断接收从键盘发往FPGA的数据,每得到一个有效的数据,data_valid会拉高,表示可以采样当年key_data的数据。
decode模块的功能就是解码的功能,把键盘的通码解码成数码管显示出来的数字;
ps2_fsm模块是用于判断通码与断码,判断按键是否长按,把从键盘接收的数据整理好,输出给led_display模块显示在数码管上。
led_display模块是实时把从ps2_fsm的数据实时显示在数码管上。
Rst_delay代码如下:
ps2_scan代码如下:
decode代码如下:
ps2_fsm状态转移图:
ps2_fsm代码如下:
Led_display的代码如下:
ps2_interface顶层代码如下:
仿真代码如下:
仿真波形图如下:(注意,仿真时,系统时钟使用的是50Mhz,下板使用时1Mhz)
由上图仿真图可知,模拟键盘信号第一次发送的数据是0→1→0→0→1→0→1→1→0→1→1,舍去第一位的起始位和倒数第一、二位的停止位与奇偶校验位,得到的数据时8’b0110_1001=8’h69,等于键盘按键1,decode模块将8’h69解码成8’hf9,同时ps2_fsm将8’hf9(数码管显示等于1)显示在第一个数码管上;模拟键盘信号第二次发送的数据是0→0→0→0→0→1→1→1→0→1→1,舍去第一位的起始位和倒数第一、二位的停止位与奇偶校验位,得到的数据时8’b0111_0000=8’h70,等于键盘按键0,decode模块将8’h70解码成8’hc0,同时ps2_fsm将8’hc0(数码管显示等于0)显示在第二个数码管上;模拟键盘信号第三次发送的数据是0→0→0→0→0→1→1→1→1→1→1,舍去第一位的起始位和倒数第一二位的停止位与奇偶校验位,得到的数据时8’b1111_0000=8’hf0,等于键盘断码表示有一个按键松开,decode模块将8’hf0解码成8’hf0,同时ps2_fsm将断码标志位打开;模拟键盘信号第四次发送的数据是0→1→0→0→1→0→1→1→0→1→1,舍去第一位的起始位和倒数第一、二位的停止位与奇偶校验位,得到的数据时8’b0110_1001=8’h69,等于键盘1,decode模块将8’h69解码成8’hf9, ps2_fsm断码标志位有效,由于数码管第一个数据等于f9,所以数码管第一个数据清零。
把程序下载到至芯板子的效果图:
把按键3按着不放;
松开按键3;
先按按键2,再按按键3(不松手);
松开按键3;
再松开按键2;