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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [fpga/] [mc/] [src/] [kbd/] [keyboard.v] - Blame information for rev 290

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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