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

Subversion Repositories rf6809

[/] [rf6809/] [trunk/] [rtl/] [noc/] [keyboard/] [PS2kbd.sv] - Blame information for rev 19

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4
//   \\__/ o\    (C) 2005-2022  Robert Finch, Waterloo
5
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch@finitron.ca
7
//       ||
8
//
9
//      PS2kbd.v - PS2 compatible keyboard interface
10
//
11
//
12
// This source file is free software: you can redistribute it and/or modify
13
// it under the terms of the GNU Lesser General Public License as published
14
// by the Free Software Foundation, either version 3 of the License, or
15
// (at your option) any later version.
16
//
17
// This source file is distributed in the hope that it will be useful,
18
// but WITHOUT ANY WARRANTY; without even the implied warranty of
19
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
// GNU General Public License for more details.
21
//
22
// You should have received a copy of the GNU General Public License
23
// along with this program.  If not, see .
24
//
25
//
26
//      PS2 compatible keyboard / mouse interface
27
//
28
//              This core provides a raw interface to the a PS2
29
//      keyboard or mouse. The interface is raw in the sense
30
//      that it doesn't do any scan code processing, it
31
//      just supplies it to the system. The core uses a
32
//      WISHBONE compatible bus interface.
33
//              Both transmit and recieve are
34
//      supported. It is possible to build the core without
35
//      the transmitter to reduce the size of the core; however
36
//      then it would not be possible to control the leds on
37
//      the keyboard. (The transmitter is required for a mouse
38
//      interface).
39
//              There is a 5us debounce circuit on the incoming
40
//      clock.
41
//              The transmitter does not have a watchdog timer, so
42
//      it may cause the keyboard to stop responding if there
43
//      was a problem with the transmit. It relys on the system
44
//      to reset the transmitter after 30ms or so of no
45
//      reponse. Resetting the transmitter should allow the
46
//      keyboard to respond again.
47
//      Note: keyboard clock must be at least three times slower
48
//      than the clk_i input to work reliably.
49
//      A typical keyboard clock is <30kHz so this should be ok
50
//      for most systems.
51
//      * There must be pullup resistors on the keyboard clock
52
//      and data lines, and the keyboard clock and data lines
53
//      are assumed to be open collector.
54
//              To read the keyboard, wait for bit 7 of the status
55
//      register to be set, then read the transmit / recieve
56
//      register. Reading the transmit / recieve register clears
57
//      the keyboard reciever, and allows the next character to
58
//      be recieved.
59
//
60
//      Reg
61
//      0        keyboard transmit/receive register
62
//      1       status reg.             itk xxxx p
63
//              i = interrupt status
64
//              t = transmit complete
65
//              k = transmit acknowledge receipt (from keyboard)
66
//              p = parity error
67
//              A write to the status register clears the transmitter
68
//              state
69
//
70
//
71
//
72
//      Webpack 9.1i xc3s1000-4ft256
73
//      LUTs / slices / MHz
74
//       block rams
75
//      multiplier
76
//
77
// ============================================================================
78
//      A good source of info:
79
//      http://panda.stb_i.ndsu.nodak.edu/~achapwes/PICmicro/PS2/ps2.htm
80
//      http://www.beyondlogic.org/keyboard/keybrd.htm
81
//
82
//      From the keyboard
83
//      1 start bit
84
//      8 data bits
85
//      1 parity bit
86
//      1 stop bit
87
//
88
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89
//      |WISHBONE Datasheet
90
//      |WISHBONE SoC Architecture Specification, Revision B.3
91
//      |
92
//      |Description:                                           Specifications:
93
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94
//      |General Description:                           PS2 keyboard / mouse interface
95
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96
//      |Supported Cycles:                                      SLAVE,READ/WRITE
97
//      |                                                                       SLAVE,BLOCK READ/WRITE
98
//      |                                                                       SLAVE,RMW
99
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100
//      |Data port, size:                                       8 bit
101
//      |Data port, granularity:                        8 bit
102
//      |Data port, maximum operand size:       8 bit
103
//      |Data transfer ordering:                        Undefined
104
//      |Data transfer sequencing:                      Undefined
105
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
106
//      |Clock frequency constraints:           none
107
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108
//      |Supported signal list and                      Signal Name             WISHBONE equiv.
109
//      |cross reference to equivalent          ack_o                   ACK_O
110
//      |WISHBONE signals                                       adr_i                   ADR_I()
111
//      |                                                                       clk_i                   CLK_I
112
//      |                                   cyc_i           CYC_I
113
//      |                                                                       dat_i(7:0)              DAT_I()
114
//      |                                                                       dat_o(7:0)              DAT_O()
115
//      |                                                                       stb_i                   STB_I
116
//      |                                                                       we_i                    WE_I
117
//      |
118
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119
//      |Special requirements:
120
//      +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121
//
122
//==================================================================
123
 
