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

Subversion Repositories next186mp3

[/] [next186mp3/] [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 [7:0]dout,
62
         input clk,                     // cpu CLK
63
         output I_KB,           // interrupt keyboard
64
         output I_MOUSE,  // interrupt mouse
65
         output reg CPU_RST = 0,
66
         inout PS2_CLK1,
67
         inout PS2_CLK2,
68
         inout PS2_DATA1,
69
         inout PS2_DATA2
70
    );
71
 
72
//      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)
73
        reg [3:0]cmdbyte = 4'b1100; // EN2,EN,INT2,INT
74
        reg wcfg = 0;    // write config byte
75
        reg next_mouse = 0;
76
        reg ctl_outb = 0;
77
        reg [9:0]wr_data;
78
        reg [7:0]clkdiv128 = 0;
79
        reg [7: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
        reg [7:0]s_data;
87
 
88
        wire [7:0]kb_data;
89
        wire [7:0]mouse_data;
90
        wire kb_data_out_ready;
91
        wire kb_data_in_ready;
92
        wire mouse_data_out_ready;
93
        wire mouse_data_in_ready;
94
        wire IBF = ((wr_kb | ~kb_data_in_ready) & ~cmdbyte[2]) | ((wr_mouse  | ~mouse_data_in_ready) & ~cmdbyte[3]);
95
        wire kb_shift;
96
        wire mouse_shift;
97
 
98
        assign dout = cmd ? {2'b00, MOBF, 1'b1, wcfg, 1'b1, IBF, OBF | MOBF | ctl_outb} : ctl_outb ? {2'b00, cmdbyte[3:2], 2'b00, cmdbyte[1:0]} : s_data; //MOBF ? mouse_data : kb_data;
99
        assign I_KB = cmdbyte[0] & OBF;                  // INT & OBF
100
        assign I_MOUSE = cmdbyte[1] & MOBF;     // INT2 & MOBF
101
 
102
        PS2Interface Keyboard
103
        (
104
                .PS2_CLK(PS2_CLK1),
105
                .PS2_DATA(PS2_DATA1),
106
                .clk(clk),
107
                .rd(rd_kb),
108
                .wr(wr_kb),
109
                .data_in(wr_data[0]),
110
                .data_out(kb_data),
111
                .data_out_ready(kb_data_out_ready),
112
                .data_in_ready(kb_data_in_ready),
113
                .delay100us(cnt100us[7]),
114
                .data_shift(kb_shift),
115
                .clk_sample(clkdiv128[7])
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[7]),
130
                .data_shift(mouse_shift),
131
                .clk_sample(clkdiv128[7])
132
        );
133
 
134
        always @(posedge clk) begin
135
                CPU_RST <= 0;
136
                if(~kb_data_in_ready) wr_kb <= 0;
137
                if(~kb_data_out_ready) rd_kb <= 1'b0;
138
                if(~mouse_data_in_ready) wr_mouse <= 0;
139
                if(~mouse_data_out_ready) rd_mouse <= 1'b0;
140
 
141
                clkdiv128 <= clkdiv128[6:0] + 1'b1;
142
                if(CS & WR & ~cmd & ~wcfg) cnt100us <= 0; // reset 100us counter for PS2 writing
143
                else if(!cnt100us[7] & clkdiv128[7]) cnt100us <= cnt100us + 1;
144
 
145
 
146
                if(~OBF & ~MOBF)
147
                        if(kb_data_out_ready & ~rd_kb & ~cmdbyte[2]) begin
148
                                OBF <= 1'b1;
149
                                s_data <= kb_data;
150
                        end else if(mouse_data_out_ready & ~rd_mouse & ~cmdbyte[3]) begin
151
                                MOBF <= 1'b1;
152
                                s_data <= mouse_data;
153
                        end
154
 
155
                if(kb_shift | mouse_shift) wr_data <= {1'b1, wr_data[9:1]};
156
 
157
                if(CS)
158
                        if(WR)
159
                                if(cmd) // 0x64 write
160
                                        case(din)
161
                                                8'h20: ctl_outb <= 1;   // read config byte
162
                                                8'h60: wcfg <= 1;                       // write config byte
163
                                                8'ha7: cmdbyte[3] <= 1; // disable mouse
164
                                                8'ha8: cmdbyte[3] <= 0;  // enable mouse
165
                                                8'had: cmdbyte[2] <= 1; // disable kb
166
                                                8'hae: cmdbyte[2] <= 0;  // enable kb
167
                                                8'hd4: next_mouse <= 1; //      write next byte to mouse
168
                                                /*8'hf0, 8'hf2, 8'hf4, 8'hf6, 8'hf8, 8'hfa, 8'hfc,*/ 8'hfe: CPU_RST <= 1; // CPU reset
169
                                        endcase
170
                                else begin      // 0x60 write
171
                                        if(wcfg) cmdbyte <= {din[5:4], din[1:0]};
172
                                        else begin
173
                                                next_mouse <= 0;
174
                                                wr_mouse <= next_mouse;
175
                                                wr_kb <= ~next_mouse;
176
                                                wr_data <= {~^din, din, 1'b0};
177
//                                              cnt100us <= 0;  // reset 100us counter for PS2 writing
178
                                        end
179
                                        wcfg <= 0;
180
                                end
181
                        else    // read data
182
                                if(~cmd) begin
183
                                        ctl_outb <= 1'b0;
184
                                        if(!ctl_outb) begin
185
                                                OBF <= 1'b0;
186
                                                MOBF <= 1'b0;
187
                                                rd_kb <= OBF;
188
                                                rd_mouse <= MOBF;
189
                                        end
190
                                end
191
        end
192
endmodule
193
 
194
 
195
module PS2Interface(
196
         inout PS2_CLK,
197
         inout PS2_DATA,
198
         input clk,
199
         input rd,                              // enable PS2 data reading
200
         input wr,                              // can write data from controller to PS2
201
         input data_in,         // data from controller
202
         input delay100us,
203
         output [7:0]data_out,   // data from PS2
204
         output reg data_out_ready = 1, // PS2 received data ready
205
         output reg data_in_ready = 1,  // PS2 sent data ready
206
         output data_shift,
207
         input clk_sample
208
        );
209
        reg [1:0]s_clk = 2'b11;
210
        reg [9:0]data = 0;
211
        reg rd_progress = 0;
212
        reg s_ps2_clk = 1'b1;
213
 
214
        assign PS2_CLK = ((~data_out_ready & data_in_ready) | (~data_in_ready & delay100us)) ? 1'bz : 1'b0;
215
        assign PS2_DATA = (data_in_ready | data_in | ~delay100us) ? 1'bz : 1'b0;
216
        assign data_out = data[7:0];
217
        assign data_shift = ~data_in_ready && delay100us && s_clk == 2'b10;
218
 
219
        always @(posedge clk) begin
220
                if(clk_sample) s_ps2_clk <= PS2_CLK; // debounce PS2 clock
221
                s_clk <= {s_clk[0], s_ps2_clk};
222
                if(data_out_ready) rd_progress <= 1'b0;
223
 
224
                if(~data_in_ready) begin        // send data to PS2
225
                        if(data_shift) data_in_ready <= data_in ^ PS2_DATA;
226
                end else if(wr && ~rd_progress) begin   // initiate data sending to PS2
227
                        data_in_ready <= 1'b0;
228
                end else if(~data_out_ready) begin      // receive data from PS2
229
                        if(s_clk == 2'b10) begin
230
                                rd_progress <= 1'b1;
231
                                if(!rd_progress) data <= 10'b1111111111;
232
                        end
233
                        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
234
                end else if(rd) begin   // initiate data receiving from PS2
235
//                      data <= 10'b1111111111; 
236
                        data_out_ready <= 1'b0;
237
                end
238
        end
239
endmodule

powered by: WebSVN 2.1.0

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