欢迎来到EDA中国!
当前位置:网站首页 >技术专栏 > FPGA

PS2键盘编码Verilog源程序

发布时间: 2013-07-06 18:07:34     来源: EDA中国

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

 除了顶层模块,三个底层模块分别为PS/2传输处理模块、串口传输模块以及串口波特率选择模块(下面只给出顶层模块和PS/2传输处理模块的Verilog代码)。

 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: ;

获取帮助