PS/2协议的verilog HDL实现

回归!

简报

键盘和鼠标是现在绝大部分人使用电脑的标配物件。它们有发光的,有花花绿绿的,有长尾巴的,有带电池的。但又有谁人记得,曾经那六孔的插口?作为本专栏的第一篇文章,就让笔者带领大家来认识计算机与键盘、鼠标进行通信的这一远古协议——SP/2。

简介

1987年,大家熟知的IBM公司推出了一款用于键盘与主机进行通信的接口标准——SP2。PS2接口一共有六根引脚,但其中只有四根引脚是有意义的:Clock(时钟),Data(数据),电源,接地。值得注意的是,其中的Clock与Data是双向的引脚。因此,PS/2协议是一种双向同步串行通信协议。它的工作方式是:通信的两端通过Clock同步,并通过Data交换数据。当任何一方试图抑制另外一方的通信时,只需要时钟引脚拉低即可。由此可见,PS/2协议适合于在两个设备之间进行通信。但是通过一定的方式对其进行变形,亦可以适应在多个设备之间进行通信。这种例子笔者将会在遥远的将来为大家进行呈现(手动狗头)。大多数PS/2设备工作在10~20kHz之间。

数据帧

PS/2的每一个数据帧都包含11~12位。说明如下:

这是数据帧:ABCDEFGHIJKL

  • A:数据起始位,总是逻辑0(低电平);
  • B~I:数据位(共八位),低位在前;
  • J:奇偶校验位,校验方式为奇校验;
  • K:停止位,总是逻辑1(高电平);
  • L:应答位,仅用于主机对设备进行通信的场合中。

数据
设备产生时钟信号,主机则是通过该信号来对设备数据进行读取。

代码

module PS2 (
    input           clk,
    input           rst,
    input           PS2D,
    input           PS2C,
    output [15:0]   key
);

reg         ps2c;               //clock transfer to slave
reg         ps2d;               //data ready to slave
reg  [7:0]  ps2c_fliter;
reg  [7:0]  ps2d_fliter;
reg  [10:0] shift1;
reg  [10:0] shift2;

assign      key = { shift2[8:1], shift1[8:1] };

always@( posedge clk or posedge rst )
begin
    if( rst )
    begin
        ps2c            <= 1;
        ps2d            <= 1;
        ps2c_fliter     <= 0;
        ps2d_fliter     <= 0;
    end
    else begin
        ps2c_fliter[7]  <= PS2C;
        ps2d_fliter[7]  <= PS2D;
        ps2c_fliter[6:0]<= ps2c_fliter[7:1];
        ps2d_fliter[6:0]<= ps2d_fliter[7:1];
        if( ps2c_fliter == 8'b11111111 )
            ps2c <= 1;
        else if( ps2c_fliter == 8'b00000000 )
            ps2c <= 0;
        else
            ps2c <= ps2c;
        if( ps2d_fliter == 8'b11111111 )
            ps2d <= 1;
        else if( ps2d_fliter == 8'b00000000 )
            ps2d <= 0; 
        else
            ps2d <= ps2d;
    end
end

always@( negedge ps2c or posedge rst )
begin
    if ( rst )
    begin
        shift1 <= 0;
        shift2 <= 0;
    end
    else
    begin
        shift1 <= { ps2d, shift1[10:1] };
        shift2 <= { shift1[0, shift2[10:1]] };         
    end
end
endmodule

仿真

module PS2_SIM();
reg         clk;
reg         rst;
reg         PS2D;
reg         PS2C;
wire [15:0] key;

PS2 U1(clk, rst, PS2D, PS2C, key);
initial begin
    clk        = 0;
    rst        = 1;
    PS2D       = 0;
    PS2C       = 0;
    #500;
    PS2D       = 0;
    rst        = 0;
    #1000;
    PS2D       = 1;
    #1000;
    PS2D       = 0;
    #1000;
    PS2D       = 1;
    #1000;
    PS2D       = 1;
    #1000;
    PS2D       = 0;
    #1000;
    PS2D       = 1;
    #1000;
    PS2D       = 1;
    #1000;
    PS2D       = 1;
    #1000;
    PS2D       = 0;
    #1000;
    PS2D       = 1;
end
always  #25 clk  = ~clk;        //system clock
always #500 PS2C = ~PS2C;       //device's clock
endmodule

在这里插入图片描述
根据波形我们可以看出,代码可以正常进行通信,实现PS/2通信协议功能。

总结

半年未见,自己曾经写过的几篇小文章竟受到不少人的喜爱,这是我所没有想到的。作为一个真心希望能够将自己的知识开源给大家的大学生,当看到自己复刻硬件的代码出乎意料的被人收藏之后,坚持下去的决心更加坚定。所以开出这一专栏,为资源的共享提供一份力量。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值