PS/2键盘时钟的VHDL描述技巧
PS/2通讯协议是一种双向同步串行通讯协议。通讯的两端通过Clock(时钟脚)同步,并通过Data(数据脚)交换数据。任何一方如果想抑制另外一方通讯时,只需要把Clock(时钟脚)拉到低电平。一般两设备间传输数据的最大时钟频率是33kHz,大多数PS/2设备工作在10~20kHz。推荐值在15kHz左右,也就是说,Clock(时钟脚)高、低电平的持续时间都为40μs。每一数据帧包含11~12个位。
数据帧格式说明
|
1个起始位 |
总是逻辑0 |
|
8个数据位 |
(LSB)低位在前 |
|
1个奇偶校验位 |
奇校验 |
|
1个停止位 |
总是逻辑1 |
|
1个应答位 |
仅用在主机对设备的通讯中 |
PS/2设备和PC机的通讯:
PS/2设备的Clock(时钟脚)和Data数据脚都是集电极开路的,平时都是高电平。当PS/2设备等待发送数据时,它首先检查Clock(时钟脚)以确认其是否为高电平。如果是低电平,则认为是PC机抑制了通讯,此时它必须缓冲需要发送的数据直到重新获得总线的控制权(一般PS/2键盘有16个字节的缓冲区,而PS/2鼠标只有一个缓冲区仅存储最后一个要发送的数据)。如果Clock(时钟脚)为高电平,PS/2设备便开始将数据发送到PC机。一般都是由PS/2设备产生时钟信号。发送时一般都是按照数据帧格式顺序发送。其中数据位在Clock(时钟脚)为高电平时准备好,在Clock(时钟脚)的下降沿被PC机读入。
PS/2设备到PC机的通讯时序如图2所示

当需要用VHDL语言来描述Clock(时钟脚)的下降沿,如果简单的描述为:
if clk='0' then
...
这种描述方法是非常不妥的,原因很多,比如PS/2键盘抖动无法消除。
比较好的描述办法是:
//假设SYS_CLK为系统时钟,其频率远大于PS/2时钟clk
signal now_ps2clk,pre_ps2clk:STD_LOGIC;定义了两个内部信号,用于表示PS/2Clock(时钟脚)CLK的当前状态和前一状态
if rising_edge(SYS_CLK) then
pre_ps2clk<=now_ps2clk;
now_ps2clk<=clk;
if(pre_ps2clk>now_ps2clk) then
...
这里用判断语句if(pre_ps2clk>now_ps2clk) 来探测Clock(时钟脚)CLK由高电平向低电平变化的这一过程,因为如果是由PS/2键盘主动发起的通信过程的话,按键比较容易出现抖动导致不稳定,这里加个时钟判断,这样就比较稳定了
以后的数据通信过程就比较简单了,用个计数器计数,按部就班的接收就行了