`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 11:16:01 03/06/2008 // Design Name: // Module Name: ps2kbmit // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // new synchronous ps2 keyboard driver, with built-in fifo, from Chris Terman module ps2(reset, clock_27mhz, ps2c, ps2d, fifo_rd, fifo_data, fifo_empty,fifo_overflow); input clock_27mhz,reset; input ps2c;// ps2 clock input ps2d;// ps2 data input fifo_rd;// fifo read request (active high) output [7:0] fifo_data;// fifo data output output fifo_empty;// fifo empty (active high) output fifo_overflow;// fifo overflow - too much kbd input reg [3:0] count; // count incoming data bits reg [9:0] shift; // accumulate incoming data bits reg [7:0] fifo[7:0]; // 8 element data fifo reg fifo_overflow; reg [2:0] wptr,rptr; // fifo write and read pointers wire [2:0] wptr_inc = wptr + 1; assign fifo_empty = (wptr == rptr); assign fifo_data = fifo[rptr]; // synchronize PS2 clock to local clock and look for falling edge reg [2:0] ps2c_sync; always @ (posedge clock_27mhz) ps2c_sync <= {ps2c_sync[1:0],ps2c}; wire sample = ps2c_sync[2] & ~ps2c_sync[1]; always @ (posedge clock_27mhz) begin if (reset) begin count <= 0; wptr <= 0; rptr <= 0; fifo_overflow <= 0; end else if (sample) begin // order of arrival: 0,8 bits of data (LSB first),odd parity,1 if (count==10) begin // just received what should be the stop bit if (shift[0]==0 && ps2d==1 && (^shift[9:1])==1) begin fifo[wptr] <= shift[8:1]; wptr <= wptr_inc; fifo_overflow <= fifo_overflow | (wptr_inc == rptr); end count <= 0; end else begin shift <= {ps2d,shift[9:1]}; count <= count + 1; end end // bump read pointer if we're done with current value. // Read also resets the overflow indicator if (fifo_rd && !fifo_empty) begin rptr <= rptr + 1; fifo_overflow <= 0; end end endmodule