PS2解码
PS2键盘:明确接线关系,只需接4根线,VCC要+5V,刚刚又测试过,3.3V也可以用。时钟和数据线要用bidir双向口线,FPGA可以不用外接上拉电阻。另外,USB键盘也可以用,只要用一个转接头转成PS2即可。


键值查表

PS2键盘解码

其中detect.v模块
1 module detect
2 (
3 input clk,
4 input rst_n,
5 input ps2_clk_pin_in,
6 output H2L_sig
7 );
8
9 reg H2L_F1,H2L_F2;
10
11 always @ (posedge clk,negedge rst_n)
12 begin
13 if(!rst_n)
14 begin
15 H2L_F1 <= 1'b1;
16 H2L_F2 <= 1'b1;
17 end
18 else
19 begin
20 H2L_F1 <= ps2_clk_pin_in;
21 H2L_F2 <= H2L_F1;
22 end
23 end
24
25 assign H2L_sig = H2L_F2&(~H2L_F1);
26
27 endmodule
解码模块--ps2接受模块
1 module decode
2 (
3 input clk,
4 input rst_n,
5 input H2L_Sig,
6 input data_in,
7 output [7:0] ps2_data,
8 output ps2_done_sig
9 );
10
11 reg [7:0] rdata;
12 reg [4:0] i;
13 reg isshift;
14 reg isdone;
15
16 always @ (posedge clk,negedge rst_n)
17 begin
18 if(!rst_n)
19 begin
20 rdata <= 8'b0;
21 i <=5'b0;
22 isdone <= 1'b0;
23 end
24 else
25 case(i)
26 5'd0:
27 if(H2L_Sig)
28 i <= i+1'b1;
29 5'd1,5'd2,5'd3,5'd4,5'd5,5'd6,5'd7,5'd8:
30 if(H2L_Sig)
31 begin
32 i <= i+1'b1;
33 rdata[i-1] <= data_in;
34 end
35 5'd9,5'd10:
36 if(H2L_Sig)
37 i <= i +1'b1;
38 5'd11:
39 if(rdata==8'hF0)
40 i<=5'd12;
41 else
42 i<=5'd23;
43 5'd12,5'd13,5'd14,5'd15,5'd16,5'd17,5'd18,5'd19,5'd20,5'd21,5'd22:
44 if(H2L_Sig)
45 i <= i+1'b1;
46 5'd23:
47 begin
48 i<=i+1'b1;
49 isdone <= 1'b1;
50 end
51 5'd24:
52 begin
53 i<=5'd0;
54 isdone <= 1'b0;
55 end
56 endcase
57 end
58
59 assign ps2_data =rdata;
60 assign ps2_done_sig = isdone;
61
62 endmodule
控制模块--与FIFO的接口模块
1 module control
2 (
3 input clk,
4 input rst_n,
5 input done_sig,
6 input [7:0] ps2_data,
7 input full_sig,
8 output write_req,
9 output [7:0] fifo_write_data
10 );
11
12 reg [1:0] i;
13 reg isreq;
14
15 always @ (posedge clk,negedge rst_n)
16 if(!rst_n)
17 begin
18 i <= 2'b0;
19 isreq <= 1'b0;
20 end
21 else
22 case(i)
23 0:
24 if(done_sig && (!full_sig))
25 i <= i+1'b1;
26 1:
27 begin
28 isreq <= 1'b1;
29 i <= i+1'b1;
30 end
31 2:
32 begin
33 isreq <= 1'b0;
34 i <= 2'b0;
35 end
36 endcase
37
38 assign fifo_write_data =ps2_data;
39 assign write_req = isreq;
40
41 endmodule
FPGA Prototyping By Verilog Examples 中的PS2解码模块
//Listing 9.1
module ps2_rx
(
input wire clk, reset,
input wire ps2d, //ps2 data
input wire ps2c, //ps2 clk
input wire rx_en,
output reg rx_done_tick,
output wire [7:0] dout
);
// symbolic state declaration
localparam [1:0]
idle = 2'b00,
dps = 2'b01,
load = 2'b10;
// signal declaration
reg [1:0] state_reg, state_next;
reg [7:0] filter_reg;
wire [7:0] filter_next;
reg f_ps2c_reg;
wire f_ps2c_next;
reg [3:0] n_reg, n_next;
reg [10:0] b_reg, b_next;
wire fall_edge;
// body
//=================================================
// filter and falling-edge tick generation for ps2c
//=================================================
always @(posedge clk, posedge reset)
if (reset)
begin
filter_reg <= 0;
f_ps2c_reg <= 0;
end
else
begin
filter_reg <= filter_next;
f_ps2c_reg <= f_ps2c_next;
end
assign filter_next = {ps2c, filter_reg[7:1]};
assign f_ps2c_next = (filter_reg==8'b11111111) ? 1'b1 :
(filter_reg==8'b00000000) ? 1'b0 :
f_ps2c_reg;
assign fall_edge = f_ps2c_reg & ~f_ps2c_next;
//=================================================
// FSMD
//=================================================
// FSMD state & data registers
always @(posedge clk, posedge reset)
if (reset)
begin
state_reg <= idle;
n_reg <= 0;
b_reg <= 0;
end
else
begin
state_reg <= state_next;
n_reg <= n_next;
b_reg <= b_next;
end
// FSMD next-state logic
always @*
begin
state_next = state_reg;
rx_done_tick = 1'b0;
n_next = n_reg;
b_next = b_reg;
case (state_reg)
idle:
if (fall_edge & rx_en)
begin
// shift in start bit
b_next = {ps2d, b_reg[10:1]};
n_next = 4'b1001;
state_next = dps;
end
dps: // 8 data + 1 parity + 1 stop
if (fall_edge)
begin
b_next = {ps2d, b_reg[10:1]};
if (n_reg==0)
state_next = load;
else
n_next = n_reg - 1;
end
load: // 1 extra clock to complete the last shift
begin
state_next = idle;
rx_done_tick = 1'b1;
end
endcase
end
// output
assign dout = b_reg[8:1]; // data bits
endmodule
路漫漫其修远兮,吾将上下而求索
浙公网安备 33010602011771号