124
`define KBD_TX  1       // include transmitter
125
 
126
`define S_KBDRX_WAIT_CLK                0
127
`define S_KBDRX_CHK_CLK_LOW             1
128
`define S_KBDRX_CAPTURE_BIT             2
129
 
130
module PS2kbd(
131
        // WISHBONE/SoC bus interface
132
        input rst_i,
133
        input clk_i,    // system clock
134
        input cs_i,
135
        input cyc_i,
136
        input stb_i,    // core select (active high)
137
        output reg ack_o,       // bus transfer acknowledged
138
        input we_i,     // I/O write taking place (active high)
139
        input [3:0] adr_i,      // address
140
        input [11:0] dat_i,     // data in
141
        output reg [11:0] dat_o,        // data out
142
        inout tri [11:0] db,
143
        //-------------
144
        output irq,     // interrupt request (active high)
145
        input kclk_i,   // keyboard clock from keyboard
146
        output kclk_en, // 1 = drive clock low
147
        input kdat_i,   // keyboard data
148
        output kdat_en  // 1 = drive data low
149
);
150
parameter pClkFreq = 40000000;
151
parameter pAckStyle = 1'b0;
152
parameter p5us = pClkFreq / 200000;             // number of clocks for 5us
153
parameter p100us = pClkFreq / 10000;    // number of clocks for 100us
154
 
