[FPGA入门笔记](十二):PS/2同步串口控制

简介

今天购买了AXLINX AX7020的开发板,从今天开始每一个例程都要做文档记录,为自己加油。
本实验,基于ALINX AX7020开发板,芯片为xc7z020clg400-2。开发板输入时钟为50MHz。
参考文档:verilog语言的ps2键盘驱动设计
PS2键盘控制及短按、长按

概述

PS2键盘也是一个经典的实验,可能很多人接触如何对通信协议、时序编程就是从这个实验开始学习的。USB键盘已经很普及,现在市场上还是有一些USB转PS2的转接头,还有一些转换芯片。这个实验虽然简单,不过不知道您有考虑过单按一次输出一个有效脉冲、短按、长按等这些是如何实现的么?这就涉及到一些时钟、边沿检测等设计问题。
PS2协议实现
我们见到的PS2的接口电路应该都是这样的:
在这里插入图片描述
主要内容:常见的PS/2端口有两类:一种5脚的DIN或6脚的mini-DIN,这两种连接器在电气特性上是十分类似的,两者只有一点不同那就是管脚的排列,具有6 脚mini-DIN 的键盘通常被叫做PS/2 键盘,而那些有5 脚DIN 叫做 AT 设备。常见ps2键盘接口如下所示:
在这里插入图片描述
由于电源和地都是主机接口提供,主要用于驱动设计的管脚只有两个,data和clock,该clock时钟是键盘产生的,最大的时钟频率是33kHz 而且大多数设备工作在10 20kHz。
PS/2 鼠标和键盘履行一种双向同步串行协议, 换句话说每次数据线上发送一位数据并且每在时钟线上发一个脉冲就被读入,键盘/ 鼠标可以发送数据到主机,而主机也可以发送数据到设备。
从键盘/ 鼠标发送到主机的数据在时钟信号的下降沿, 当时钟从高变到低的时候 被读取 。
从主机发送到键盘/鼠标的数据在上升沿,当时钟从低变到高的时候被读取。
不管通讯的方向怎样键盘/鼠标总是产生时钟信号该同步串行协议的帧结构如下:(从键盘到主机的帧长度为11bit)
在这里插入图片描述
一根时钟线、一根数据线完成通信,PS2通信的帧格式如下所示,时钟的下降沿数据有效:
在这里插入图片描述
按键在被按下时,会发送一个字节,这个码就是通码;按键在释放时,会发送两个字节,这个码就做断码(当然也有例外)。每一个按键都有唯一的通码和断码,据此进行判断按下的是哪个键,从而执行对应的功能。

代码:

module ps2_control(
    //input
    input          sys_clk, //50Mhz
    input          rst_n,
    input          key_clk, //键盘时钟
    input          key_data,//键盘数据
    //output
    output  [7:0]  data_buf //保存要显示的数据
    );
    
    wire    key_clk_n;
    reg     key_clk_1;
    reg     key_clk_2;
    //***********************************************
    //检测key_clk的下降沿
    //***********************************************
    always @(posedge sys_clk or negedge rst_n)
    if(!rst_n) begin
        key_clk_1 <= 1'b1;
        key_clk_2 <= 1'b1;
    end
    else begin
        key_clk_1 <= key_clk;
        key_clk_2 <= key_clk_1;
    end

    assign key_clk_n = key_clk_2 & (~key_clk_1);
    //***********************************************
    //对key_data上的数据进行保存
    //***********************************************
    reg [3:0] i;
    reg [7:0] data_temp;
    
    always @(posedge sys_clk or negedge rst_n)
    if(!rst_n) 
        begin
        i <= 4'd0;
        data_temp <= 8'h00;
        end
    else if(key_clk_n) 
    begin
        case(i)
        4'd0: i <= i + 1'b1;  //起始位不处理

        4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8:
        begin
            i <= i + 1'b1;
            data_temp[i-1] <= key_data;
        end

        4'd9: i <= i + 1'b1;  //奇校验位不处理

        4'd10:i <= 4'd0;      //停止位不处理

        default:    ;
        endcase
    end

    reg         key_f0;        //松键标志位,置1表示接收到数据8'hf0,再接收到下一个数据后清零
    reg [7:0]   ps2_data;
    
    always @(posedge sys_clk or negedge rst_n)    //接收数据的相应处理,这里只对1byte的键值进行处理
    if(!rst_n) 
        begin
            key_f0 <= 1'b0;
            ps2_data <= 8'h00;
        end
    else if(i==4'd10) //刚传送完一个字节数据
        begin
            if(data_temp == 8'hf0)
                key_f0 <= 1'b1;  //说明有键被释放
            else if(!key_f0)     //说明有键按下
                ps2_data <= data_temp;    //锁存当前键值
            else
                key_f0 <= 1'b0;
        end

    always @ (ps2_data) 
    begin
        case (ps2_data)
            8'h15: data_buf = "Q";
            8'h1d: data_buf = "W";
            8'h24: data_buf = "E";
            8'h2d: data_buf = "R";
            8'h2c: data_buf = "T";
            8'h35: data_buf = "Y";
            8'h3c: data_buf = "U";
            8'h43: data_buf = "I";
            8'h44: data_buf = "O";
            8'h4d: data_buf = "P";
            8'h1c: data_buf = "A";
            8'h1b: data_buf = "S";
            8'h23: data_buf = "D";
            8'h2b: data_buf = "F";
            8'h34: data_buf = "G";
            8'h33: data_buf = "H";
            8'h3b: data_buf = "J";
            8'h42: data_buf = "K";
            8'h4b: data_buf = "L";
            8'h1a: data_buf = "Z";
            8'h22: data_buf = "X";
            8'h21: data_buf = "C";
            8'h2a: data_buf = "V";
            8'h32: data_buf = "B";
            8'h31: data_buf = "N";
            8'h3a: data_buf = "M";
            default: data_buf = 8'h00;
        endcase
    end

endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值