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

第五波浪潮来袭,如何把人工智能放进每个终端?
变频无线发射机系统电路设计详解 —电路图天天读(188)
Synaptics拓展语音生态系统,支持微软Cortana集成
TMC2160大功率步进电机驱动板-CAN总线
如何处理中性点接地电阻柜漏电现象
PS2键盘编码Verilog源程序分享
科学家成功开发出自旋转移矩-磁性随机存储器
FANUC系统的数控机床过热故障如何检修
北斗+人工智能,打造极致出行体验
示波器实现高速全方位分析
消息称苹果iPad发售时间推迟到3月26日
LoRa模块的应用场景
200元以内口碑爆棚的网红电动牙刷,性价比高体验好
称重传感器安装过程中的需要留心哪些问题
电源端口串联2个电容的作用?
租赁HP6632A/HP6634A/HP6552A/HP66
PLC中模拟量信号的处理方法
郭朝晖分享报告《人工智能与智能制造》PPT全文分享
AVM环视系统在自标定中的应用及原理分析
便携式无线墒情综合监测仪是什么,它都有哪些作用