URL
https://opencores.org/ocsvn/ps2/ps2/trunk
Subversion Repositories ps2
Compare Revisions
- This comparison shows the changes necessary to convert path
/ps2/tags/rel_8/rtl
- from Rev 32 to Rev 51
- ↔ Reverse comparison
Rev 32 → Rev 51
/verilog/ps2_mouse.v
0,0 → 1,523
//------------------------------------------------------------------------------------- |
// |
// Author: John Clayton |
// Date : April 30, 2001 |
// Update: 4/30/01 copied this file from lcd_2.v (pared down). |
// Update: 5/24/01 changed the first module from "ps2_keyboard_receiver" |
// to "ps2_keyboard_interface" |
// Update: 5/29/01 Added input synchronizing flip-flops. Changed state |
// encoding (m1) for good operation after part config. |
// Update: 5/31/01 Added low drive strength and slow transitions to ps2_clk |
// and ps2_data in the constraints file. Added the signal |
// "tx_shifting_done" as distinguished from "rx_shifting_done." |
// Debugged the transmitter portion in the lab. |
// Update: 6/01/01 Added horizontal tab to the ascii output. |
// Update: 6/01/01 Added parameter TRAP_SHIFT_KEYS. |
// Update: 6/05/01 Debugged the "debounce" timer functionality. |
// Used 60usec timer as a "watchdog" timeout during |
// receive from the keyboard. This means that a keyboard |
// can now be "hot plugged" into the interface, without |
// messing up the bit_count, since the bit_count is reset |
// to zero during periods of inactivity anyway. This was |
// difficult to debug. I ended up using the logic analyzer, |
// and had to scratch my head quite a bit. |
// Update: 6/06/01 Removed extra comments before the input synchronizing |
// flip-flops. Used the correct parameter to size the |
// 5usec_timer_count. Changed the name of this file from |
// ps2.v to ps2_keyboard.v |
// Update: 6/06/01 Removed "&& q[7:0]" in output_strobe logic. Removed extra |
// commented out "else" condition in the shift register and |
// bit counter. |
// Update: 6/07/01 Changed default values for 60usec timer parameters so that |
// they correspond to 60usec for a 49.152MHz clock. |
// |
// |
// |
// |
// |
// Description |
//------------------------------------------------------------------------------------- |
// This is a state-machine driven serial-to-parallel and parallel-to-serial |
// interface to the ps2 style keyboard interface. The details of the operation |
// of the keyboard interface were obtained from the following website: |
// |
// http://www.beyondlogic.org/keyboard/keybrd.htm |
// |
// Some aspects of the keyboard interface are not implemented (e.g, parity |
// checking for the receive side, and recognition of the various commands |
// which the keyboard sends out, such as "power on selt test passed," "Error" |
// and "Resend.") However, if the user wishes to recognize these reply |
// messages, the scan code output can always be used to extend functionality |
// as desired. |
// |
// Note that the "Extended" (0xE0) and "Released" (0xF0) codes are recognized. |
// The rx interface provides separate indicator flags for these two conditions |
// with every valid character scan code which it provides. The shift keys are |
// also trapped by the interface, in order to provide correct uppercase ASCII |
// characters at the ascii output, although the scan codes for the shift keys |
// are still provided at the scan code output. So, the left/right ALT keys |
// can be differentiated by the presence of the rx_entended signal, while the |
// left/right shift keys are differentiable by the different scan codes |
// received. |
// |
// The interface to the ps2 keyboard uses ps2_clk clock rates of |
// 30-40 kHz, dependent upon the keyboard itself. The rate at which the state |
// machine runs should be at least twice the rate of the ps2_clk, so that the |
// states can accurately follow the clock signal itself. Four times |
// oversampling is better. Say 200kHz at least. The upper limit for clocking |
// the state machine will undoubtedly be determined by delays in the logic |
// which decodes the scan codes into ASCII equivalents. The maximum speed |
// will be most likely many megahertz, depending upon target technology. |
// In order to run the state machine extremely fast, synchronizing flip-flops |
// have been added to the ps2_clk and ps2_data inputs of the state machine. |
// This avoids poor performance related to slow transitions of the inputs. |
// |
// Because this is a bi-directional interface, while reading from the keyboard |
// the ps2_clk and ps2_data lines are used as inputs. While writing to the |
// keyboard, however (which may be done at any time. If writing interrupts a |
// read from the keyboard, the keyboard will buffer up its data, and send |
// it later) both the ps2_clk and ps2_data lines are occasionally pulled low, |
// and pullup resistors are used to bring the lines high again, by setting |
// the drivers to high impedance state. |
// |
// The tx interface, for writing to the keyboard, does not provide any special |
// pre-processing. It simply transmits the 8-bit command value to the |
// keyboard. |
// |
// Pullups MUST BE USED on the ps2_clk and ps2_data lines for this design, |
// whether they be internal to an FPGA I/O pad, or externally placed. |
// If internal pullups are used, they may be fairly weak, causing bounces |
// due to crosstalk, etc. There is a "debounce timer" implemented in order |
// to eliminate erroneous state transitions which would occur based on bounce. |
// |
// Parameters are provided in order to configure and appropriately size the |
// counter of a 60 microsecond timer used in the transmitter, depending on |
// the clock frequency used. The 60 microsecond period is guaranteed to be |
// more than one period of the ps2_clk_s signal. |
// |
// Also, a smaller 5 microsecond timer has been included for "debounce". |
// This is used because, with internal pullups on the ps2_clk and ps2_data |
// lines, there is some bouncing around which occurs |
// |
// A parameter TRAP_SHIFT_KEYS allows the user to eliminate shift keypresses |
// from producing scan codes (along with their "undefined" ASCII equivalents) |
// at the output of the interface. If TRAP_SHIFT_KEYS is non-zero, the shift |
// key status will only be reported by rx_shift_key_on. No ascii or scan |
// codes will be reported for the shift keys. This is useful for those who |
// wish to use the ASCII data stream, and who don't want to have to "filter |
// out" the shift key codes. |
// |
//------------------------------------------------------------------------------------- |
|
|
// synopsys translate_off |
`resetall |
`include "timescale.v" |
// synopsys translate_on |
`define TOTAL_BITS 11 |
|
module ps2_mouse ( |
clk, |
reset, |
ps2_clk_en_o_, |
ps2_data_en_o_, |
ps2_clk_i, |
ps2_data_i, |
rx_scan_code, |
rx_data_ready, // rx_read_o |
rx_read, // rx_read_ack_i |
tx_data, |
tx_write, |
tx_write_ack_o, |
tx_error_no_ack, |
devide_reg_i |
); |
|
// Parameters |
|
// The timer value can be up to (2^bits) inclusive. |
parameter TIMER_60USEC_VALUE_PP = 2950; // Number of sys_clks for 60usec. |
parameter TIMER_60USEC_BITS_PP = 12; // Number of bits needed for timer |
parameter TIMER_5USEC_VALUE_PP = 186; // Number of sys_clks for debounce |
parameter TIMER_5USEC_BITS_PP = 8; // Number of bits needed for timer |
|
// State encodings, provided as parameters |
// for flexibility to the one instantiating the module. |
// In general, the default values need not be changed. |
|
// State "m1_rx_clk_l" has been chosen on purpose. Since the input |
// synchronizing flip-flops initially contain zero, it takes one clk |
// for them to update to reflect the actual (idle = high) status of |
// the I/O lines from the keyboard. Therefore, choosing 0 for m1_rx_clk_l |
// allows the state machine to transition to m1_rx_clk_h when the true |
// values of the input signals become present at the outputs of the |
// synchronizing flip-flops. This initial transition is harmless, and it |
// eliminates the need for a "reset" pulse before the interface can operate. |
|
parameter m1_rx_clk_h = 1; |
parameter m1_rx_clk_l = 0; |
parameter m1_rx_falling_edge_marker = 13; |
parameter m1_rx_rising_edge_marker = 14; |
parameter m1_tx_force_clk_l = 3; |
parameter m1_tx_first_wait_clk_h = 10; |
parameter m1_tx_first_wait_clk_l = 11; |
parameter m1_tx_reset_timer = 12; |
parameter m1_tx_wait_clk_h = 2; |
parameter m1_tx_clk_h = 4; |
parameter m1_tx_clk_l = 5; |
parameter m1_tx_wait_ack = 6; |
parameter m1_tx_done_recovery = 7; |
parameter m1_tx_error_no_ack = 8; |
parameter m1_tx_rising_edge_marker = 9; |
parameter m2_rx_data_ready = 1; |
parameter m2_rx_data_ready_ack = 0; |
|
|
// I/O declarations |
input clk; |
input reset; |
output ps2_clk_en_o_ ; |
output ps2_data_en_o_ ; |
input ps2_clk_i ; |
input ps2_data_i ; |
output [7:0] rx_scan_code; |
output rx_data_ready; |
input rx_read; |
input [7:0] tx_data; |
input tx_write; |
output tx_write_ack_o; |
output tx_error_no_ack; |
|
input [15:0] devide_reg_i; |
|
reg rx_released; |
reg [7:0] rx_scan_code; |
reg rx_data_ready; |
reg tx_error_no_ack; |
|
// Internal signal declarations |
wire timer_60usec_done; |
wire timer_5usec_done; |
reg timer_done ; |
reg timer_5usec ; |
// NOTE: These two signals used to be one. They |
// were split into two signals because of |
// shift key trapping. With shift key |
// trapping, no event is generated externally, |
// but the "hold" data must still be cleared |
// anyway regardless, in preparation for the |
// next scan codes. |
wire rx_output_event; // Used only to clear: hold_released, hold_extended |
wire rx_output_strobe; // Used to produce the actual output. |
|
wire tx_parity_bit; |
wire rx_shifting_done; |
wire tx_shifting_done; |
|
reg [`TOTAL_BITS-1:0] q; |
reg [3:0] m1_state; |
reg [3:0] m1_next_state; |
reg m2_state; |
reg m2_next_state; |
reg [3:0] bit_count; |
reg enable_timer_60usec; |
reg enable_timer_5usec; |
reg [TIMER_60USEC_BITS_PP-1:0] timer_60usec_count; |
reg [TIMER_5USEC_BITS_PP-1:0] timer_5usec_count; |
reg ps2_clk_s; // Synchronous version of this input |
reg ps2_data_s; // Synchronous version of this input |
reg ps2_clk_hi_z; // Without keyboard, high Z equals 1 due to pullups. |
reg ps2_data_hi_z; // Without keyboard, high Z equals 1 due to pullups. |
|
reg ps2_clk_ms; |
reg ps2_data_ms; |
|
//-------------------------------------------------------------------------- |
// Module code |
|
assign ps2_clk_en_o_ = ps2_clk_hi_z ; |
assign ps2_data_en_o_ = ps2_data_hi_z ; |
|
// Input "synchronizing" logic -- synchronizes the inputs to the state |
// machine clock, thus avoiding errors related to |
// spurious state machine transitions. |
always @(posedge clk) |
begin |
ps2_clk_ms <= #1 ps2_clk_i; |
ps2_data_ms <= #1 ps2_data_i; |
|
ps2_clk_s <= #1 ps2_clk_ms; |
ps2_data_s <= #1 ps2_data_ms; |
|
end |
|
// State register |
always @(posedge clk) |
begin : m1_state_register |
if (reset) m1_state <= #1 m1_rx_clk_h; |
else m1_state <= #1 m1_next_state; |
end |
|
// State transition logic |
always @(m1_state |
or q |
or tx_shifting_done |
or tx_write |
or ps2_clk_s |
or ps2_data_s |
or timer_60usec_done |
or timer_5usec_done |
) |
begin : m1_state_logic |
|
// Output signals default to this value, unless changed in a state condition. |
ps2_clk_hi_z <= #1 1; |
ps2_data_hi_z <= #1 1; |
tx_error_no_ack <= #1 0; |
enable_timer_60usec <= #1 0; |
enable_timer_5usec <= #1 0; |
|
case (m1_state) |
|
m1_rx_clk_h : |
begin |
enable_timer_60usec <= #1 1; |
if (tx_write) m1_next_state <= #1 m1_tx_reset_timer; |
else if (~ps2_clk_s) m1_next_state <= #1 m1_rx_falling_edge_marker; |
else m1_next_state <= #1 m1_rx_clk_h; |
end |
|
m1_rx_falling_edge_marker : |
begin |
enable_timer_60usec <= #1 0; |
m1_next_state <= #1 m1_rx_clk_l; |
end |
|
m1_rx_rising_edge_marker : |
begin |
enable_timer_60usec <= #1 0; |
m1_next_state <= #1 m1_rx_clk_h; |
end |
|
|
m1_rx_clk_l : |
begin |
enable_timer_60usec <= #1 1; |
if (tx_write) m1_next_state <= #1 m1_tx_reset_timer; |
else if (ps2_clk_s) m1_next_state <= #1 m1_rx_rising_edge_marker; |
else m1_next_state <= #1 m1_rx_clk_l; |
end |
|
m1_tx_reset_timer: |
begin |
enable_timer_60usec <= #1 0; |
m1_next_state <= #1 m1_tx_force_clk_l; |
end |
|
m1_tx_force_clk_l : |
begin |
enable_timer_60usec <= #1 1; |
ps2_clk_hi_z <= #1 0; // Force the ps2_clk line low. |
if (timer_60usec_done) m1_next_state <= #1 m1_tx_first_wait_clk_h; |
else m1_next_state <= #1 m1_tx_force_clk_l; |
end |
|
m1_tx_first_wait_clk_h : |
begin |
enable_timer_5usec <= #1 1; |
ps2_data_hi_z <= #1 0; // Start bit. |
if (~ps2_clk_s && timer_5usec_done) |
m1_next_state <= #1 m1_tx_clk_l; |
else |
m1_next_state <= #1 m1_tx_first_wait_clk_h; |
end |
|
// This state must be included because the device might possibly |
// delay for up to 10 milliseconds before beginning its clock pulses. |
// During that waiting time, we cannot drive the data (q[0]) because it |
// is possibly 1, which would cause the keyboard to abort its receive |
// and the expected clocks would then never be generated. |
m1_tx_first_wait_clk_l : |
begin |
ps2_data_hi_z <= #1 0; |
if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l; |
else m1_next_state <= #1 m1_tx_first_wait_clk_l; |
end |
|
m1_tx_wait_clk_h : |
begin |
enable_timer_5usec <= #1 1; |
ps2_data_hi_z <= #1 q[0]; |
if (ps2_clk_s && timer_5usec_done) |
m1_next_state <= #1 m1_tx_rising_edge_marker; |
else |
m1_next_state <= #1 m1_tx_wait_clk_h; |
end |
|
m1_tx_rising_edge_marker : |
begin |
ps2_data_hi_z <= #1 q[0]; |
m1_next_state <= #1 m1_tx_clk_h; |
end |
|
m1_tx_clk_h : |
begin |
ps2_data_hi_z <= #1 q[0]; |
if (tx_shifting_done) m1_next_state <= #1 m1_tx_wait_ack; |
else if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l; |
else m1_next_state <= #1 m1_tx_clk_h; |
end |
|
m1_tx_clk_l : |
begin |
ps2_data_hi_z <= #1 q[0]; |
if (ps2_clk_s) m1_next_state <= #1 m1_tx_wait_clk_h; |
else m1_next_state <= #1 m1_tx_clk_l; |
end |
|
m1_tx_wait_ack : |
begin |
if (~ps2_clk_s && ps2_data_s) |
m1_next_state <= #1 m1_tx_error_no_ack; |
else if (~ps2_clk_s && ~ps2_data_s) |
m1_next_state <= #1 m1_tx_done_recovery; |
else m1_next_state <= #1 m1_tx_wait_ack; |
end |
|
m1_tx_done_recovery : |
begin |
if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h; |
else m1_next_state <= #1 m1_tx_done_recovery; |
end |
|
m1_tx_error_no_ack : |
begin |
tx_error_no_ack <= #1 1; |
if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h; |
else m1_next_state <= #1 m1_tx_error_no_ack; |
end |
|
default : m1_next_state <= #1 m1_rx_clk_h; |
endcase |
end |
|
// State register |
always @(posedge clk) |
begin : m2_state_register |
if (reset) m2_state <= #1 m2_rx_data_ready_ack; |
else m2_state <= #1 m2_next_state; |
end |
|
// State transition logic |
always @(m2_state or rx_output_strobe or rx_read) |
begin : m2_state_logic |
case (m2_state) |
m2_rx_data_ready_ack: |
begin |
rx_data_ready <= #1 1'b0; |
if (rx_output_strobe) m2_next_state <= #1 m2_rx_data_ready; |
else m2_next_state <= #1 m2_rx_data_ready_ack; |
end |
m2_rx_data_ready: |
begin |
rx_data_ready <= #1 1'b1; |
if (rx_read) m2_next_state <= #1 m2_rx_data_ready_ack; |
else m2_next_state <= #1 m2_rx_data_ready; |
end |
default : m2_next_state <= #1 m2_rx_data_ready_ack; |
endcase |
end |
|
// This is the bit counter |
always @(posedge clk) |
begin |
if ( reset |
|| rx_shifting_done |
|| (m1_state == m1_tx_wait_ack) // After tx is done. |
) bit_count <= #1 0; // normal reset |
else if (timer_60usec_done |
&& (m1_state == m1_rx_clk_h) |
&& (ps2_clk_s) |
) bit_count <= #1 0; // rx watchdog timer reset |
else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx |
||(m1_state == m1_tx_rising_edge_marker) // increment for tx |
) |
bit_count <= #1 bit_count + 1; |
end |
// This signal is high for one clock at the end of the timer count. |
assign rx_shifting_done = (bit_count == `TOTAL_BITS); |
assign tx_shifting_done = (bit_count == `TOTAL_BITS-1); |
|
// This is the signal which enables loading of the shift register. |
// It also indicates "ack" to the device writing to the transmitter. |
assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h)) |
||(tx_write && (m1_state == m1_rx_clk_l)) |
); |
|
// This is the ODD parity bit for the transmitted word. |
assign tx_parity_bit = ~^tx_data; |
|
// This is the shift register |
always @(posedge clk) |
begin |
if (reset) q <= #1 0; |
else if (tx_write_ack_o) q <= #1 {1'b1,tx_parity_bit,tx_data,1'b0}; |
else if ( (m1_state == m1_rx_falling_edge_marker) |
||(m1_state == m1_tx_rising_edge_marker) ) |
q <= #1 {ps2_data_s,q[`TOTAL_BITS-1:1]}; |
end |
|
// This is the 60usec timer counter |
always @(posedge clk) |
begin |
if (~enable_timer_60usec) timer_60usec_count <= #1 0; |
else if ( timer_done && !timer_60usec_done) |
timer_60usec_count<= #1 timer_60usec_count +1; |
end |
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP )); |
|
|
|
always @(posedge clk or posedge reset) |
if (reset) timer_5usec <= #1 1; |
else if (!enable_timer_60usec) timer_5usec <= #1 1; |
else if (timer_5usec == devide_reg_i) |
begin |
timer_5usec <= #1 1; |
timer_done <= #1 1; |
end |
else |
begin |
timer_5usec<= #1 timer_5usec +1; |
timer_done <= #1 0; |
end |
|
// This is the 5usec timer counter |
always @(posedge clk) |
begin |
if (~enable_timer_5usec) timer_5usec_count <= #1 0; |
else if (~timer_5usec_done) timer_5usec_count <= #1 timer_5usec_count + 1; |
end |
assign timer_5usec_done = (timer_5usec_count == devide_reg_i - 1); |
|
always @(posedge clk) |
begin |
if (reset) |
begin |
rx_scan_code <= #1 0; |
end |
else if (rx_output_strobe) |
begin |
rx_scan_code <= #1 q[8:1]; |
end |
end |
|
// Store the final rx output data only when all extend and release codes |
// are received and the next (actual key) scan code is also ready. |
// (the presence of rx_extended or rx_released refers to the |
// the current latest scan code received, not the previously latched flags.) |
assign rx_output_event = rx_shifting_done ; |
|
assign rx_output_strobe = rx_shifting_done ; |
|
endmodule |
verilog/ps2_mouse.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: verilog/ps2_wb_if.v
===================================================================
--- verilog/ps2_wb_if.v (nonexistent)
+++ verilog/ps2_wb_if.v (revision 51)
@@ -0,0 +1,727 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// ps2_wb_if.v ////
+//// ////
+//// This file is part of the "ps2" project ////
+//// http://www.opencores.org/cores/ps2/ ////
+//// ////
+//// Author(s): ////
+//// - mihad@opencores.org ////
+//// - Miha Dolenc ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+// Revision 1.7 2003/10/03 10:16:52 primozs
+// support for configurable devider added
+//
+// Revision 1.6 2003/05/28 16:27:09 simons
+// Change the address width.
+//
+// Revision 1.5 2002/04/09 13:24:11 mihad
+// Added mouse interface and everything for its handling, cleaned up some unused code
+//
+// Revision 1.4 2002/02/20 16:35:43 mihad
+// Little/big endian changes continued
+//
+// Revision 1.3 2002/02/20 15:20:10 mihad
+// Little/big endian changes incorporated
+//
+// Revision 1.2 2002/02/18 18:07:55 mihad
+// One bug fixed
+//
+// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
+// Initial project import - working
+//
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+module ps2_wb_if
+(
+ wb_clk_i,
+ wb_rst_i,
+ wb_cyc_i,
+ wb_stb_i,
+ wb_we_i,
+ wb_sel_i,
+ wb_adr_i,
+ wb_dat_i,
+ wb_dat_o,
+ wb_ack_o,
+
+ wb_int_o,
+
+ tx_kbd_write_ack_i,
+ tx_kbd_data_o,
+ tx_kbd_write_o,
+ rx_scancode_i,
+ rx_kbd_data_ready_i,
+ rx_kbd_read_o,
+ translate_o,
+ ps2_kbd_clk_i,
+ devide_reg_o,
+ inhibit_kbd_if_o
+ `ifdef PS2_AUX
+ ,
+ wb_intb_o,
+
+ rx_aux_data_i,
+ rx_aux_data_ready_i,
+ rx_aux_read_o,
+ tx_aux_data_o,
+ tx_aux_write_o,
+ tx_aux_write_ack_i,
+ ps2_aux_clk_i,
+ inhibit_aux_if_o
+`endif
+) ;
+
+input wb_clk_i,
+ wb_rst_i,
+ wb_cyc_i,
+ wb_stb_i,
+ wb_we_i ;
+
+input [3:0] wb_sel_i ;
+
+input [3:0] wb_adr_i ;
+
+input [31:0] wb_dat_i ;
+
+output [31:0] wb_dat_o ;
+
+output wb_ack_o ;
+
+reg wb_ack_o ;
+
+output wb_int_o ;
+reg wb_int_o ;
+
+input tx_kbd_write_ack_i ;
+
+input [7:0] rx_scancode_i ;
+input rx_kbd_data_ready_i ;
+output rx_kbd_read_o ;
+
+output tx_kbd_write_o ;
+output [7:0] tx_kbd_data_o ;
+
+output translate_o ;
+input ps2_kbd_clk_i ;
+
+output inhibit_kbd_if_o ;
+
+reg [7:0] input_buffer,
+ output_buffer ;
+
+output [15:0] devide_reg_o;
+reg [15:0] devide_reg;
+assign devide_reg_o = devide_reg;
+
+
+reg [15:0] wb_dat_i_sampled ;
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ wb_dat_i_sampled <= #1 0 ;
+ else if ( wb_cyc_i && wb_stb_i && wb_we_i )
+ wb_dat_i_sampled <= #1 wb_dat_i[31:16] ;
+end
+
+`ifdef PS2_AUX
+output wb_intb_o ;
+reg wb_intb_o ;
+
+input [7:0] rx_aux_data_i ;
+input rx_aux_data_ready_i ;
+output rx_aux_read_o ;
+output [7:0] tx_aux_data_o ;
+output tx_aux_write_o ;
+input tx_aux_write_ack_i ;
+input ps2_aux_clk_i ;
+output inhibit_aux_if_o ;
+reg inhibit_aux_if_o ;
+reg aux_output_buffer_full ;
+reg aux_input_buffer_full ;
+reg interrupt2 ;
+reg enable2 ;
+assign tx_aux_data_o = output_buffer ;
+assign tx_aux_write_o = aux_output_buffer_full ;
+`else
+wire aux_input_buffer_full = 1'b0 ;
+wire aux_output_buffer_full = 1'b0 ;
+wire interrupt2 = 1'b0 ;
+wire enable2 = 1'b1 ;
+`endif
+
+assign tx_kbd_data_o = output_buffer ;
+
+reg input_buffer_full, // receive buffer
+ output_buffer_full ; // transmit buffer
+
+assign tx_kbd_write_o = output_buffer_full ;
+
+wire system_flag ;
+wire a2 = 1'b0 ;
+wire kbd_inhibit = ps2_kbd_clk_i ;
+wire timeout = 1'b0 ;
+wire perr = 1'b0 ;
+
+wire [7:0] status_byte = {perr, timeout, aux_input_buffer_full, kbd_inhibit, a2, system_flag, output_buffer_full || aux_output_buffer_full, input_buffer_full} ;
+
+reg read_input_buffer_reg ;
+wire read_input_buffer = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !read_input_buffer_reg && !wb_we_i && (wb_adr_i[3:0] == 4'h0) ;
+
+reg write_output_buffer_reg ;
+wire write_output_buffer = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !write_output_buffer_reg && wb_we_i && (wb_adr_i[3:0] == 4'h0) ;
+
+reg read_status_register_reg ;
+wire read_status_register = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !read_status_register_reg && !wb_we_i && (wb_adr_i[3:0] == 4'h4) ;
+
+reg send_command_reg ;
+wire send_command = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !send_command_reg && wb_we_i && (wb_adr_i[3:0] == 4'h4) ;
+
+reg write_devide_reg0 ;
+wire write_devide0 = wb_cyc_i && wb_stb_i && wb_sel_i[2] && !wb_ack_o && !write_devide_reg0 && wb_we_i && (wb_adr_i[3:0] == 4'h8) ;
+
+//reg read_devide_reg ;
+wire read_devide = wb_cyc_i && wb_stb_i && ( wb_sel_i[2]|| wb_sel_i [3] ) && !wb_we_i && (wb_adr_i[3:0] == 4'h8) ;
+
+reg write_devide_reg1 ;
+wire write_devide1 = wb_cyc_i && wb_stb_i && wb_sel_i[3] && !wb_ack_o && !write_devide_reg1 && wb_we_i && (wb_adr_i[3:0] == 4'h8) ;
+
+
+reg translate_o,
+ enable1,
+ system,
+ interrupt1 ;
+
+reg inhibit_kbd_if_o ;
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ inhibit_kbd_if_o <= #1 1'b0 ;
+ else if ( ps2_kbd_clk_i && rx_kbd_data_ready_i && !enable1)
+ inhibit_kbd_if_o <= #1 1'b1 ;
+ else if ( !rx_kbd_data_ready_i || enable1 )
+ inhibit_kbd_if_o <= #1 1'b0 ;
+
+end
+
+`ifdef PS2_AUX
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ inhibit_aux_if_o <= #1 1'b1 ;
+ else if ( ps2_aux_clk_i && rx_aux_data_ready_i && !enable2 )
+ inhibit_aux_if_o <= #1 1'b1 ;
+ else if ( !rx_aux_data_ready_i || enable2 )
+ inhibit_aux_if_o <= #1 1'b0 ;
+
+end
+`endif
+
+assign system_flag = system ;
+
+wire [7:0] command_byte = {1'b0, translate_o, enable2, enable1, 1'b0, system, interrupt2, interrupt1} ;
+
+reg [7:0] current_command ;
+reg [7:0] current_command_output ;
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ begin
+ send_command_reg <= #1 1'b0 ;
+ read_input_buffer_reg <= #1 1'b0 ;
+ write_output_buffer_reg <= #1 1'b0 ;
+ read_status_register_reg <= #1 1'b0 ;
+ write_devide_reg0 <= #1 1'b0 ;
+ //read_devide_reg <= #1 1'b0 ;
+ write_devide_reg1 <= #1 1'b0 ;
+ end
+ else
+ begin
+ send_command_reg <= #1 send_command ;
+ read_input_buffer_reg <= #1 read_input_buffer ;
+ write_output_buffer_reg <= #1 write_output_buffer ;
+ read_status_register_reg <= #1 read_status_register ;
+ write_devide_reg0 <= #1 write_devide0 ;
+ //read_devide_reg <= #1 read_devide ;
+ write_devide_reg1 <= #1 write_devide1 ;
+ end
+end
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ current_command <= #1 8'h0 ;
+ else if ( send_command_reg )
+ current_command <= #1 wb_dat_i_sampled[15:8] ;
+end
+
+reg current_command_valid,
+ current_command_returns_value,
+ current_command_gets_parameter,
+ current_command_gets_null_terminated_string ;
+
+reg write_output_buffer_reg_previous ;
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ write_output_buffer_reg_previous <= #1 1'b0 ;
+ else
+ write_output_buffer_reg_previous <= #1 write_output_buffer_reg ;
+end
+
+wire invalidate_current_command =
+ current_command_valid &&
+ (( current_command_returns_value && read_input_buffer_reg && input_buffer_full) ||
+ ( current_command_gets_parameter && write_output_buffer_reg_previous ) ||
+ ( current_command_gets_null_terminated_string && write_output_buffer_reg_previous && (output_buffer == 8'h00) ) ||
+ ( !current_command_returns_value && !current_command_gets_parameter && !current_command_gets_null_terminated_string )
+ ) ;
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ current_command_valid <= #1 1'b0 ;
+ else if ( invalidate_current_command )
+ current_command_valid <= #1 1'b0 ;
+ else if ( send_command_reg )
+ current_command_valid <= #1 1'b1 ;
+
+end
+
+reg write_command_byte ;
+reg current_command_output_valid ;
+always@(
+ current_command or
+ command_byte or
+ write_output_buffer_reg_previous or
+ current_command_valid or
+ output_buffer
+)
+begin
+ current_command_returns_value = 1'b0 ;
+ current_command_gets_parameter = 1'b0 ;
+ current_command_gets_null_terminated_string = 1'b0 ;
+ current_command_output = 8'h00 ;
+ write_command_byte = 1'b0 ;
+ current_command_output_valid = 1'b0 ;
+ case(current_command)
+ 8'h20:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = command_byte ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'h60:begin
+ current_command_gets_parameter = 1'b1 ;
+ write_command_byte = write_output_buffer_reg_previous && current_command_valid ;
+ end
+ 8'hA1:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'h00 ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hA4:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'hF1 ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hA5:begin
+ current_command_gets_null_terminated_string = 1'b1 ;
+ end
+ 8'hA6:begin
+ end
+ 8'hA7:begin
+ end
+ 8'hA8:begin
+ end
+ 8'hA9:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output_valid = 1'b1 ;
+ `ifdef PS2_AUX
+ current_command_output = 8'h00 ; // interface OK
+ `else
+ current_command_output = 8'h02 ; // clock line stuck high
+ `endif
+ end
+ 8'hAA:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'h55 ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hAB:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'h00 ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hAD:begin
+ end
+ 8'hAE:begin
+ end
+ 8'hAF:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'h00 ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hC0:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'hFF ;
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hC1:begin
+ end
+ 8'hC2:begin
+ end
+ 8'hD0:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'h01 ; // only system reset bit is 1
+ current_command_output_valid = 1'b1 ;
+ end
+ 8'hD1:begin
+ current_command_gets_parameter = 1'b1 ;
+ end
+ 8'hD2:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_gets_parameter = 1'b1 ;
+ current_command_output = output_buffer ;
+ current_command_output_valid = write_output_buffer_reg_previous ;
+ end
+ 8'hD3:begin
+ current_command_gets_parameter = 1'b1 ;
+ `ifdef PS2_AUX
+ current_command_returns_value = 1'b1 ;
+ current_command_output = output_buffer ;
+ current_command_output_valid = write_output_buffer_reg_previous ;
+ `endif
+ end
+ 8'hD4:begin
+ current_command_gets_parameter = 1'b1 ;
+ end
+ 8'hE0:begin
+ current_command_returns_value = 1'b1 ;
+ current_command_output = 8'hFF ;
+ current_command_output_valid = 1'b1 ;
+ end
+ endcase
+end
+
+reg cyc_i_previous ;
+reg stb_i_previous ;
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ begin
+ cyc_i_previous <= #1 1'b0 ;
+ stb_i_previous <= #1 1'b0 ;
+ end
+ else if ( wb_ack_o )
+ begin
+ cyc_i_previous <= #1 1'b0 ;
+ stb_i_previous <= #1 1'b0 ;
+ end
+ else
+ begin
+ cyc_i_previous <= #1 wb_cyc_i ;
+ stb_i_previous <= #1 wb_stb_i ;
+ end
+
+end
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ wb_ack_o <= #1 1'b0 ;
+ else if ( wb_ack_o )
+ wb_ack_o <= #1 1'b0 ;
+ else
+ wb_ack_o <= #1 cyc_i_previous && stb_i_previous ;
+end
+
+reg [31:0] wb_dat_o ;
+wire wb_read = read_input_buffer_reg || read_status_register_reg || read_devide ;
+
+wire [15:0] output_data = read_status_register_reg ? {2{status_byte}} : read_devide ? devide_reg : {2{input_buffer}} ;
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ wb_dat_o <= #1 32'h0 ;
+ else if ( wb_read )
+ wb_dat_o <= #1 {2{output_data}} ;
+end
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ output_buffer_full <= #1 1'b0 ;
+ else if ( output_buffer_full && tx_kbd_write_ack_i || enable1)
+ output_buffer_full <= #1 1'b0 ;
+ else
+ output_buffer_full <= #1 write_output_buffer_reg && (!current_command_valid || (!current_command_gets_parameter && !current_command_gets_null_terminated_string)) ;
+end
+
+`ifdef PS2_AUX
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ aux_output_buffer_full <= #1 1'b0 ;
+ else if ( aux_output_buffer_full && tx_aux_write_ack_i || enable2)
+ aux_output_buffer_full <= #1 1'b0 ;
+ else
+ aux_output_buffer_full <= #1 write_output_buffer_reg && current_command_valid && (current_command == 8'hD4) ;
+end
+`endif
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ output_buffer <= #1 8'h00 ;
+ else if ( write_output_buffer_reg )
+ output_buffer <= #1 wb_dat_i_sampled[15:8];
+end
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ devide_reg <= #1 8'h00 ;
+ else
+ begin
+ if ( write_devide_reg0 )
+ devide_reg[7:0] <= #1 wb_dat_i_sampled[7:0] ;
+ if ( write_devide_reg1 )
+ devide_reg[15:8] <= #1 wb_dat_i_sampled[15:8] ;
+ end
+end
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ begin
+ translate_o <= #1 1'b0 ;
+ system <= #1 1'b0 ;
+ interrupt1 <= #1 1'b0 ;
+ `ifdef PS2_AUX
+ interrupt2 <= #1 1'b0 ;
+ `endif
+ end
+ else if ( write_command_byte )
+ begin
+ translate_o <= #1 output_buffer[6] ;
+ system <= #1 output_buffer[2] ;
+ interrupt1 <= #1 output_buffer[0] ;
+ `ifdef PS2_AUX
+ interrupt2 <= #1 output_buffer[1] ;
+ `endif
+ end
+end
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ enable1 <= #1 1'b1 ;
+ else if ( current_command_valid && (current_command == 8'hAE) )
+ enable1 <= #1 1'b0 ;
+ else if ( current_command_valid && (current_command == 8'hAD) )
+ enable1 <= #1 1'b1 ;
+ else if ( write_command_byte )
+ enable1 <= #1 output_buffer[4] ;
+
+end
+
+`ifdef PS2_AUX
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ enable2 <= #1 1'b1 ;
+ else if ( current_command_valid && (current_command == 8'hA8) )
+ enable2 <= #1 1'b0 ;
+ else if ( current_command_valid && (current_command == 8'hA7) )
+ enable2 <= #1 1'b1 ;
+ else if ( write_command_byte )
+ enable2 <= #1 output_buffer[5] ;
+
+end
+`endif
+
+wire write_input_buffer_from_command = current_command_valid && current_command_returns_value && current_command_output_valid ;
+wire write_input_buffer_from_kbd = !input_buffer_full && rx_kbd_data_ready_i && !enable1 && !current_command_valid ;
+
+`ifdef PS2_AUX
+wire write_input_buffer_from_aux = !input_buffer_full && rx_aux_data_ready_i && !enable2 && !current_command_valid && !write_input_buffer_from_kbd ;
+`endif
+
+wire load_input_buffer_value =
+ write_input_buffer_from_command
+ ||
+ write_input_buffer_from_kbd
+ `ifdef PS2_AUX
+ ||
+ write_input_buffer_from_aux
+ `endif
+ ;
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ input_buffer_full <= #1 1'b0 ;
+ else if ( read_input_buffer_reg )
+ input_buffer_full <= #1 1'b0 ;
+ else if ( load_input_buffer_value )
+ input_buffer_full <= #1 1'b1 ;
+end
+
+`ifdef PS2_AUX
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ aux_input_buffer_full <= #1 1'b0 ;
+ else if ( read_input_buffer_reg )
+ aux_input_buffer_full <= #1 1'b0 ;
+ else if ( write_input_buffer_from_aux || (write_input_buffer_from_command && (current_command == 8'hD3)) )
+ aux_input_buffer_full <= #1 1'b1 ;
+end
+`endif
+
+reg input_buffer_filled_from_command ;
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ input_buffer_filled_from_command <= #1 1'b0 ;
+ else if ( read_input_buffer_reg )
+ input_buffer_filled_from_command <= #1 1'b0 ;
+ else if ( write_input_buffer_from_command )
+ input_buffer_filled_from_command <= #1 1'b1 ;
+end
+
+`ifdef PS2_AUX
+reg [7:0] value_to_load_in_input_buffer ;
+always@
+(
+ write_input_buffer_from_command
+ or
+ current_command_output
+ or
+ rx_scancode_i
+ or
+ write_input_buffer_from_kbd
+ or
+ rx_aux_data_i
+)
+begin
+ case ({write_input_buffer_from_command, write_input_buffer_from_kbd})
+ 2'b10,
+ 2'b11 : value_to_load_in_input_buffer = current_command_output ;
+ 2'b01 : value_to_load_in_input_buffer = rx_scancode_i ;
+ 2'b00 : value_to_load_in_input_buffer = rx_aux_data_i ;
+ endcase
+end
+
+`else
+wire [7:0] value_to_load_in_input_buffer = write_input_buffer_from_command ? current_command_output : rx_scancode_i ;
+`endif
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ input_buffer <= #1 8'h00 ;
+ else if ( load_input_buffer_value )
+ input_buffer <= #1 value_to_load_in_input_buffer ;
+end
+
+assign rx_kbd_read_o = rx_kbd_data_ready_i &&
+ ( enable1
+ ||
+ ( read_input_buffer_reg
+ &&
+ input_buffer_full
+ &&
+ !input_buffer_filled_from_command
+ `ifdef PS2_AUX
+ &&
+ !aux_input_buffer_full
+ `endif
+ )
+ );
+
+`ifdef PS2_AUX
+assign rx_aux_read_o = rx_aux_data_ready_i &&
+ ( enable2 ||
+ ( read_input_buffer_reg
+ &&
+ input_buffer_full
+ &&
+ aux_input_buffer_full
+ &&
+ !input_buffer_filled_from_command
+ )
+ );
+`endif
+
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ wb_int_o <= #1 1'b0 ;
+ else if ( read_input_buffer_reg || enable1 || !interrupt1)
+ wb_int_o <= #1 1'b0 ;
+ else
+ wb_int_o <= #1 input_buffer_full
+ `ifdef PS2_AUX
+ &&
+ !aux_input_buffer_full
+ `endif
+ ;
+end
+
+`ifdef PS2_AUX
+always@(posedge wb_clk_i or posedge wb_rst_i)
+begin
+ if ( wb_rst_i )
+ wb_intb_o <= #1 1'b0 ;
+ else if ( read_input_buffer_reg || enable2 || !interrupt2)
+ wb_intb_o <= #1 1'b0 ;
+ else
+ wb_intb_o <= #1 input_buffer_full
+ &&
+ aux_input_buffer_full
+ ;
+end
+`endif
+
+endmodule // ps2_wb_if
Index: verilog/ps2_keyboard.v
===================================================================
--- verilog/ps2_keyboard.v (nonexistent)
+++ verilog/ps2_keyboard.v (revision 51)
@@ -0,0 +1,568 @@
+//-------------------------------------------------------------------------------------
+//
+// Author: John Clayton
+// Date : April 30, 2001
+// Update: 4/30/01 copied this file from lcd_2.v (pared down).
+// Update: 5/24/01 changed the first module from "ps2_keyboard_receiver"
+// to "ps2_keyboard_interface"
+// Update: 5/29/01 Added input synchronizing flip-flops. Changed state
+// encoding (m1) for good operation after part config.
+// Update: 5/31/01 Added low drive strength and slow transitions to ps2_clk
+// and ps2_data in the constraints file. Added the signal
+// "tx_shifting_done" as distinguished from "rx_shifting_done."
+// Debugged the transmitter portion in the lab.
+// Update: 6/01/01 Added horizontal tab to the ascii output.
+// Update: 6/01/01 Added parameter TRAP_SHIFT_KEYS.
+// Update: 6/05/01 Debugged the "debounce" timer functionality.
+// Used 60usec timer as a "watchdog" timeout during
+// receive from the keyboard. This means that a keyboard
+// can now be "hot plugged" into the interface, without
+// messing up the bit_count, since the bit_count is reset
+// to zero during periods of inactivity anyway. This was
+// difficult to debug. I ended up using the logic analyzer,
+// and had to scratch my head quite a bit.
+// Update: 6/06/01 Removed extra comments before the input synchronizing
+// flip-flops. Used the correct parameter to size the
+// 5usec_timer_count. Changed the name of this file from
+// ps2.v to ps2_keyboard.v
+// Update: 6/06/01 Removed "&& q[7:0]" in output_strobe logic. Removed extra
+// commented out "else" condition in the shift register and
+// bit counter.
+// Update: 6/07/01 Changed default values for 60usec timer parameters so that
+// they correspond to 60usec for a 49.152MHz clock.
+//
+//
+//
+//
+//
+// Description
+//-------------------------------------------------------------------------------------
+// This is a state-machine driven serial-to-parallel and parallel-to-serial
+// interface to the ps2 style keyboard interface. The details of the operation
+// of the keyboard interface were obtained from the following website:
+//
+// http://www.beyondlogic.org/keyboard/keybrd.htm
+//
+// Some aspects of the keyboard interface are not implemented (e.g, parity
+// checking for the receive side, and recognition of the various commands
+// which the keyboard sends out, such as "power on selt test passed," "Error"
+// and "Resend.") However, if the user wishes to recognize these reply
+// messages, the scan code output can always be used to extend functionality
+// as desired.
+//
+// Note that the "Extended" (0xE0) and "Released" (0xF0) codes are recognized.
+// The rx interface provides separate indicator flags for these two conditions
+// with every valid character scan code which it provides. The shift keys are
+// also trapped by the interface, in order to provide correct uppercase ASCII
+// characters at the ascii output, although the scan codes for the shift keys
+// are still provided at the scan code output. So, the left/right ALT keys
+// can be differentiated by the presence of the rx_entended signal, while the
+// left/right shift keys are differentiable by the different scan codes
+// received.
+//
+// The interface to the ps2 keyboard uses ps2_clk clock rates of
+// 30-40 kHz, dependent upon the keyboard itself. The rate at which the state
+// machine runs should be at least twice the rate of the ps2_clk, so that the
+// states can accurately follow the clock signal itself. Four times
+// oversampling is better. Say 200kHz at least. The upper limit for clocking
+// the state machine will undoubtedly be determined by delays in the logic
+// which decodes the scan codes into ASCII equivalents. The maximum speed
+// will be most likely many megahertz, depending upon target technology.
+// In order to run the state machine extremely fast, synchronizing flip-flops
+// have been added to the ps2_clk and ps2_data inputs of the state machine.
+// This avoids poor performance related to slow transitions of the inputs.
+//
+// Because this is a bi-directional interface, while reading from the keyboard
+// the ps2_clk and ps2_data lines are used as inputs. While writing to the
+// keyboard, however (which may be done at any time. If writing interrupts a
+// read from the keyboard, the keyboard will buffer up its data, and send
+// it later) both the ps2_clk and ps2_data lines are occasionally pulled low,
+// and pullup resistors are used to bring the lines high again, by setting
+// the drivers to high impedance state.
+//
+// The tx interface, for writing to the keyboard, does not provide any special
+// pre-processing. It simply transmits the 8-bit command value to the
+// keyboard.
+//
+// Pullups MUST BE USED on the ps2_clk and ps2_data lines for this design,
+// whether they be internal to an FPGA I/O pad, or externally placed.
+// If internal pullups are used, they may be fairly weak, causing bounces
+// due to crosstalk, etc. There is a "debounce timer" implemented in order
+// to eliminate erroneous state transitions which would occur based on bounce.
+//
+// Parameters are provided in order to configure and appropriately size the
+// counter of a 60 microsecond timer used in the transmitter, depending on
+// the clock frequency used. The 60 microsecond period is guaranteed to be
+// more than one period of the ps2_clk_s signal.
+//
+// Also, a smaller 5 microsecond timer has been included for "debounce".
+// This is used because, with internal pullups on the ps2_clk and ps2_data
+// lines, there is some bouncing around which occurs
+//
+// A parameter TRAP_SHIFT_KEYS allows the user to eliminate shift keypresses
+// from producing scan codes (along with their "undefined" ASCII equivalents)
+// at the output of the interface. If TRAP_SHIFT_KEYS is non-zero, the shift
+// key status will only be reported by rx_shift_key_on. No ascii or scan
+// codes will be reported for the shift keys. This is useful for those who
+// wish to use the ASCII data stream, and who don't want to have to "filter
+// out" the shift key codes.
+//
+//-------------------------------------------------------------------------------------
+
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+`define TOTAL_BITS 11
+`define RELEASE_CODE 16'hF0
+
+module ps2_keyboard (
+ clk,
+ reset,
+ ps2_clk_en_o_,
+ ps2_data_en_o_,
+ ps2_clk_i,
+ ps2_data_i,
+ rx_released,
+ rx_scan_code,
+ rx_data_ready, // rx_read_o
+ rx_read, // rx_read_ack_i
+ tx_data,
+ tx_write,
+ tx_write_ack_o,
+ tx_error_no_keyboard_ack,
+ translate,
+ devide_reg_i
+ );
+
+// Parameters
+
+
+// The timer value can be up to (2^bits) inclusive.
+parameter TIMER_60USEC_VALUE_PP = 2950; // Number of sys_clks for 60usec.
+parameter TIMER_60USEC_BITS_PP = 12; // Number of bits needed for timer
+parameter TIMER_5USEC_VALUE_PP = 186; // Number of sys_clks for debounce
+parameter TIMER_5USEC_BITS_PP = 8; // Number of bits needed for timer
+
+// State encodings, provided as parameters
+// for flexibility to the one instantiating the module.
+// In general, the default values need not be changed.
+
+// State "m1_rx_clk_l" has been chosen on purpose. Since the input
+// synchronizing flip-flops initially contain zero, it takes one clk
+// for them to update to reflect the actual (idle = high) status of
+// the I/O lines from the keyboard. Therefore, choosing 0 for m1_rx_clk_l
+// allows the state machine to transition to m1_rx_clk_h when the true
+// values of the input signals become present at the outputs of the
+// synchronizing flip-flops. This initial transition is harmless, and it
+// eliminates the need for a "reset" pulse before the interface can operate.
+
+parameter m1_rx_clk_h = 1;
+parameter m1_rx_clk_l = 0;
+parameter m1_rx_falling_edge_marker = 13;
+parameter m1_rx_rising_edge_marker = 14;
+parameter m1_tx_force_clk_l = 3;
+parameter m1_tx_first_wait_clk_h = 10;
+parameter m1_tx_first_wait_clk_l = 11;
+parameter m1_tx_reset_timer = 12;
+parameter m1_tx_wait_clk_h = 2;
+parameter m1_tx_clk_h = 4;
+parameter m1_tx_clk_l = 5;
+parameter m1_tx_wait_keyboard_ack = 6;
+parameter m1_tx_done_recovery = 7;
+parameter m1_tx_error_no_keyboard_ack = 8;
+parameter m1_tx_rising_edge_marker = 9;
+parameter m2_rx_data_ready = 1;
+parameter m2_rx_data_ready_ack = 0;
+
+
+// I/O declarations
+input clk;
+input reset;
+output ps2_clk_en_o_ ;
+output ps2_data_en_o_ ;
+input ps2_clk_i ;
+input ps2_data_i ;
+output rx_released;
+output [7:0] rx_scan_code;
+output rx_data_ready;
+input rx_read;
+input [7:0] tx_data;
+input tx_write;
+output tx_write_ack_o;
+output tx_error_no_keyboard_ack;
+input translate ;
+
+input [15:0] devide_reg_i;
+
+reg rx_released;
+reg [7:0] rx_scan_code;
+reg rx_data_ready;
+reg tx_error_no_keyboard_ack;
+
+// Internal signal declarations
+wire timer_60usec_done;
+wire timer_5usec_done;
+wire released;
+
+ // NOTE: These two signals used to be one. They
+ // were split into two signals because of
+ // shift key trapping. With shift key
+ // trapping, no event is generated externally,
+ // but the "hold" data must still be cleared
+ // anyway regardless, in preparation for the
+ // next scan codes.
+wire rx_output_event; // Used only to clear: hold_released, hold_extended
+wire rx_output_strobe; // Used to produce the actual output.
+
+wire tx_parity_bit;
+wire rx_shifting_done;
+wire tx_shifting_done;
+
+reg [`TOTAL_BITS-1:0] q;
+reg [3:0] m1_state;
+reg [3:0] m1_next_state;
+reg m2_state;
+reg m2_next_state;
+reg [3:0] bit_count;
+reg enable_timer_60usec;
+reg enable_timer_5usec;
+reg [TIMER_60USEC_BITS_PP-1:0] timer_60usec_count;
+reg [TIMER_5USEC_BITS_PP-1:0] timer_5usec_count;
+reg hold_released; // Holds prior value, cleared at rx_output_strobe
+reg ps2_clk_s; // Synchronous version of this input
+reg ps2_data_s; // Synchronous version of this input
+reg ps2_clk_hi_z; // Without keyboard, high Z equals 1 due to pullups.
+reg ps2_data_hi_z; // Without keyboard, high Z equals 1 due to pullups.
+reg ps2_clk_ms;
+reg ps2_data_ms;
+
+
+reg [15:0] timer_5usec;
+reg timer_done;
+
+
+
+//--------------------------------------------------------------------------
+// Module code
+
+assign ps2_clk_en_o_ = ps2_clk_hi_z ;
+assign ps2_data_en_o_ = ps2_data_hi_z ;
+
+// Input "synchronizing" logic -- synchronizes the inputs to the state
+// machine clock, thus avoiding errors related to
+// spurious state machine transitions.
+always @(posedge clk)
+begin
+ ps2_clk_ms <= #1 ps2_clk_i;
+ ps2_data_ms <= #1 ps2_data_i;
+
+ ps2_clk_s <= #1 ps2_clk_ms;
+ ps2_data_s <= #1 ps2_data_ms;
+
+end
+
+// State register
+always @(posedge clk or posedge reset)
+begin : m1_state_register
+ if (reset) m1_state <= #1 m1_rx_clk_h;
+ else m1_state <= #1 m1_next_state;
+end
+
+// State transition logic
+always @(m1_state
+ or q
+ or tx_shifting_done
+ or tx_write
+ or ps2_clk_s
+ or ps2_data_s
+ or timer_60usec_done
+ or timer_5usec_done
+ )
+begin : m1_state_logic
+
+ // Output signals default to this value, unless changed in a state condition.
+ ps2_clk_hi_z <= #1 1;
+ ps2_data_hi_z <= #1 1;
+ tx_error_no_keyboard_ack <= #1 1'b0;
+ enable_timer_60usec <= #1 0;
+ enable_timer_5usec <= #1 0;
+
+ case (m1_state)
+
+ m1_rx_clk_h :
+ begin
+ enable_timer_60usec <= #1 1;
+ if (tx_write) m1_next_state <= #1 m1_tx_reset_timer;
+ else if (~ps2_clk_s) m1_next_state <= #1 m1_rx_falling_edge_marker;
+ else m1_next_state <= #1 m1_rx_clk_h;
+ end
+
+ m1_rx_falling_edge_marker :
+ begin
+ enable_timer_60usec <= #1 0;
+ m1_next_state <= #1 m1_rx_clk_l;
+ end
+
+ m1_rx_rising_edge_marker :
+ begin
+ enable_timer_60usec <= #1 0;
+ m1_next_state <= #1 m1_rx_clk_h;
+ end
+
+
+ m1_rx_clk_l :
+ begin
+ enable_timer_60usec <= #1 1;
+ if (tx_write) m1_next_state <= #1 m1_tx_reset_timer;
+ else if (ps2_clk_s) m1_next_state <= #1 m1_rx_rising_edge_marker;
+ else m1_next_state <= #1 m1_rx_clk_l;
+ end
+
+ m1_tx_reset_timer:
+ begin
+ enable_timer_60usec <= #1 0;
+ m1_next_state <= #1 m1_tx_force_clk_l;
+ end
+
+ m1_tx_force_clk_l :
+ begin
+ enable_timer_60usec <= #1 1;
+ ps2_clk_hi_z <= #1 0; // Force the ps2_clk line low.
+ if (timer_60usec_done) m1_next_state <= #1 m1_tx_first_wait_clk_h;
+ else m1_next_state <= #1 m1_tx_force_clk_l;
+ end
+
+ m1_tx_first_wait_clk_h :
+ begin
+ enable_timer_5usec <= #1 1;
+ ps2_data_hi_z <= #1 0; // Start bit.
+ if (~ps2_clk_s && timer_5usec_done)
+ m1_next_state <= #1 m1_tx_clk_l;
+ else
+ m1_next_state <= #1 m1_tx_first_wait_clk_h;
+ end
+
+ // This state must be included because the device might possibly
+ // delay for up to 10 milliseconds before beginning its clock pulses.
+ // During that waiting time, we cannot drive the data (q[0]) because it
+ // is possibly 1, which would cause the keyboard to abort its receive
+ // and the expected clocks would then never be generated.
+ m1_tx_first_wait_clk_l :
+ begin
+ ps2_data_hi_z <= #1 0;
+ if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l;
+ else m1_next_state <= #1 m1_tx_first_wait_clk_l;
+ end
+
+ m1_tx_wait_clk_h :
+ begin
+ enable_timer_5usec <= #1 1;
+ ps2_data_hi_z <= #1 q[0];
+ if (ps2_clk_s && timer_5usec_done)
+ m1_next_state <= #1 m1_tx_rising_edge_marker;
+ else
+ m1_next_state <= #1 m1_tx_wait_clk_h;
+ end
+
+ m1_tx_rising_edge_marker :
+ begin
+ ps2_data_hi_z <= #1 q[0];
+ m1_next_state <= #1 m1_tx_clk_h;
+ end
+
+ m1_tx_clk_h :
+ begin
+ ps2_data_hi_z <= #1 q[0];
+ if (tx_shifting_done) m1_next_state <= #1 m1_tx_wait_keyboard_ack;
+ else if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l;
+ else m1_next_state <= #1 m1_tx_clk_h;
+ end
+
+ m1_tx_clk_l :
+ begin
+ ps2_data_hi_z <= #1 q[0];
+ if (ps2_clk_s) m1_next_state <= #1 m1_tx_wait_clk_h;
+ else m1_next_state <= #1 m1_tx_clk_l;
+ end
+
+ m1_tx_wait_keyboard_ack :
+ begin
+ if (~ps2_clk_s && ps2_data_s)
+ m1_next_state <= #1 m1_tx_error_no_keyboard_ack;
+ else if (~ps2_clk_s && ~ps2_data_s)
+ m1_next_state <= #1 m1_tx_done_recovery;
+ else m1_next_state <= #1 m1_tx_wait_keyboard_ack;
+ end
+
+ m1_tx_done_recovery :
+ begin
+ if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h;
+ else m1_next_state <= #1 m1_tx_done_recovery;
+ end
+
+ m1_tx_error_no_keyboard_ack :
+ begin
+ tx_error_no_keyboard_ack <= #1 1;
+ if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h;
+ else m1_next_state <= #1 m1_tx_error_no_keyboard_ack;
+ end
+
+ default : m1_next_state <= #1 m1_rx_clk_h;
+ endcase
+end
+
+// State register
+always @(posedge clk or posedge reset)
+begin : m2_state_register
+ if (reset) m2_state <= #1 m2_rx_data_ready_ack;
+ else m2_state <= #1 m2_next_state;
+end
+
+// State transition logic
+always @(m2_state or rx_output_strobe or rx_read)
+begin : m2_state_logic
+ case (m2_state)
+ m2_rx_data_ready_ack:
+ begin
+ rx_data_ready <= #1 1'b0;
+ if (rx_output_strobe) m2_next_state <= #1 m2_rx_data_ready;
+ else m2_next_state <= #1 m2_rx_data_ready_ack;
+ end
+ m2_rx_data_ready:
+ begin
+ rx_data_ready <= #1 1'b1;
+ if (rx_read) m2_next_state <= #1 m2_rx_data_ready_ack;
+ else m2_next_state <= #1 m2_rx_data_ready;
+ end
+ default : m2_next_state <= #1 m2_rx_data_ready_ack;
+ endcase
+end
+
+// This is the bit counter
+always @(posedge clk or posedge reset)
+begin
+ if ( reset) bit_count <= #1 0;
+ else if ( rx_shifting_done || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done.
+ ) bit_count <= #1 0; // normal reset
+ else if (timer_60usec_done
+ && (m1_state == m1_rx_clk_h)
+ && (ps2_clk_s)
+ ) bit_count <= #1 0; // rx watchdog timer reset
+ else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
+ ||(m1_state == m1_tx_rising_edge_marker) // increment for tx
+ )
+ bit_count <= #1 bit_count + 1;
+end
+// This signal is high for one clock at the end of the timer count.
+assign rx_shifting_done = (bit_count == `TOTAL_BITS);
+assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
+
+// This is the signal which enables loading of the shift register.
+// It also indicates "ack" to the device writing to the transmitter.
+assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h))
+ ||(tx_write && (m1_state == m1_rx_clk_l))
+ );
+
+// This is the ODD parity bit for the transmitted word.
+assign tx_parity_bit = ~^tx_data;
+
+// This is the shift register
+always @(posedge clk or posedge reset)
+begin
+ if (reset) q <= #1 0;
+ else if (tx_write_ack_o) q <= #1 {1'b1,tx_parity_bit,tx_data,1'b0};
+ else if ( (m1_state == m1_rx_falling_edge_marker)
+ ||(m1_state == m1_tx_rising_edge_marker) )
+ q <= #1 {ps2_data_s,q[`TOTAL_BITS-1:1]};
+end
+
+// This is the 60usec timer counter
+always @(posedge clk)
+begin
+ if (~enable_timer_60usec) timer_60usec_count <= #1 0;
+ else if ( timer_done && !timer_60usec_done)
+ timer_60usec_count<= #1 timer_60usec_count +1;
+ end
+assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP ));
+
+
+
+always @(posedge clk or posedge reset)
+if (reset) timer_5usec <= #1 1;
+else if (!enable_timer_60usec) timer_5usec <= #1 1;
+else if (timer_5usec == devide_reg_i)
+ begin
+ timer_5usec <= #1 1;
+ timer_done <= #1 1;
+ end
+else
+ begin
+ timer_5usec<= #1 timer_5usec +1;
+ timer_done <= #1 0;
+ end
+
+// This is the 5usec timer counter
+always @(posedge clk)
+begin
+ if (~enable_timer_5usec) timer_5usec_count <= #1 0;
+ else if (~timer_5usec_done) timer_5usec_count <= #1 timer_5usec_count + 1;
+end
+assign timer_5usec_done = (timer_5usec_count == devide_reg_i -1);
+
+
+// Create the signals which indicate special scan codes received.
+// These are the "unlatched versions."
+assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done && translate ;
+
+// Store the special scan code status bits
+// Not the final output, but an intermediate storage place,
+// until the entire set of output data can be assembled.
+always @(posedge clk or posedge reset)
+begin
+ if (reset) hold_released <= #1 0;
+ else if (rx_output_event)
+ begin
+ hold_released <= #1 0;
+ end
+ else
+ begin
+ if (rx_shifting_done && released) hold_released <= #1 1;
+ end
+end
+
+// Output the special scan code flags, the scan code and the ascii
+always @(posedge clk or posedge reset)
+begin
+ if (reset)
+ begin
+ rx_released <= #1 0;
+ rx_scan_code <= #1 0;
+ end
+ else if (rx_output_strobe)
+ begin
+ rx_released <= #1 hold_released;
+ rx_scan_code <= #1 q[8:1];
+ end
+end
+
+// Store the final rx output data only when all extend and release codes
+// are received and the next (actual key) scan code is also ready.
+// (the presence of rx_extended or rx_released refers to the
+// the current latest scan code received, not the previously latched flags.)
+assign rx_output_event = (rx_shifting_done
+ && ~released
+ );
+
+assign rx_output_strobe = (rx_shifting_done
+ && ~released
+ );
+
+endmodule
+
+//`undefine TOTAL_BITS
+//`undefine EXTEND_CODE
+//`undefine RELEASE_CODE
+//`undefine LEFT_SHIFT
+//`undefine RIGHT_SHIFT
+
verilog/ps2_keyboard.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: verilog/ps2_defines.v
===================================================================
--- verilog/ps2_defines.v (nonexistent)
+++ verilog/ps2_defines.v (revision 51)
@@ -0,0 +1,78 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// ps2_defines.v ////
+//// ////
+//// This file is part of the "ps2" project ////
+//// http://www.opencores.org/cores/ps2/ ////
+//// ////
+//// Author(s): ////
+//// - mihad@opencores.org ////
+//// - Miha Dolenc ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+// Revision 1.4 2003/07/01 12:34:03 mihad
+// Added an option to use constant values instead of RAM
+// in the translation table.
+//
+// Revision 1.3 2002/04/09 13:21:15 mihad
+// Added mouse interface and everything for its handling, cleaned up some unused code
+//
+// Revision 1.2 2002/02/18 16:33:08 mihad
+// Changed defines for simulation to work without xilinx primitives
+//
+// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
+// Initial project import - working
+//
+//
+
+//`define PS2_RAMB4
+`define PS2_CONSTANTS_ROM
+
+`define PS2_TRANSLATION_TABLE_31_0 256'h5b03111e1f2c71665a02101d702a386559290f3e40424464583c3b3d3f4143ff
+`define PS2_TRANSLATION_TABLE_63_32 256'h5f0908162432726a5e071522233031695d061314212f39685c040512202d2e67
+`define PS2_TRANSLATION_TABLE_95_64 256'h76632b751b1c363a6e620d1a7428736d610c19272635346c600a0b181725336b
+`define PS2_TRANSLATION_TABLE_127_96 256'h544649374a514e574501484d4c5053526f7f7e474b7d4f7c7b0e7a7978775655
+`define PS2_TRANSLATION_TABLE_159_128 256'h9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786855441828180
+`define PS2_TRANSLATION_TABLE_191_160 256'hbfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0
+`define PS2_TRANSLATION_TABLE_223_192 256'hdfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0
+`define PS2_TRANSLATION_TABLE_255_224 256'hfffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0
+
+`define PS2_TIMER_60USEC_VALUE_PP 12 // Number of sys_clks for 60usec.
+`define PS2_TIMER_60USEC_BITS_PP 4 // Number of bits needed for timer
+`define PS2_TIMER_5USEC_VALUE_PP 500 // Number of sys_clks for debounce
+`define PS2_TIMER_5USEC_BITS_PP 16 // Number of bits needed for timer
+
+//`define PS2_AUX
verilog/ps2_defines.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: verilog/ps2_top.v
===================================================================
--- verilog/ps2_top.v (nonexistent)
+++ verilog/ps2_top.v (revision 51)
@@ -0,0 +1,305 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// ps2_top.v ////
+//// ////
+//// This file is part of the "ps2" project ////
+//// http://www.opencores.org/cores/ps2/ ////
+//// ////
+//// Author(s): ////
+//// - mihad@opencores.org ////
+//// - Miha Dolenc ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+// Revision 1.5 2003/06/30 15:29:27 simons
+// Error fixed again.
+//
+// Revision 1.4 2003/06/30 15:25:45 simons
+// Error fixed.
+//
+// Revision 1.3 2003/05/28 16:27:09 simons
+// Change the address width.
+//
+// Revision 1.2 2002/04/09 13:21:15 mihad
+// Added mouse interface and everything for its handling, cleaned up some unused code
+//
+// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
+// Initial project import - working
+//
+//
+
+`include "ps2_defines.v"
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+module ps2_top
+(
+ wb_clk_i,
+ wb_rst_i,
+ wb_cyc_i,
+ wb_stb_i,
+ wb_we_i,
+ wb_sel_i,
+ wb_adr_i,
+ wb_dat_i,
+ wb_dat_o,
+ wb_ack_o,
+
+ wb_int_o,
+
+ ps2_kbd_clk_pad_i,
+ ps2_kbd_data_pad_i,
+ ps2_kbd_clk_pad_o,
+ ps2_kbd_data_pad_o,
+ ps2_kbd_clk_pad_oe_o,
+ ps2_kbd_data_pad_oe_o
+ `ifdef PS2_AUX
+ ,
+ wb_intb_o,
+
+ ps2_aux_clk_pad_i,
+ ps2_aux_data_pad_i,
+ ps2_aux_clk_pad_o,
+ ps2_aux_data_pad_o,
+ ps2_aux_clk_pad_oe_o,
+ ps2_aux_data_pad_oe_o
+ `endif
+) ;
+
+input wb_clk_i,
+ wb_rst_i,
+ wb_cyc_i,
+ wb_stb_i,
+ wb_we_i ;
+
+input [3:0] wb_sel_i ;
+
+input [3:0] wb_adr_i ;
+input [31:0] wb_dat_i ;
+
+output [31:0] wb_dat_o ;
+
+output wb_ack_o ;
+
+output wb_int_o ;
+
+input ps2_kbd_clk_pad_i,
+ ps2_kbd_data_pad_i ;
+
+output ps2_kbd_clk_pad_o,
+ ps2_kbd_data_pad_o,
+ ps2_kbd_clk_pad_oe_o,
+ ps2_kbd_data_pad_oe_o ;
+
+`ifdef PS2_AUX
+output wb_intb_o ;
+input ps2_aux_clk_pad_i,
+ ps2_aux_data_pad_i ;
+
+output ps2_aux_clk_pad_o,
+ ps2_aux_data_pad_o,
+ ps2_aux_clk_pad_oe_o,
+ ps2_aux_data_pad_oe_o ;
+
+assign ps2_aux_clk_pad_o = 1'b0 ;
+assign ps2_aux_data_pad_o = 1'b0 ;
+`endif
+
+wire rx_released,
+ rx_kbd_data_ready,
+ rx_translated_data_ready,
+ rx_kbd_read_wb,
+ rx_kbd_read_tt,
+ tx_kbd_write,
+ tx_kbd_write_ack,
+ tx_error_no_keyboard_ack,
+ ps2_ctrl_kbd_data_en_,
+ ps2_ctrl_kbd_clk_en_,
+ ps2_ctrl_kbd_clk,
+ inhibit_kbd_if ;
+
+wire [15:0] devide_reg;
+
+wire [7:0] rx_scan_code,
+ rx_translated_scan_code,
+ tx_kbd_data ;
+
+assign ps2_kbd_clk_pad_o = 1'b0 ;
+assign ps2_kbd_data_pad_o = 1'b0 ;
+
+ps2_io_ctrl i_ps2_io_ctrl_keyboard
+(
+ .clk_i (wb_clk_i),
+ .rst_i (wb_rst_i),
+ .ps2_ctrl_clk_en_i_ (ps2_ctrl_kbd_clk_en_),
+ .ps2_ctrl_data_en_i_ (ps2_ctrl_kbd_data_en_),
+ .ps2_clk_pad_i (ps2_kbd_clk_pad_i),
+ .ps2_clk_pad_oe_o (ps2_kbd_clk_pad_oe_o),
+ .ps2_data_pad_oe_o (ps2_kbd_data_pad_oe_o),
+ .inhibit_if_i (inhibit_kbd_if),
+ .ps2_ctrl_clk_o (ps2_ctrl_kbd_clk)
+);
+
+`ifdef PS2_AUX
+wire rx_aux_data_ready,
+ rx_aux_read,
+ tx_aux_write,
+ tx_aux_write_ack,
+ tx_error_no_aux_ack,
+ ps2_ctrl_aux_data_en_,
+ ps2_ctrl_aux_clk_en_,
+ ps2_ctrl_aux_clk,
+ inhibit_aux_if ;
+
+wire [7:0] rx_aux_data,
+ tx_aux_data ;
+
+ps2_io_ctrl i_ps2_io_ctrl_auxiliary
+(
+ .clk_i (wb_clk_i),
+ .rst_i (wb_rst_i),
+ .ps2_ctrl_clk_en_i_ (ps2_ctrl_aux_clk_en_),
+ .ps2_ctrl_data_en_i_ (ps2_ctrl_aux_data_en_),
+ .ps2_clk_pad_i (ps2_aux_clk_pad_i),
+ .ps2_clk_pad_oe_o (ps2_aux_clk_pad_oe_o),
+ .ps2_data_pad_oe_o (ps2_aux_data_pad_oe_o),
+ .inhibit_if_i (inhibit_aux_if),
+ .ps2_ctrl_clk_o (ps2_ctrl_aux_clk)
+);
+
+ps2_mouse #(`PS2_TIMER_60USEC_VALUE_PP, `PS2_TIMER_60USEC_BITS_PP, `PS2_TIMER_5USEC_VALUE_PP, `PS2_TIMER_5USEC_BITS_PP)
+i_ps2_mouse
+(
+ .clk (wb_clk_i),
+ .reset (wb_rst_i),
+ .ps2_clk_en_o_ (ps2_ctrl_aux_clk_en_),
+ .ps2_data_en_o_ (ps2_ctrl_aux_data_en_),
+ .ps2_clk_i (ps2_ctrl_aux_clk),
+ .ps2_data_i (ps2_aux_data_pad_i),
+ .rx_scan_code (rx_aux_data),
+ .rx_data_ready (rx_aux_data_ready),
+ .rx_read (rx_aux_read),
+ .tx_data (tx_aux_data),
+ .tx_write (tx_aux_write),
+ .tx_write_ack_o (tx_aux_write_ack),
+ .tx_error_no_ack (tx_error_no_aux_ack),
+ .devide_reg_i (devide_reg)
+);
+
+`endif
+
+ps2_keyboard #(`PS2_TIMER_60USEC_VALUE_PP, `PS2_TIMER_60USEC_BITS_PP, `PS2_TIMER_5USEC_VALUE_PP, `PS2_TIMER_5USEC_BITS_PP)
+i_ps2_keyboard
+(
+ .clk (wb_clk_i),
+ .reset (wb_rst_i),
+ .ps2_clk_en_o_ (ps2_ctrl_kbd_clk_en_),
+ .ps2_data_en_o_ (ps2_ctrl_kbd_data_en_),
+ .ps2_clk_i (ps2_ctrl_kbd_clk),
+ .ps2_data_i (ps2_kbd_data_pad_i),
+ .rx_released (rx_released),
+ .rx_scan_code (rx_scan_code),
+ .rx_data_ready (rx_kbd_data_ready),
+ .rx_read (rx_kbd_read_tt),
+ .tx_data (tx_kbd_data),
+ .tx_write (tx_kbd_write),
+ .tx_write_ack_o (tx_kbd_write_ack),
+ .tx_error_no_keyboard_ack (tx_error_no_keyboard_ack),
+ .translate (translate),
+ .devide_reg_i (devide_reg)
+);
+
+ps2_wb_if i_ps2_wb_if
+(
+ .wb_clk_i (wb_clk_i),
+ .wb_rst_i (wb_rst_i),
+ .wb_cyc_i (wb_cyc_i),
+ .wb_stb_i (wb_stb_i),
+ .wb_we_i (wb_we_i),
+ .wb_sel_i (wb_sel_i),
+ .wb_adr_i (wb_adr_i),
+ .wb_dat_i (wb_dat_i),
+ .wb_dat_o (wb_dat_o),
+ .wb_ack_o (wb_ack_o),
+
+ .wb_int_o (wb_int_o),
+
+ .devide_reg_o (devide_reg),
+
+ .rx_scancode_i (rx_translated_scan_code),
+ .rx_kbd_data_ready_i (rx_translated_data_ready),
+ .rx_kbd_read_o (rx_kbd_read_wb),
+ .tx_kbd_data_o (tx_kbd_data),
+ .tx_kbd_write_o (tx_kbd_write),
+ .tx_kbd_write_ack_i (tx_kbd_write_ack),
+ .translate_o (translate),
+ .ps2_kbd_clk_i (ps2_kbd_clk_pad_i),
+ .inhibit_kbd_if_o (inhibit_kbd_if)
+ `ifdef PS2_AUX
+ ,
+ .wb_intb_o (wb_intb_o),
+
+ .rx_aux_data_i (rx_aux_data),
+ .rx_aux_data_ready_i (rx_aux_data_ready),
+ .rx_aux_read_o (rx_aux_read),
+ .tx_aux_data_o (tx_aux_data),
+ .tx_aux_write_o (tx_aux_write),
+ .tx_aux_write_ack_i (tx_aux_write_ack),
+ .ps2_aux_clk_i (ps2_aux_clk_pad_i),
+ .inhibit_aux_if_o (inhibit_aux_if)
+ `endif
+) ;
+
+ps2_translation_table i_ps2_translation_table
+(
+ .reset_i (wb_rst_i),
+ .clock_i (wb_clk_i),
+ .translate_i (translate),
+ .code_i (rx_scan_code),
+ .code_o (rx_translated_scan_code),
+ .address_i (8'h00),
+ .data_i (8'h00),
+ .we_i (1'b0),
+ .re_i (1'b0),
+ .data_o (),
+ .rx_data_ready_i (rx_kbd_data_ready),
+ .rx_translated_data_ready_o (rx_translated_data_ready),
+ .rx_read_i (rx_kbd_read_wb),
+ .rx_read_o (rx_kbd_read_tt),
+ .rx_released_i (rx_released)
+) ;
+
+endmodule // ps2_top
Index: verilog/ps2_translation_table.v
===================================================================
--- verilog/ps2_translation_table.v (nonexistent)
+++ verilog/ps2_translation_table.v (revision 51)
@@ -0,0 +1,290 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// ps2_translation_table.v ////
+//// ////
+//// This file is part of the "ps2" project ////
+//// http://www.opencores.org/cores/ps2/ ////
+//// ////
+//// Author(s): ////
+//// - mihad@opencores.org ////
+//// - Miha Dolenc ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+// Revision 1.3 2003/06/02 17:13:22 simons
+// resetall keyword removed. ifdef moved to a separated line.
+//
+// Revision 1.2 2002/04/09 13:21:15 mihad
+// Added mouse interface and everything for its handling, cleaned up some unused code
+//
+// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
+// Initial project import - working
+//
+//
+
+`include "ps2_defines.v"
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+module ps2_translation_table
+(
+ reset_i,
+ clock_i,
+ translate_i,
+ code_i,
+ code_o,
+ address_i,
+ data_i,
+ we_i,
+ re_i,
+ data_o,
+ rx_data_ready_i,
+ rx_translated_data_ready_o,
+ rx_read_i,
+ rx_read_o,
+ rx_released_i
+) ;
+
+input reset_i,
+ clock_i,
+ translate_i ;
+
+input [7:0] code_i ;
+output [7:0] code_o ;
+input [7:0] address_i ;
+input [7:0] data_i ;
+input we_i,
+ re_i ;
+
+output [7:0] data_o ;
+
+input rx_data_ready_i,
+ rx_read_i ;
+
+output rx_translated_data_ready_o ;
+output rx_read_o ;
+
+input rx_released_i ;
+
+wire translation_table_write_enable = we_i && (!translate_i || !rx_data_ready_i) ;
+wire [7:0] translation_table_address = ((we_i || re_i) && (!rx_data_ready_i || !translate_i)) ? address_i : code_i ;
+wire translation_table_enable = we_i || re_i || (translate_i && rx_data_ready_i) ;
+
+reg rx_translated_data_ready ;
+always@(posedge clock_i or posedge reset_i)
+begin
+ if ( reset_i )
+ rx_translated_data_ready <= #1 1'b0 ;
+ else if ( rx_read_i || !translate_i )
+ rx_translated_data_ready <= #1 1'b0 ;
+ else
+ rx_translated_data_ready <= #1 rx_data_ready_i ;
+end
+
+`ifdef PS2_RAMB4
+ `define PS2_RAM_SELECTED
+
+ wire [7:0] ram_out ;
+ RAMB4_S8
+ `ifdef SIM
+ #("ignore",
+ `PS2_TRANSLATION_TABLE_31_0,
+ `PS2_TRANSLATION_TABLE_63_32,
+ `PS2_TRANSLATION_TABLE_95_64,
+ `PS2_TRANSLATION_TABLE_127_96,
+ `PS2_TRANSLATION_TABLE_159_128,
+ `PS2_TRANSLATION_TABLE_191_160,
+ `PS2_TRANSLATION_TABLE_223_192,
+ `PS2_TRANSLATION_TABLE_255_224)
+ `endif
+ ps2_ram
+ (
+ .DO (ram_out),
+ .ADDR ({1'b0, translation_table_address}),
+ .DI (data_i),
+ .EN (translation_table_enable),
+ .CLK (clock_i),
+ .WE (translation_table_write_enable),
+ .RST (reset_i)
+ ) ;
+
+`endif
+
+`ifdef PS2_CONSTANTS_ROM
+ `define PS2_RAM_SELECTED
+
+ reg [32 * 8 - 1:0] ps2_32byte_constant ;
+ reg [7:0] ram_out ;
+
+ always@(translation_table_address)
+ begin
+ case (translation_table_address[7:5])
+ 3'b000:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_31_0 ;
+ 3'b001:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_63_32 ;
+ 3'b010:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_95_64 ;
+ 3'b011:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_127_96 ;
+ 3'b100:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_159_128 ;
+ 3'b101:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_191_160 ;
+ 3'b110:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_223_192 ;
+ 3'b111:ps2_32byte_constant = `PS2_TRANSLATION_TABLE_255_224 ;
+ endcase
+ end
+
+ always@(posedge clock_i or posedge reset_i)
+ begin
+ if ( reset_i )
+ ram_out <= #1 8'h0 ;
+ else if ( translation_table_enable )
+ begin:get_dat_out
+ reg [7:0] bit_num ;
+
+ bit_num = translation_table_address[4:0] << 3 ;
+
+ repeat(8)
+ begin
+ ram_out[bit_num % 8] <= #1 ps2_32byte_constant[bit_num] ;
+ bit_num = bit_num + 1'b1 ;
+ end
+ end
+ end
+
+`endif
+
+`ifdef PS2_RAM_SELECTED
+`else
+ `define PS2_RAM_SELECTED
+
+ reg [7:0] ps2_ram [0:255] ;
+ reg [7:0] ram_out ;
+
+ always@(posedge clock_i or posedge reset_i)
+ begin
+ if ( reset_i )
+ ram_out <= #1 8'h0 ;
+ else if ( translation_table_enable )
+ ram_out <= #1 ps2_ram[translation_table_address] ;
+ end
+
+ always@(posedge clock_i)
+ begin
+ if ( translation_table_write_enable )
+ ps2_ram[translation_table_address] <= #1 data_i ;
+ end
+
+ // synopsys translate_off
+ initial
+ begin:ps2_ram_init
+ integer i ;
+ reg [255:0] temp_init_val ;
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_31_0 ;
+
+ for ( i = 0 ; i <= 31 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_63_32 ;
+
+ for ( i = 32 ; i <= 63 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_95_64 ;
+
+ for ( i = 64 ; i <= 95 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_127_96 ;
+
+ for ( i = 96 ; i <= 127 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_159_128 ;
+
+ for ( i = 128 ; i <= 159 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_191_160 ;
+
+ for ( i = 160 ; i <= 191 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_223_192 ;
+
+ for ( i = 192 ; i <= 223 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+
+ temp_init_val = `PS2_TRANSLATION_TABLE_255_224 ;
+
+ for ( i = 224 ; i <= 255 ; i = i + 1 )
+ begin
+ ps2_ram[i] = temp_init_val[7:0] ;
+ temp_init_val = temp_init_val >> 8 ;
+ end
+ end
+
+ // synopsys translate_on
+
+`endif
+
+assign data_o = ram_out ;
+assign code_o = translate_i ? {(rx_released_i | ram_out[7]), ram_out[6:0]} : code_i ;
+assign rx_translated_data_ready_o = translate_i ? rx_translated_data_ready : rx_data_ready_i ;
+assign rx_read_o = rx_read_i ;
+
+`undef PS2_RAM_SELECTED
+
+endmodule //ps2_translation_table
Index: verilog/ps2_io_ctrl.v
===================================================================
--- verilog/ps2_io_ctrl.v (nonexistent)
+++ verilog/ps2_io_ctrl.v (revision 51)
@@ -0,0 +1,106 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// ps2_io_ctrl.v ////
+//// ////
+//// This file is part of the "ps2" project ////
+//// http://www.opencores.org/cores/ps2/ ////
+//// ////
+//// Author(s): ////
+//// - mihad@opencores.org ////
+//// - Miha Dolenc ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
+// Initial project import - working
+//
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+module ps2_io_ctrl
+(
+ clk_i,
+ rst_i,
+ ps2_ctrl_clk_en_i_,
+ ps2_ctrl_data_en_i_,
+ ps2_clk_pad_i,
+ ps2_clk_pad_oe_o,
+ ps2_data_pad_oe_o,
+ inhibit_if_i,
+ ps2_ctrl_clk_o
+);
+
+input clk_i,
+ rst_i,
+ ps2_ctrl_clk_en_i_,
+ ps2_ctrl_data_en_i_,
+ ps2_clk_pad_i,
+ inhibit_if_i ;
+
+output ps2_clk_pad_oe_o,
+ ps2_data_pad_oe_o,
+ ps2_ctrl_clk_o ;
+
+reg ps2_clk_pad_oe_o,
+ ps2_data_pad_oe_o ;
+
+always@(posedge clk_i or posedge rst_i)
+begin
+ if ( rst_i )
+ begin
+ ps2_clk_pad_oe_o <= #1 1'b0 ;
+ ps2_data_pad_oe_o <= #1 1'b0 ;
+ end
+ else
+ begin
+ ps2_clk_pad_oe_o <= #1 !ps2_ctrl_clk_en_i_ || inhibit_if_i ;
+ ps2_data_pad_oe_o <= #1 !ps2_ctrl_data_en_i_ ;
+ end
+end
+
+reg inhibit_if_previous ;
+always@(posedge clk_i or posedge rst_i)
+begin
+ if ( rst_i )
+ inhibit_if_previous <= #1 1'b1 ;
+ else
+ inhibit_if_previous <= #1 inhibit_if_i ;
+end
+
+assign ps2_ctrl_clk_o = ps2_clk_pad_i || ps2_clk_pad_oe_o && inhibit_if_previous ;
+endmodule // ps2_io_ctrl
Index: verilog/timescale.v
===================================================================
--- verilog/timescale.v (nonexistent)
+++ verilog/timescale.v (revision 51)
@@ -0,0 +1 @@
+`timescale 1ns/1ps
\ No newline at end of file