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

Subversion Repositories next186_soc_pc

[/] [next186_soc_pc/] [trunk/] [HW/] [KB_8042.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next186 Soc PC project
4
// http://opencores.org/project,next186
5
//
6
// Filename: KB_8042.v
7
// Description: Part of the Next186 SoC PC project, keyboard/mouse PS2 controller
8
//              Simplified 8042 implementation
9
// Version 1.0
10
// Creation date: Jan2013
11
//
12
// Author: Nicolae Dumitrache 
13
// e-mail: ndumitrache@opencores.org
14
//
15
/////////////////////////////////////////////////////////////////////////////////
16
// 
17
// Copyright (C) 2013 Nicolae Dumitrache
18
// 
19
// This source file may be used and distributed without 
20
// restriction provided that this copyright statement is not 
21
// removed from the file and that any derivative work contains 
22
// the original copyright notice and the associated disclaimer.
23
// 
24
// This source file is free software; you can redistribute it 
25
// and/or modify it under the terms of the GNU Lesser General 
26
// Public License as published by the Free Software Foundation;
27
// either version 2.1 of the License, or (at your option) any 
28
// later version. 
29
// 
30
// This source is distributed in the hope that it will be 
31
// useful, but WITHOUT ANY WARRANTY; without even the implied 
32
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
33
// PURPOSE. See the GNU Lesser General Public License for more 
34
// details. 
35
// 
36
// You should have received a copy of the GNU Lesser General 
37
// Public License along with this source; if not, download it 
38
// from http://www.opencores.org/lgpl.shtml 
39
// 
40
///////////////////////////////////////////////////////////////////////////////////
41
// Additional Comments: 
42
//
43
// http://www.computer-engineering.org/ps2keyboard/
44
// http://wiki.osdev.org/%228042%22_PS/2_Controller
45
// http://wiki.osdev.org/Mouse_Input
46
//
47
//      Primary connection
48
//              NET "PS2_CLK1" LOC = "W12" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
49
//              NET "PS2_DATA1" LOC = "V11" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
50
//      Secondary connection (requires Y-splitter cable)
51
//              NET "PS2_CLK2" LOC = "U11" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
52
//              NET "PS2_DATA2" LOC = "Y12" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
53
//////////////////////////////////////////////////////////////////////////////////
54
`timescale 1ns / 1ps
55
 
56
module KB_Mouse_8042(
57
    input CS,
58
         input WR,
59
    input cmd,                  // 0x60 = data, 0x64 = cmd
60
         input [7:0]din,
61
         output OE,
62
         output [7:0]dout,
63
         input clk,                     // cpu CLK
64
         output I_KB,           // interrupt keyboard
65
         output I_MOUSE,  // interrupt mouse
66
         output reg CPU_RST = 0,
67
         inout PS2_CLK1,
68
         inout PS2_CLK2,
69
         inout PS2_DATA1,
70
         inout PS2_DATA2
71
    );
72
 
73
//      status bit5 = MOBF (mouse to host buffer full - with OBF), bit4=INH, bit2(1-initialized ok), bit1(IBF-input buffer full - host to kb/mouse), bit0(OBF-output buffer full - kb/mouse to host)
74
        reg [3:0]cmdbyte = 4'b1100; // EN2,EN,INT2,INT
75
        reg wcfg = 0;    // write config byte
76
        reg next_mouse = 0;
77
        reg ctl_outb = 0;
78
        reg [9:0]wr_data;
79
        reg [14:0]cnt100us = 0; // single delay counter for both kb and mouse
80
        reg wr_mouse = 0;
81
        reg wr_kb = 0;
82
        reg rd_kb = 0;
83
        reg rd_mouse = 0;
84
        reg OBF = 0;
85
        reg MOBF = 0;
86
 
87
        wire [7:0]kb_data;
88
        wire [7:0]mouse_data;
89
        wire kb_data_out_ready;
90
        wire kb_data_in_ready;
91
        wire mouse_data_out_ready;
92
        wire mouse_data_in_ready;
93
        wire IBF = ((wr_kb | ~kb_data_in_ready) & ~cmdbyte[2]) | ((wr_mouse  | ~mouse_data_in_ready) & ~cmdbyte[3]);
94
        wire [7:0]inb = ctl_outb ? {2'b00, cmdbyte[3:2], 2'b00, cmdbyte[1:0]} : MOBF ? mouse_data : kb_data;
95
        wire kb_shift;
96
        wire mouse_shift;
97
 
98
        assign OE = CS & ~WR;
99
        assign dout = cmd ? {2'b00, MOBF, 1'b1, wcfg, 1'b1, IBF, OBF | MOBF | ctl_outb} : inb;
100
        assign I_KB = cmdbyte[0] & OBF;                  // INT & OBF
101
        assign I_MOUSE = cmdbyte[1] & MOBF;     // INT2 & MOBF
102
 
103
        PS2Interface Keyboard
104
        (
105
                .PS2_CLK(PS2_CLK1),
106
                .PS2_DATA(PS2_DATA1),
107
                .clk(clk),
108
                .rd(rd_kb),
109
                .wr(wr_kb),
110
                .data_in(wr_data[0]),
111
                .data_out(kb_data),
112
                .data_out_ready(kb_data_out_ready),
113
                .data_in_ready(kb_data_in_ready),
114
                .delay100us(cnt100us[14]),
115
                .data_shift(kb_shift)
116
        );
117
 
118
        PS2Interface Mouse
119
        (
120
                .PS2_CLK(PS2_CLK2),
121
                .PS2_DATA(PS2_DATA2),
122
                .clk(clk),
123
                .rd(rd_mouse),
124
                .wr(wr_mouse),
125
                .data_in(wr_data[0]),
126
                .data_out(mouse_data),
127
                .data_out_ready(mouse_data_out_ready),
128
                .data_in_ready(mouse_data_in_ready),
129
                .delay100us(cnt100us[14]),
130
                .data_shift(mouse_shift)
131
        );
132
 
133
        always @(posedge clk) begin
134
                CPU_RST <= 0;
135
                if(~kb_data_in_ready) wr_kb <= 0;
136
                if(~kb_data_out_ready) rd_kb <= 1'b0;
137
                if(~mouse_data_in_ready) wr_mouse <= 0;
138
                if(~mouse_data_out_ready) rd_mouse <= 1'b0;
139
 
140
                if(CS & WR & ~cmd & ~wcfg) cnt100us <= 0; // reset 100us counter for PS2 writing
141
                else if(!cnt100us[14]) cnt100us <= cnt100us + 1;
142
 
143
                if(~OBF & ~MOBF)
144
                        if(kb_data_out_ready & ~rd_kb & ~cmdbyte[2]) OBF <= 1'b1;
145
                        else MOBF <= mouse_data_out_ready & ~rd_mouse & ~cmdbyte[3];
146
 
147
                if(kb_shift | mouse_shift) wr_data <= {1'b1, wr_data[9:1]};
148
 
149
                if(CS)
150
                        if(WR)
151
                                if(cmd) // 0x64 write
152
                                        case(din)
153
                                                8'h20: ctl_outb <= 1;   // read config byte
154
                                                8'h60: wcfg <= 1;                       // write config byte
155
                                                8'ha7: cmdbyte[3] <= 1; // disable mouse
156
                                                8'ha8: cmdbyte[3] <= 0;  // enable mouse
157
                                                8'had: cmdbyte[2] <= 1; // disable kb
158
                                                8'hae: cmdbyte[2] <= 0;  // enable kb
159
                                                8'hd4: next_mouse <= 1; //      write next byte to mouse
160
                                                /*8'hf0, 8'hf2, 8'hf4, 8'hf6, 8'hf8, 8'hfa, 8'hfc,*/ 8'hfe: CPU_RST <= 1; // CPU reset
161
                                        endcase
162
                                else begin      // 0x60 write
163
                                        if(wcfg) cmdbyte <= {din[5:4], din[1:0]};
164
                                        else begin
165
                                                next_mouse <= 0;
166
                                                wr_mouse <= next_mouse;
167
                                                wr_kb <= ~next_mouse;
168
                                                wr_data <= {~^din, din, 1'b0};
169
//                                              cnt100us <= 0;  // reset 100us counter for PS2 writing
170
                                        end
171
                                        wcfg <= 0;
172
                                end
173
                        else    // read data
174
                                if(~cmd) begin
175
                                        ctl_outb <= 1'b0;
176
                                        if(!ctl_outb) begin
177
                                                OBF <= 1'b0;
178
                                                MOBF <= 1'b0;
179
                                                rd_kb <= OBF;
180
                                                rd_mouse <= MOBF;
181
                                        end
182
                                end
183
        end
184
endmodule
185
 
186
 
187
module PS2Interface(
188
         inout PS2_CLK,
189
         inout PS2_DATA,
190
         input clk,
191
         input rd,                              // enable PS2 data reading
192
         input wr,                              // can write data from controller to PS2
193
         input data_in,         // data from controller
194
         input delay100us,
195
         output [7:0]data_out,   // data from PS2
196
         output reg data_out_ready = 1, // PS2 received data ready
197
         output reg data_in_ready = 1,  // PS2 sent data ready
198
         output data_shift
199
        );
200
        reg [1:0]s_clk = 2'b11;
201
        reg [9:0]data = 0;
202
        reg rd_progress = 0;
203
 
204
        assign PS2_CLK = ((~data_out_ready & data_in_ready) | (~data_in_ready & delay100us)) ? 1'bz : 1'b0;
205
        assign PS2_DATA = (data_in_ready | data_in | ~delay100us) ? 1'bz : 1'b0;
206
        assign data_out = data[7:0];
207
        assign data_shift = ~data_in_ready && delay100us && s_clk == 2'b10;
208
 
209
        always @(posedge clk) begin
210
                s_clk <= {s_clk[0], PS2_CLK};
211
                if(data_out_ready) rd_progress <= 1'b0;
212
 
213
                if(~data_in_ready) begin        // send data to PS2
214
                        if(data_shift) data_in_ready <= data_in ^ PS2_DATA;
215
                end else if(wr && ~rd_progress) begin   // initiate data sending to PS2
216
                        data_in_ready <= 1'b0;
217
                end else if(~data_out_ready) begin      // receive data from PS2
218
                        if(s_clk == 2'b10) begin
219
                                rd_progress <= 1'b1;
220
                                if(!rd_progress) data <= 10'b1111111111;
221
                        end
222
                        if(s_clk == 2'b01 && rd_progress) {data, data_out_ready} <= {PS2_DATA, data[9:1], ~data[0]}; // receive is ended by the stop bit
223
                end else if(rd) begin   // initiate data receiving from PS2
224
//                      data <= 10'b1111111111; 
225
                        data_out_ready <= 1'b0;
226
                end
227
        end
228
endmodule

powered by: WebSVN 2.1.0

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