OpenCores
URL https://opencores.org/ocsvn/a-z80/a-z80/trunk

Subversion Repositories a-z80

[/] [a-z80/] [trunk/] [host/] [zxspectrum_de1/] [ula/] [ps2_kbd.sv] - Blame information for rev 8

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

Line No. Rev Author Line
1 8 gdevic
//============================================================================
2
// Implementation of the PS/2 keyboard scan-code reader
3
//
4
//  Copyright (C) 2014-2016  Goran Devic
5
//
6
//  This program is free software; you can redistribute it and/or modify it
7
//  under the terms of the GNU General Public License as published by the Free
8
//  Software Foundation; either version 2 of the License, or (at your option)
9
//  any later version.
10
//
11
//  This program is distributed in the hope that it will be useful, but WITHOUT
12
//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
//  more details.
15
//
16
//  You should have received a copy of the GNU General Public License along
17
//  with this program; if not, write to the Free Software Foundation, Inc.,
18
//  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
//============================================================================
20
module ps2_keyboard
21
(
22
    input wire clk,
23
    input wire reset,           // Reset (negative logic)
24
    input wire PS2_CLK,         // PS/2 keyboard clock line
25
    input wire PS2_DAT,         // PS/2 keyboard data line
26
 
27
    output wire [7:0] scan_code,// Completed keyboard scan code
28
    output reg scan_code_ready, // Active for 1 clock: scan code is ready
29
    output reg scan_code_error  // Error receiving keyboard data
30
);
31
 
32
reg [7:0] clk_filter;
33
reg ps2_clk_in;
34
 
35
reg clk_edge;
36
reg [3:0] bit_count;
37
 
38
// Shift register contains all the bits that are read so far; scan_code simply
39
// mirrors it and becomes valid only when "scan_code_ready" is set
40
reg [8:0] shiftreg;
41
assign scan_code = shiftreg[7:0];
42
 
43
// Compute parity on the fly; we only need it after the last bit is stored
44
wire parity;
45
assign parity = ^shiftreg[8:0];
46
 
47
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48
// Filter the PS/2 clock signal since it might have a noise (false '1')
49
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50
always @(posedge clk or negedge reset)
51
begin
52
    if (!reset) begin
53
        ps2_clk_in <= 1;
54
        clk_filter <= 8'b1;
55
        clk_edge <= 0;
56
        end
57
    else begin
58
        // Filter in a new keyboard clock sample
59
        clk_filter <= { PS2_CLK, clk_filter[7:1] };
60
        clk_edge <= 0;
61
 
62
        if (clk_filter==8'b1)
63
            ps2_clk_in <= 1;
64
        else if (clk_filter==8'b0) begin
65
            // Filter clock is low, check for edge
66
            if (ps2_clk_in==1)
67
                clk_edge <= 1;
68
            ps2_clk_in <= 0;
69
        end
70
    end
71
end
72
 
73
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74
// State machine to process bits of PS/2 data
75
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76
always @(posedge clk or negedge reset)
77
begin
78
    if (!reset) begin
79
        bit_count <= '0;
80
        shiftreg <= '0;
81
        scan_code_ready <= 0;
82
        scan_code_error <= 0;
83
        end
84
    else begin
85
        scan_code_ready <= 0;
86
        scan_code_error <= 0;
87
        // We have a new valid clocked bit from the keyboard
88
        if (clk_edge==1) begin
89
            // Start condition, the bit count is 0
90
            if (bit_count==0 && PS2_DAT==0)
91
                    bit_count <= bit_count + 4'h1;
92
            else begin
93
                // Collecting up to 8 data bits and a parity bit
94
                if (bit_count < 10) begin
95
                    bit_count <= bit_count + 4'h1;
96
                    shiftreg <= { PS2_DAT, shiftreg[8:1] };
97
                    end
98
                else
99
                // Finalize: both the calculated parity and the stop bits should be '1'
100
                begin
101
                    bit_count <= '0;
102
                    scan_code_ready <= { PS2_DAT, parity} == 2'b11;
103
                    scan_code_error <= { PS2_DAT, parity} != 2'b11;
104
                end
105
            end
106
        end
107
    end
108
end
109
 
110
endmodule

powered by: WebSVN 2.1.0

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