PS2解码

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

PS2解码_第1张图片

PS2解码_第2张图片

键值查表

PS2解码_第3张图片

PS2键盘解码

PS2解码_第4张图片

其中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

你可能感兴趣的:(PS)