OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.23/] [fpga/] [src/] [kbd/] [keyboard.v] - Blame information for rev 185

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 116 hellwig
//
2
// keyboard.v -- PC keyboard receiver
3
//
4
 
5
 
6 27 hellwig
module keyboard(ps2_clk, ps2_data,
7
                clk, reset,
8
                keyboard_data, keyboard_rdy);
9
    input ps2_clk;
10
    input ps2_data;
11
    input clk;
12
    input reset;
13
    output [7:0] keyboard_data;
14
    output keyboard_rdy;
15
 
16
  reg ps2_clk_p;
17
  reg ps2_clk_s;
18
  reg ps2_data_p;
19
  reg ps2_data_s;
20
  wire [3:0] ps2_clk_int_x;
21
  reg [3:0] ps2_clk_int_r;
22
  reg ps2_clk_lvl;
23
  reg ps2_clk_lvl_prv;
24
  wire ps2_clk_fall;
25
  wire ps2_clk_rise;
26
  wire ps2_clk_edge;
27
  wire [9:0] data_x;
28
  reg [9:0] data_r;
29
  wire [12:0] timer_x;
30
  reg [12:0] timer_r;
31
  wire ps2_clk_quiet;
32
  wire [3:0] bitcnt_x;
33
  reg [3:0] bitcnt_r;
34
  wire rdy_x;
35
  reg rdy_r;
36
  wire err_x;
37
  reg err_r;
38
 
39
  // ps2 clock and data synchronizer
40
  always @(posedge clk) begin
41
    ps2_clk_p <= ps2_clk;
42
    ps2_clk_s <= ps2_clk_p;
43
    ps2_data_p <= ps2_data;
44
    ps2_data_s <= ps2_data_p;
45
  end
46
 
47
  // integrate ps2 clock
48
  assign ps2_clk_int_x =
49
    (ps2_clk_int_r == 4'b1111 && ps2_clk_s == 1) ? 4'b1111 :
50
    (ps2_clk_int_r == 4'b0000 && ps2_clk_s == 0) ? 4'b0000 :
51
    (ps2_clk_s == 1) ? ps2_clk_int_r + 1 :
52
    ps2_clk_int_r - 1;
53
 
54
  // clock level detector with hysteresis
55
  always @(posedge clk) begin
56
    if (reset == 1) begin
57
      ps2_clk_lvl_prv <= 1;
58
      ps2_clk_lvl <= 1;
59
    end else begin
60
      ps2_clk_lvl_prv <= ps2_clk_lvl;
61
      if (ps2_clk_int_r == 4'b0100) begin
62
        ps2_clk_lvl <= 0;
63
      end
64
      if (ps2_clk_int_r == 4'b1011) begin
65
        ps2_clk_lvl <= 1;
66
      end
67
    end
68
  end
69
 
70
  // find clock edges
71
  assign ps2_clk_fall = ps2_clk_lvl_prv & ~ps2_clk_lvl;
72
  assign ps2_clk_rise = ~ps2_clk_lvl_prv & ps2_clk_lvl;
73
  assign ps2_clk_edge = ps2_clk_fall | ps2_clk_rise;
74
 
75
  // shift ps2 data into a register
76
  assign data_x =
77
    (ps2_clk_fall == 1) ? { ps2_data_s, data_r[9:1]} : data_r;
78
 
79
  // clear timer if clock is pulsing, otherwise count
80
  assign timer_x =
81
    (ps2_clk_edge == 1) ? 13'b0000000000000 : timer_r + 1;
82
 
83
  // determine if clock has stopped at high level
84
  assign ps2_clk_quiet =
85
    (timer_r == 13'b1010000000000 && ps2_clk_lvl == 1) ? 1 : 0;
86
 
87
  // maintain bit counter
88
  assign bitcnt_x =
89
    (ps2_clk_fall == 1) ? bitcnt_r + 1 :
90
    (ps2_clk_quiet == 1 || err_r == 1) ? 4'b0000:
91
    bitcnt_r;
92
 
93
  // check if data ready
94
  assign rdy_x =
95
    (bitcnt_r == 4'b1011 && ps2_clk_quiet == 1) ? 1 : 0;
96
 
97
  // check for errors
98
  assign err_x =
99
    ((timer_r == 13'b1010000000000 &&
100
      ps2_clk_lvl == 0) ||
101
     (ps2_clk_quiet == 1 &&
102
      bitcnt_r != 4'b1011 &&
103
      bitcnt_r != 4'b0000)) ? 1 : err_r;
104
 
105
  // update state registers
106
  always @(posedge clk) begin
107
    if (reset == 1 || err_r == 1) begin
108
      ps2_clk_int_r <= 4'b1111;
109
      data_r <= 10'b0000000000;
110
      timer_r <= 13'b0000000000000;
111
      bitcnt_r <= 4'b0000;
112
      rdy_r <= 0;
113
      err_r <= 0;
114
    end else begin
115
      ps2_clk_int_r <= ps2_clk_int_x;
116
      data_r <= data_x;
117
      timer_r <= timer_x;
118
      bitcnt_r <= bitcnt_x;
119
      rdy_r <= rdy_x;
120
      err_r <= err_x;
121
    end
122
  end
123
 
124
  // assign outputs
125
  assign keyboard_data = data_r[7:0];
126
  assign keyboard_rdy = rdy_r;
127
 
128
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.