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

posted on 2010-12-24 15:50  齐威王  阅读(1596)  评论(1编辑  收藏  举报

导航