FPGA 实现PS/2键盘控制LED

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chief_cf/article/details/53141860

今天发现开发板上有PS/2接口,所以就打算试试是不是好的。
在这里简单说一下PS/2的基本知识,增加了解。PS/2
如图即为PS/2接口的公头,是一种6针的接口。包括数据(1脚)、时钟(5脚)、电源(+5V)(4脚)、地(3脚),以及预留了2个针脚。
它名字的来历是最早出现在IBM的PS/2的机子上,故之。它是一种鼠标和键盘的专用接口,输速率比COM接口稍快一些,而且是ATX主板的标准接口,是目前应用最为广泛的键盘接口之一。
键盘和鼠标都可以使用PS/2接口,但是按照PC’99颜色规范,鼠标通常占用浅绿色接口,键盘占用紫色接口。尽管键盘鼠标对于的ps/2针脚一样,但是这两个接口还是不能混插,这是由它们在电脑内部不同的信号定义所决定的。
接下来说说键盘编码,普通计算机都是采用编码键盘,编码方式分为第一套、第二套、第三套编码,民用都是第二套。具体编码细则可以自行百度。在这里我用到了Z键、Y键和Ctrl键,他们对于的编码分别是0x1A、0x35、0x14。
然后是PS/2的时序,具体如下:起始位、数据0、数据1、数据2、数据3。。。。数据7、校验位、停止位。(这和串口很相似),在PS/2时钟下降沿采集数据。
接下来直接上代码

module ps2
(
/*系统信号*******/
input clk,
input rst_n,
/**ps2信号************/
input data_in,
input clk_in,
/*测试信号*******/
output reg done_flag,
output reg[3:0] led
);

/************************/
reg r1,r2;
reg[7:0] ps2_data;
reg[4:0] i;//状态
wire ps2_clk_n;
/************************/
//clk_in下降沿检测
/*************************/
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
r1 <= 1’b0;
r2 <= 1’b0;
end
else
begin
r1 <= clk_in;
r2 <= r1;
end
end

assign ps2_clk_n = r2&(!r1);
/***************************/
//获取ps2键值
/***************************/
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
i<= ‘d0;
done_flag <= 1’b0;
ps2_data <= 8’b0;
end
else case(i)
‘d0:
begin
if(ps2_clk_n)
i <= i + 1’b1;
else i <= i;
end
‘d1,’d2,’d3,’d4,’d5,’d6,’d7,’d8:
begin
if(ps2_clk_n)
begin
i <= i + 1’b1;
ps2_data[i-1] <= data_in;
end
else i <= i;
end
‘d9,’d10:
begin
if(ps2_clk_n)
i <= i + 1’b1;
else
i <= i;
end
‘d11://判断通断码,为F0则是断码
begin
if(ps2_data==8’hF0)
i <= ‘d12;
else
i <= ‘d23;
end
‘d12,’d13,’d14,’d15,’d16,’d17,’d18,’d19,’d20,’d21,’d22:
begin
if(ps2_clk_n)
i <= i + 1’b1;
else
i <= i;
end
‘d23:
begin
i <= i + 1’b1;
done_flag <= 1’b1;
end
‘d24:
begin
i <= ‘d0;
done_flag <= 1’b0;
end
default:i <= ‘d0;
endcase

end 

/*****************************/
//输出控制led,Z键左移;Y键右移;CTRL切换
/****************************/
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
led <= 4’b1110;
else if(done_flag)
case(ps2_data)
8’h1a://字母z
begin
led <= {led[2:0],led[3]};//左移
end
8’h35://字母y
begin
led <= {led[0],led[3:1]};//右移
end
8’h14:
begin
led <= {led[0],led[1],led[2],led[3]};
end
default:;
endcase
end

endmodule
首先进行PS/2时钟下降沿检测,然后接受键盘过来的键值(即按键的编码,比如Z键接收到的就是0x1A),通过对按键编码的判断来控制LED的左右移动和切换。
这是最简单的PS/2操作,如果要做更复杂处理,同样可以按照这个思路扩展,以支持不同操作。

展开阅读全文

没有更多推荐了,返回首页