原创 verilog的PS2键盘解码

2008-8-30 18:54 8921 13 28 分类: FPGA/CPLD

verilogPS2键盘解码<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


 


    之前日志里深入探讨过PS/2键盘编解码以及数据传输协议,这次自己动手实现了利用FPGA接收键盘编码,然后通过串口传输到PC。做的比较简单,只是通过FPGA把大写字母A-Z转换成相应的ASCII码,只要字母按键被按下,就能在串口调试助手里显示相应大写字母。下面就共享代码吧!


    除了顶层模块,三个底层模块分别为PS/2传输处理模块、串口传输模块以及串口波特率选择模块(下面只给出顶层模块和PS/2传输处理模块的verilog代码,串口部分的可以参考上一篇日志http://blog.ednchina.com/ilove314/153551/Message.aspx)。


 


module ps2_key(clk,rst_n,ps2k_clk,ps2k_data,rs232_tx);


 


input clk; //50M时钟信号


input rst_n;  //复位信号


input ps2k_clk;   //PS2接口时钟信号


input ps2k_data;  //PS2接口数据信号


output rs232_tx;  // RS232发送数据信号


 


 


wire[7:0] ps2_byte;  // 1byte键值


wire ps2_state;      //按键状态标志位


 


wire bps_start;   //接收到数据后,波特率时钟启动信号置位


wire clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点


 


ps2scan           ps2scan(   .clk(clk),            //按键扫描模块


                            .rst_n(rst_n),             


                            .ps2k_clk(ps2k_clk),


                            .ps2k_data(ps2k_data),


                             .ps2_byte(ps2_byte),


                            .ps2_state(ps2_state)


                            );


 


speed_select  speed_select( .clk(clk),


                                   .rst_n(rst_n),


                                   .bps_start(bps_start),


                                   .clk_bps(clk_bps)


                                   );


 


my_uart_tx    my_uart_tx(       .clk(clk),


                                   .rst_n(rst_n),


                                   .clk_bps(clk_bps),


                                   .rx_data(ps2_byte),


                                   .rx_int(ps2_state),


                                   .rs232_tx(rs232_tx),


                                   .bps_start(bps_start)


                                   );


 


Endmodule


 


 


module ps2scan(clk,rst_n,ps2k_clk,ps2k_data,ps2_byte,ps2_state);


 


input clk; //50M时钟信号


input rst_n;  //复位信号


input ps2k_clk;   //PS2接口时钟信号


input ps2k_data;  //PS2接口数据信号


output[7:0] ps2_byte;    // 1byte键值,只做简单的按键扫描


output ps2_state;    //键盘当前状态,ps2_state=1表示有键被按下


 


//------------------------------------------


reg ps2k_clk_r0,ps2k_clk_r1,ps2k_clk_r2;  //ps2k_clk状态寄存器


 


//wire pos_ps2k_clk;     // ps2k_clk上升沿标志位


wire neg_ps2k_clk;   // ps2k_clk下降沿标志位


 


always @ (posedge clk or negedge rst_n) begin


    if(!rst_n) begin


           ps2k_clk_r0 <= 1'b0;


           ps2k_clk_r1 <= 1'b0;


           ps2k_clk_r2 <= 1'b0;


       end


    else begin                         //锁存状态,进行滤波


           ps2k_clk_r0 <= ps2k_clk;


           ps2k_clk_r1 <= ps2k_clk_r0;


           ps2k_clk_r2 <= ps2k_clk_r1;


       end


end


 


assign neg_ps2k_clk = ~ps2k_clk_r1 & ps2k_clk_r2;    //下降沿


 


//------------------------------------------


reg[7:0] ps2_byte_r;     //PC接收来自PS2的一个字节数据存储器


reg[7:0] temp_data;  //当前接收数据寄存器


reg[3:0] num; //计数寄存器


 


always @ (posedge clk or negedge rst_n) begin


    if(!rst_n) begin


           num <= 4'd0;


           temp_data <= 8'd0;


       end


    else if(neg_ps2k_clk) begin //检测到ps2k_clk的下降沿


           case (num)


              4'd0:  num <= num+1'b1;


              4'd1:  begin


                         num <= num+1'b1;


                         temp_data[0] <= ps2k_data;  //bit0


                     end


              4'd2:  begin


                         num <= num+1'b1;


                         temp_data[1] <= ps2k_data;  //bit1


                     end


              4'd3:  begin


                         num <= num+1'b1;


                         temp_data[2] <= ps2k_data;  //bit2


                     end


              4'd4:  begin


                         num <= num+1'b1;


                         temp_data[3] <= ps2k_data;  //bit3


                     end


              4'd5:  begin


                         num <= num+1'b1;


                         temp_data[4] <= ps2k_data;  //bit4


                     end


              4'd6:  begin


                         num <= num+1'b1;


                         temp_data[5] <= ps2k_data;  //bit5


                     end


              4'd7:  begin


                         num <= num+1'b1;


                         temp_data[6] <= ps2k_data;  //bit6


                     end


              4'd8:  begin


                         num <= num+1'b1;


                         temp_data[7] <= ps2k_data;  //bit7


                     end


              4'd9:  begin


                         num <= num+1'b1;  //奇偶校验位,不做处理


                     end


              4'd10: begin


                         num <= 4'd0;  // num清零


                     end


              default: ;


              endcase


       end


end


 


reg key_f0;       //松键标志位,置1表示接收到数据8'hf0,再接收到下一个数据后清零


reg ps2_state_r;  //键盘当前状态,ps2_state_r=1表示有键被按下


 


always @ (posedge clk or negedge rst_n) begin //接收数据的相应处理,这里只对1byte的键值进行处理


    if(!rst_n) begin


           key_f0 <= 1'b0;


           ps2_state_r <= 1'b0;


       end


    else if(num==4'd10) begin   //刚传送完一个字节数据


           if(temp_data == 8'hf0) key_f0 <= 1'b1;


           else begin


                  if(!key_f0) begin //说明有键按下


                         ps2_state_r <= 1'b1;


                         ps2_byte_r <= temp_data; //锁存当前键值


                     end


                  else begin


                         ps2_state_r <= 1'b0;


                         key_f0 <= 1'b0;


                     end


              end


       end


end


 


reg[7:0] ps2_asci;   //接收数据的相应ASCII


 


always @ (ps2_byte_r) begin


    case (ps2_byte_r)    //键值转换为ASCII码,这里做的比较简单,只处理字母


       8'h15: ps2_asci <= 8'h51;   //Q


       8'h1d: ps2_asci <= 8'h57;   //W


       8'h24: ps2_asci <= 8'h45;   //E


       8'h2d: ps2_asci <= 8'h52;   //R


       8'h2c: ps2_asci <= 8'h54;   //T


       8'h35: ps2_asci <= 8'h59;   //Y


       8'h3c: ps2_asci <= 8'h55;   //U


       8'h43: ps2_asci <= 8'h49;   //I


       8'h44: ps2_asci <= 8'h4f;   //O


       8'h4d: ps2_asci <= 8'h50;   //P              


       8'h1c: ps2_asci <= 8'h41;   //A


       8'h1b: ps2_asci <= 8'h53;   //S


       8'h23: ps2_asci <= 8'h44;   //D


       8'h2b: ps2_asci <= 8'h46;   //F


       8'h34: ps2_asci <= 8'h47;   //G


       8'h33: ps2_asci <= 8'h48;   //H


       8'h3b: ps2_asci <= 8'h4a;   //J


       8'h42: ps2_asci <= 8'h4b;   //K


       8'h4b: ps2_asci <= 8'h4c;   //L


       8'h1z: ps2_asci <= 8'h5a;   //Z


       8'h22: ps2_asci <= 8'h58;   //X


       8'h21: ps2_asci <= 8'h43;   //C


       8'h2a: ps2_asci <= 8'h56;   //V


       8'h32: ps2_asci <= 8'h42;   //B


       8'h31: ps2_asci <= 8'h4e;   //N


       8'h3a: ps2_asci <= 8'h4d;   //M


       default: ;


       endcase


end


 


assign ps2_byte = ps2_asci;


assign ps2_state = ps2_state_r;


 


endmodule


 


PARTNER CONTENT

文章评论15条评论)

登录后参与讨论

用户1646504 2013-12-7 22:39

从代码上看,的确应该是按下就发送,但是请问为什么释放了才发送到串口呢?

用户1646504 2013-12-7 22:38

我也在思考这个问题

用户573832 2013-3-31 16:45

从代码上看,的确应该是按下就发送,但是请问为什么释放了才发送到串口呢?

用户573832 2013-3-31 16:43

为什么按住的时候不显示字符,放开才显示?

用户379532 2012-3-12 15:55

为什么按住的时候不显示字符,放开才显示?

用户377235 2011-12-2 15:22

8'h1z: ps2_asci <= 8'h5a; //Z 这句话有点看不明白,为什么是8'h1z呢?

是Z的键码:8'h1a 么?

ilove314_323192455 2010-11-9 22:15

也许年底吧,也许年初吧,我只能尽力先奉上教程了

用户591598 2010-11-9 20:26

特权同学,SF-NIOS2 学习板什么时候问世啊?期待中。。。

ilove314_323192455 2008-11-17 22:40

clk是主时钟,50M,所以做分频时钟ps2k_clk,确切的说不能叫分频,只是做一个计数器使能信号来触发得到需要的ps2k_clk,具体你可以参考我的代码

用户157954 2008-11-16 21:57

请问你的两个时钟clk和ps2k_clk时序是怎么配合的
相关推荐阅读
特权ilove314 2016-06-30 21:16
例说FPGA连载6:FPGA开发所需的技能
例说FPGA连载6:FPGA开发所需的技能 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   前面的文字已经做了很多铺垫,相信读...
特权ilove314 2016-06-28 21:09
例说FPGA连载5:FPGA的优势与局限性
例说FPGA连载5:FPGA的优势与局限性 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   若要准确评估FPGA技术能否满足开...
特权ilove314 2016-06-28 21:05
例说FPGA连载5:FPGA的优势与局限性
例说FPGA连载5:FPGA的优势与局限性 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   若要准确评估FPGA技术能否满足开...
特权ilove314 2016-06-26 22:11
例说FPGA连载4:FPGA语言与厂商介绍
例说FPGA连载4:FPGA语言与厂商介绍 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   Verilog与VHDL 说到FP...
特权ilove314 2016-06-23 21:26
例说FPGA连载3:FPGA与其它主流芯片的比较
例说FPGA连载3:FPGA与其它主流芯片的比较 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   FPGA、ASIC和ASSP...
特权ilove314 2016-06-21 20:32
例说FPGA连载2:FPGA是什么
例说FPGA连载2:FPGA是什么 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   2015年伊始,Intel欲出资百亿美金收...
EE直播间
更多
我要评论
15
13
关闭 站长推荐上一条 /3 下一条