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
路漫漫其修远兮,吾将上下而求索