155
reg [13:0] os;  // one shot
156
wire os_5us_done = os==p5us;
157
wire os_100us_done = os==p100us;
158
reg [10:0] q;   // receive register
159
reg tc;                 // transmit complete indicator
160
reg [1:0] s_rx; // keyboard receive state
161
reg [7:0] kq;
162
reg [15:0] kqc;
163
// Use majority logic for bit capture
164
// 4 or more bits high = 1, otherwise 0
165
wire [2:0] kqs = {2'b0,kq[0]}+
166
                                {2'b0,kq[1]}+
167
                                {2'b0,kq[2]}+
168
                                {2'b0,kq[3]}+
169
                                {2'b0,kq[4]}+
170
                                {2'b0,kq[5]}+
171
                                {2'b0,kq[6]};
172
wire kqcne;                     // negative edge on kqc
173
wire kqcpe;                     // positive edge on kqc
174
assign irq = ~q[0];
175
reg kack;                       // keyboard acknowledge bit
176
`ifdef KBD_TX
177
reg [16:0] tx_state;    // transmitter states
178
reg klow;               // force clock line low
179
reg [10:0] t;   // transmit register
180
wire rx_inh = ~tc;      // inhibit receive while transmit occuring
181
reg [3:0] bitcnt;
182
wire shift_done = bitcnt==0;
183
reg tx_oe;                      // transmitter output enable / shift enable
184
`else
185
wire rx_inh = 0;
186
`endif
187
 
188
wire cs = cyc_i & stb_i & cs_i;
189
//reg ack,ack1;
190
//always @(posedge clk_i) begin ack <= cs; ack1 <= ack & cs; end
191
always_ff @(posedge clk_i)
192
        ack_o <= cs ? 1'b1 : pAckStyle;// ? (we_i ? 1'b1 : ack) : 1'b0;
193
 
194
wire pe_cs;
195
edge_det ed1 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(cs), .pe(pe_cs), .ne(), .ee() );
196
 
197
// register read path
198
// Latches data on positive edge of the circuit select, as reading the keyboard
199
// register triggers a clear of it.
200
always_ff @(posedge clk_i)
201
if (cs_i)
202
        case(adr_i[1:0])
203
        2'd0:   dat_o <= {4'h0,q[8:1]};
204
        2'd1:   dat_o <= {4'h0,~q[0],tc,~kack,4'b0,~^q[9:1]};
205
        2'd2:   dat_o <= {4'h0,q[8:1]};
206
        2'd3:   dat_o <= {4'h0,~q[0],tc,~kack,4'b0,~^q[9:1]};
207
        endcase
208
else
209
        dat_o <= 12'h00;
210
 
211
assign db = (cs & ~we_i) ? dat_o : {12{1'bz}};
212
 
213
// Prohibit keyboard device from further transmits until
214
// this character has been processed.
215
// Holding the clock line low does this.
216
//assign kclk = irq ? 1'b0 : 1'bz;
217
`ifdef KBD_TX
218
// Force clock and data low during transmits
219
assign kclk_en = klow | irq;
220
assign kdat_en = tx_oe & ~t[0];// ? 1'b0 : 1'bz;
221
`else
222
assign kclk_en = irq;
223
`endif
224
 
225
// stabilize clock and data
226
always_ff @(posedge clk_i) begin
227
        kq <= {kq[6:0],kdat_i};
228
        kqc <= {kqc[14:0],kclk_i};
229
end
230
 
231
edge_det ed0 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(kqc[10]), .pe(kqcpe), .ne(kqcne), .ee() );
232
 
233
 
234
// The debounce one-shot and 100us timer
235
always @(posedge clk_i)
236
        if (rst_i)
237
                os <= 0;
238
        else begin
239
                if ((s_rx==`S_KBDRX_WAIT_CLK && kqcne && ~rx_inh)||
240
                        (s_rx==`S_KBDRX_CHK_CLK_LOW && rx_inh)
241
`ifdef KBD_TX
242
                        ||tx_state[0]||tx_state[2]||tx_state[5]||tx_state[7]||tx_state[9]||tx_state[11]||tx_state[14]
243
`endif
244
                        )
245
                        os <= 0;
246
                else
247
                        os <= os + 1;
248
        end
249
 
250
 
251
// Receive state machine
252
always_ff @(posedge clk_i) begin
253
        if (rst_i) begin
254
                q <= 11'h7FF;
255
                s_rx <= `S_KBDRX_WAIT_CLK;
256
        end
257
        else begin
258
 
259
                // clear rx on write to status reg
260
                if (cs && we_i && adr_i[1:0]==2'd1 && dat_i[7:0]==8'h00)
261
                        q <= 11'h7FF;
262
 
263
                // Receive state machine
264
                case (s_rx)     // synopsys full_case parallel_case
265
                // negedge on kclk ?
266
                // then set debounce one-shot
267
                `S_KBDRX_WAIT_CLK:
268
                        if (kqcne && ~rx_inh)
269
                                s_rx <= `S_KBDRX_CHK_CLK_LOW;
270
 
271
                // wait 5us
272
                // check if clock low
273
                `S_KBDRX_CHK_CLK_LOW:
274
                        if (rx_inh)
275
                                s_rx <= `S_KBDRX_WAIT_CLK;
276
                        else if (os_5us_done) begin
277
                                // clock low ?
278
                                if (~kqc[10])
279
                                        s_rx <= `S_KBDRX_CAPTURE_BIT;
280
                                else
281
                                        s_rx <= `S_KBDRX_WAIT_CLK;      // no - spurious
282
                        end
283
 
284
                // capture keyboard bit
285
                // keyboard transmits LSB first
286
                `S_KBDRX_CAPTURE_BIT:
287
                        begin
288
                        q <= {kq[2],q[10:1]};
289
                        s_rx <= `S_KBDRX_WAIT_CLK;
290
                        end
291
 
292
                default:
293
                        s_rx <= `S_KBDRX_WAIT_CLK;
294
                endcase
295
        end
296
end
297
 
298
 
299
`ifdef KBD_TX
300
 
301
// Transmit state machine
302
// a shift register / ring counter is used
303
reg adv_tx_state;                       // advance transmitter state
304
reg start_tx;                           // start the transmitter
305
reg clear_tx;                           // clear the transmit state
306
always_ff @(posedge clk_i)
307
        if (rst_i)
308
                tx_state <= 0;
309
        else begin
310
                if (clear_tx)
311
                        tx_state <= 0;
312
                else if (start_tx)
313
                        tx_state[0] <= 1;
314
                else if (adv_tx_state) begin
315
                        tx_state[6:0] <= {tx_state[5:0],1'b0};
316
                        tx_state[7] <= (tx_state[8] && !shift_done) || tx_state[6];
317
                        tx_state[8] <= tx_state[7];
318
                        tx_state[9] <= tx_state[8] && shift_done;
319
                        tx_state[16:10] <= tx_state[15:9];
320
                end
321
        end
322
 
323
 
324
// detect when to advance the transmit state
325
always_comb
326
        case (1'b1)             // synopsys parallel_case
327
        tx_state[0]:    adv_tx_state <= 1;
328
        tx_state[1]:    adv_tx_state <= os_100us_done;
329
        tx_state[2]:    adv_tx_state <= 1;
330
        tx_state[3]:    adv_tx_state <= os_5us_done;
331
        tx_state[4]:    adv_tx_state <= 1;
332
        tx_state[5]:    adv_tx_state <= kqcne;
333
        tx_state[6]:    adv_tx_state <= os_5us_done;
334
        tx_state[7]:    adv_tx_state <= kqcpe;
335
        tx_state[8]:    adv_tx_state <= os_5us_done;
336
        tx_state[9]:    adv_tx_state <= kqcpe;
337
        tx_state[10]:   adv_tx_state <= os_5us_done;
338
        tx_state[11]:   adv_tx_state <= kqcne;
339
        tx_state[12]:   adv_tx_state <= os_5us_done;
340
        tx_state[13]:   adv_tx_state <= 1;
341
        tx_state[14]:   adv_tx_state <= kqcpe;
342
        tx_state[15]:   adv_tx_state <= os_5us_done;
343
        default:                adv_tx_state <= 0;
344
        endcase
345
 
346
wire load_tx = cs && we_i && adr_i[1:0]==2'b0;
347
wire shift_tx = (tx_state[7] & kqcpe)|tx_state[4];
348
 
349
// It can take up to 20ms for the keyboard to accept data
350
// from the host.
351
always_ff @(posedge clk_i) begin
352
        if (rst_i) begin
353
                klow <= 0;
354
                tc <= 1;
355
                start_tx <= 0;
356
                tx_oe <= 0;
357
        end
358
        else begin
359
 
360
                clear_tx <= 0;
361
                start_tx <= 0;
362
 
363
                // write to keyboard register triggers whole thing
364
                if (load_tx) begin
365
                        start_tx <= 1;
366
                        tc <= 0;
367
                end
368
                // write to status register clears transmit state
369
                else if (cs && we_i && adr_i[1:0]==2'd1 && dat_i[7:0]==8'hFF) begin
370
                        tc <= 1;
371
                        tx_oe <= 0;
372
                        klow <= 1'b0;
373
                        clear_tx <= 1;
374
                end
375
                else begin
376
 
377
                        case (1'b1)     // synopsys parallel_case
378
 
379
                        tx_state[0]:    klow <= 1'b1;   // First step: pull the clock low
380
                        tx_state[1]:    ;                               // wait 100 us (hold clock low)
381
                        tx_state[2]:    tx_oe <= 1;             // bring data low / enable shift
382
                        tx_state[3]:    ;       // wait 5us
383
                        // at this point the clock should go high
384
                        // and shift out the start bit
385
                        tx_state[4]:    klow <= 0;              // release clock line
386
                        tx_state[5]:    ;                               // wait for clock to go low
387
                        tx_state[6]:    ;                               // wait 5us
388
                        // state7, 8 shift the data out
389
                        tx_state[7]:    ;                               // wait for clock to go high
390
                        tx_state[8]:    ;                               // wait 5us, go back to state 7
391
                        tx_state[9]:    tx_oe <= 0;             // wait for clock to go high // disable transmit output / shift
392
                        tx_state[10]:   ;                               // wait 5us
393
                        tx_state[11]:   ;                               // wait for clock to go low
394
                        tx_state[12]:   ;                               // wait 5us
395
                        tx_state[13]:   kack <= kq[1];  // capture the ack_o bit from the keyboard
396
                        tx_state[14]:   ;                               // wait for clock to go high
397
                        tx_state[15]:   ;                               // wait 5us
398
                        tx_state[16]:
399
                                begin
400
                                        tc <= 1;                // transmit is now complete
401
                                        clear_tx <= 1;
402
                                end
403
 
404
                        default:        ;
405
 
406
                        endcase
407
                end
408
        end
409
end
410
 
411
 
412
// transmitter shift register
413
always_ff @(posedge clk_i)
414
        if (rst_i)
415
                t <= 11'd0;
416
        else begin
417
                if (load_tx)
418
                        t <= {~(^dat_i[7:0]),dat_i[7:0],2'b0};
419
                else if (shift_tx)
420
                        t <= {1'b1,t[10:1]};
421
        end
422
 
423
 
424
// transmitter bit counter
425
always_ff @(posedge clk_i)
426
        if (rst_i)
427
                bitcnt <= 4'd0;
428
        else begin
429
                if (load_tx)
430
                        bitcnt <= 4'd11;
431
                else if (shift_tx)
432
                        bitcnt <= bitcnt - 4'd1;
433
        end
434
 
435
`endif
436
 
437
endmodule

powered by: WebSVN 2.1.0

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