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

Subversion Repositories ps2

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 12 to Rev 13
    Reverse comparison

Rev 12 → Rev 13

/trunk/rtl/verilog/ps2_io_ctrl.v
43,7 → 43,10
// 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"
53,51 → 56,51
(
clk_i,
rst_i,
ps2_ctrl_kbd_clk_en_i_,
ps2_ctrl_kbd_data_en_i_,
ps2_kbd_clk_pad_i,
ps2_kbd_clk_pad_oe_o,
ps2_kbd_data_pad_oe_o,
inhibit_kbd_if_i,
ps2_ctrl_kbd_clk_o
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_kbd_clk_en_i_,
ps2_ctrl_kbd_data_en_i_,
ps2_kbd_clk_pad_i,
inhibit_kbd_if_i ;
ps2_ctrl_clk_en_i_,
ps2_ctrl_data_en_i_,
ps2_clk_pad_i,
inhibit_if_i ;
 
output ps2_kbd_clk_pad_oe_o,
ps2_kbd_data_pad_oe_o,
ps2_ctrl_kbd_clk_o ;
output ps2_clk_pad_oe_o,
ps2_data_pad_oe_o,
ps2_ctrl_clk_o ;
 
reg ps2_kbd_clk_pad_oe_o,
ps2_kbd_data_pad_oe_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_kbd_clk_pad_oe_o <= #1 1'b0 ;
ps2_kbd_data_pad_oe_o <= #1 1'b0 ;
ps2_clk_pad_oe_o <= #1 1'b0 ;
ps2_data_pad_oe_o <= #1 1'b0 ;
end
else
begin
ps2_kbd_clk_pad_oe_o <= #1 !ps2_ctrl_kbd_clk_en_i_ || inhibit_kbd_if_i ;
ps2_kbd_data_pad_oe_o <= #1 !ps2_ctrl_kbd_data_en_i_ ;
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_kbd_if_previous ;
reg inhibit_if_previous ;
always@(posedge clk_i or posedge rst_i)
begin
if ( rst_i )
inhibit_kbd_if_previous <= #1 1'b1 ;
inhibit_if_previous <= #1 1'b1 ;
else
inhibit_kbd_if_previous <= #1 inhibit_kbd_if_i ;
inhibit_if_previous <= #1 inhibit_if_i ;
end
 
assign ps2_ctrl_kbd_clk_o = ps2_kbd_clk_pad_i || ps2_kbd_clk_pad_oe_o && inhibit_kbd_if_previous ;
assign ps2_ctrl_clk_o = ps2_clk_pad_i || ps2_clk_pad_oe_o && inhibit_if_previous ;
endmodule // ps2_io_ctrl
/trunk/rtl/verilog/ps2_defines.v
43,12 → 43,15
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// 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_RAMB4
`define PS2_TRANSLATION_TABLE_31_0 256'h5b03111e1f2c71665a02101d702a386559290f3e40424464583c3b3d3f4143ff
`define PS2_TRANSLATION_TABLE_63_32 256'h5f0908162432726a5e071522233031695d061314212f39685c040512202d2e67
`define PS2_TRANSLATION_TABLE_95_64 256'h76632b751b1c363a6e620d1a7428736d610c19272635346c600a0b181725336b
58,9 → 61,11
`define PS2_TRANSLATION_TABLE_223_192 256'hdfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0
`define PS2_TRANSLATION_TABLE_255_224 256'hfffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0
 
`define PS2_TIMER_60USEC_VALUE_PP 1920 // Number of sys_clks for 60usec.
`define PS2_TIMER_60USEC_VALUE_PP 1500 // Number of sys_clks for 60usec.
`define PS2_TIMER_60USEC_BITS_PP 11 // Number of bits needed for timer
`define PS2_TIMER_5USEC_VALUE_PP 160 // Number of sys_clks for debounce
`define PS2_TIMER_5USEC_BITS_PP 8 // Number of bits needed for timer
`define PS2_TIMER_5USEC_VALUE_PP 125 // Number of sys_clks for debounce
`define PS2_TIMER_5USEC_BITS_PP 7 // Number of bits needed for timer
 
//`define PS2_AUX
 
//`define SIM
/trunk/rtl/verilog/ps2_keyboard.v
1,710 → 1,536
//-------------------------------------------------------------------------------------
//
// 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
`define EXTEND_CODE 16'hE0
`define RELEASE_CODE 16'hF0
`define LEFT_SHIFT 16'h12
`define RIGHT_SHIFT 16'h59
 
 
module ps2_keyboard (
clk,
reset,
ps2_clk_en_o_,
ps2_data_en_o_,
ps2_clk_i,
ps2_data_i,
rx_extended,
rx_released,
rx_shift_key_on,
rx_scan_code,
rx_ascii,
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
);
 
// 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
parameter TRAP_SHIFT_KEYS_PP = 0; // Default: No shift key trap.
 
// 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_extended;
output rx_released;
output rx_shift_key_on;
output [7:0] rx_scan_code;
output [7:0] rx_ascii;
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 ;
 
reg rx_extended;
reg rx_released;
reg [7:0] rx_scan_code;
reg [7:0] rx_ascii;
reg rx_data_ready;
reg tx_error_no_keyboard_ack;
 
// Internal signal declarations
wire timer_60usec_done;
wire timer_5usec_done;
wire extended;
wire released;
wire shift_key_on;
 
// 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;
wire [11:0] shift_key_plus_code;
 
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 [7:0] ascii; // "REG" type only because a case statement is used.
reg left_shift_key;
reg right_shift_key;
reg hold_extended; // Holds prior value, cleared at rx_output_strobe
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.
 
//--------------------------------------------------------------------------
// 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_s <= ps2_clk_i;
ps2_data_s <= ps2_data_i;
end
 
// State register
always @(posedge clk)
begin : m1_state_register
if (reset) m1_state <= m1_rx_clk_h;
else m1_state <= 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;
ps2_data_hi_z <= 1;
tx_error_no_keyboard_ack <= 0;
enable_timer_60usec <= 0;
enable_timer_5usec <= 0;
 
case (m1_state)
 
m1_rx_clk_h :
begin
enable_timer_60usec <= 1;
if (tx_write) m1_next_state <= m1_tx_reset_timer;
else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
else m1_next_state <= m1_rx_clk_h;
end
m1_rx_falling_edge_marker :
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_rx_clk_l;
end
 
m1_rx_rising_edge_marker :
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_rx_clk_h;
end
 
 
m1_rx_clk_l :
begin
enable_timer_60usec <= 1;
if (tx_write) m1_next_state <= m1_tx_reset_timer;
else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
else m1_next_state <= m1_rx_clk_l;
end
 
m1_tx_reset_timer:
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_tx_force_clk_l;
end
 
m1_tx_force_clk_l :
begin
enable_timer_60usec <= 1;
ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
else m1_next_state <= m1_tx_force_clk_l;
end
 
m1_tx_first_wait_clk_h :
begin
enable_timer_5usec <= 1;
ps2_data_hi_z <= 0; // Start bit.
if (~ps2_clk_s && timer_5usec_done)
m1_next_state <= m1_tx_clk_l;
else
m1_next_state <= 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 <= 0;
if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
else m1_next_state <= m1_tx_first_wait_clk_l;
end
 
m1_tx_wait_clk_h :
begin
enable_timer_5usec <= 1;
ps2_data_hi_z <= q[0];
if (ps2_clk_s && timer_5usec_done)
m1_next_state <= m1_tx_rising_edge_marker;
else
m1_next_state <= m1_tx_wait_clk_h;
end
 
m1_tx_rising_edge_marker :
begin
ps2_data_hi_z <= q[0];
m1_next_state <= m1_tx_clk_h;
end
 
m1_tx_clk_h :
begin
ps2_data_hi_z <= q[0];
if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack;
else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
else m1_next_state <= m1_tx_clk_h;
end
 
m1_tx_clk_l :
begin
ps2_data_hi_z <= q[0];
if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
else m1_next_state <= m1_tx_clk_l;
end
 
m1_tx_wait_keyboard_ack :
begin
if (~ps2_clk_s && ps2_data_s)
m1_next_state <= m1_tx_error_no_keyboard_ack;
else if (~ps2_clk_s && ~ps2_data_s)
m1_next_state <= m1_tx_done_recovery;
else m1_next_state <= m1_tx_wait_keyboard_ack;
end
 
m1_tx_done_recovery :
begin
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
else m1_next_state <= m1_tx_done_recovery;
end
 
m1_tx_error_no_keyboard_ack :
begin
tx_error_no_keyboard_ack <= 1;
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
else m1_next_state <= m1_tx_error_no_keyboard_ack;
end
 
default : m1_next_state <= m1_rx_clk_h;
endcase
end
 
// State register
always @(posedge clk)
begin : m2_state_register
if (reset) m2_state <= m2_rx_data_ready_ack;
else m2_state <= 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'b0;
if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
else m2_next_state <= m2_rx_data_ready_ack;
end
m2_rx_data_ready:
begin
rx_data_ready <= 1'b1;
if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
else m2_next_state <= m2_rx_data_ready;
end
default : m2_next_state <= 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_keyboard_ack) // After tx is done.
) bit_count <= 0; // normal reset
else if (timer_60usec_done
&& (m1_state == m1_rx_clk_h)
&& (ps2_clk_s)
) bit_count <= 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 <= 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 <= 0;
else if (tx_write_ack_o) q <= {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 <= {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 <= 0;
else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1;
end
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1));
 
// This is the 5usec timer counter
always @(posedge clk)
begin
if (~enable_timer_5usec) timer_5usec_count <= 0;
else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
end
assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 1);
 
 
// Create the signals which indicate special scan codes received.
// These are the "unlatched versions."
`ifdef PS2_TRAP_EXTENDED
assign extended = (q[8:1] == `EXTEND_CODE) && rx_shifting_done && translate ;
`else
assign extended = 1'b0 ;
`endif
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)
begin
if (reset || rx_output_event)
begin
hold_extended <= 0;
hold_released <= 0;
end
else
begin
if (rx_shifting_done && extended) hold_extended <= 1;
if (rx_shifting_done && released) hold_released <= 1;
end
end
 
 
// These bits contain the status of the two shift keys
always @(posedge clk)
begin
if (reset) left_shift_key <= 0;
else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && ~hold_released)
left_shift_key <= 1;
else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && hold_released)
left_shift_key <= 0;
end
 
always @(posedge clk)
begin
if (reset) right_shift_key <= 0;
else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && ~hold_released)
right_shift_key <= 1;
else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && hold_released)
right_shift_key <= 0;
end
 
assign rx_shift_key_on = left_shift_key || right_shift_key;
 
// Output the special scan code flags, the scan code and the ascii
always @(posedge clk)
begin
if (reset)
begin
rx_extended <= 0;
rx_released <= 0;
rx_scan_code <= 0;
rx_ascii <= 0;
end
else if (rx_output_strobe)
begin
rx_extended <= hold_extended;
rx_released <= hold_released;
rx_scan_code <= q[8:1];
rx_ascii <= ascii;
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
&& ~extended
&& ~released
);
 
assign rx_output_strobe = (rx_shifting_done
&& ~extended
&& ~released
&& ( (TRAP_SHIFT_KEYS_PP == 0)
|| ( (q[8:1] != `RIGHT_SHIFT)
&&(q[8:1] != `LEFT_SHIFT)
)
)
);
 
// This part translates the scan code into an ASCII value...
// Only the ASCII codes which I considered important have been included.
// if you want more, just add the appropriate case statement lines...
// (You will need to know the keyboard scan codes you wish to assign.)
// The entries are listed in ascending order of ASCII value.
assign shift_key_plus_code = {3'b0,rx_shift_key_on,q[8:1]};
always @(shift_key_plus_code)
begin
casez (shift_key_plus_code)
12'h?66 : ascii <= 8'h08; // Backspace ("backspace" key)
12'h?0d : ascii <= 8'h09; // Horizontal Tab
12'h?5a : ascii <= 8'h0d; // Carriage return ("enter" key)
12'h?76 : ascii <= 8'h1b; // Escape ("esc" key)
12'h?29 : ascii <= 8'h20; // Space
12'h116 : ascii <= 8'h21; // !
12'h152 : ascii <= 8'h22; // "
12'h126 : ascii <= 8'h23; // #
12'h125 : ascii <= 8'h24; // $
12'h12e : ascii <= 8'h25; // %
12'h13d : ascii <= 8'h26; // &
12'h052 : ascii <= 8'h27; // '
12'h146 : ascii <= 8'h28; // (
12'h145 : ascii <= 8'h29; // )
12'h13e : ascii <= 8'h2a; // *
12'h155 : ascii <= 8'h2b; // +
12'h041 : ascii <= 8'h2c; // ,
12'h04e : ascii <= 8'h2d; // -
12'h049 : ascii <= 8'h2e; // .
12'h04a : ascii <= 8'h2f; // /
12'h045 : ascii <= 8'h30; // 0
12'h016 : ascii <= 8'h31; // 1
12'h01e : ascii <= 8'h32; // 2
12'h026 : ascii <= 8'h33; // 3
12'h025 : ascii <= 8'h34; // 4
12'h02e : ascii <= 8'h35; // 5
12'h036 : ascii <= 8'h36; // 6
12'h03d : ascii <= 8'h37; // 7
12'h03e : ascii <= 8'h38; // 8
12'h046 : ascii <= 8'h39; // 9
12'h14c : ascii <= 8'h3a; // :
12'h04c : ascii <= 8'h3b; // ;
12'h141 : ascii <= 8'h3c; // <
12'h055 : ascii <= 8'h3d; // =
12'h149 : ascii <= 8'h3e; // >
12'h14a : ascii <= 8'h3f; // ?
12'h11e : ascii <= 8'h40; // @
12'h11c : ascii <= 8'h41; // A
12'h132 : ascii <= 8'h42; // B
12'h121 : ascii <= 8'h43; // C
12'h123 : ascii <= 8'h44; // D
12'h124 : ascii <= 8'h45; // E
12'h12b : ascii <= 8'h46; // F
12'h134 : ascii <= 8'h47; // G
12'h133 : ascii <= 8'h48; // H
12'h143 : ascii <= 8'h49; // I
12'h13b : ascii <= 8'h4a; // J
12'h142 : ascii <= 8'h4b; // K
12'h14b : ascii <= 8'h4c; // L
12'h13a : ascii <= 8'h4d; // M
12'h131 : ascii <= 8'h4e; // N
12'h144 : ascii <= 8'h4f; // O
12'h14d : ascii <= 8'h50; // P
12'h115 : ascii <= 8'h51; // Q
12'h12d : ascii <= 8'h52; // R
12'h11b : ascii <= 8'h53; // S
12'h12c : ascii <= 8'h54; // T
12'h13c : ascii <= 8'h55; // U
12'h12a : ascii <= 8'h56; // V
12'h11d : ascii <= 8'h57; // W
12'h122 : ascii <= 8'h58; // X
12'h135 : ascii <= 8'h59; // Y
12'h11a : ascii <= 8'h5a; // Z
12'h054 : ascii <= 8'h5b; // [
12'h05d : ascii <= 8'h5c; // \
12'h05b : ascii <= 8'h5d; // ]
12'h136 : ascii <= 8'h5e; // ^
12'h14e : ascii <= 8'h5f; // _
12'h00e : ascii <= 8'h60; // `
12'h01c : ascii <= 8'h61; // a
12'h032 : ascii <= 8'h62; // b
12'h021 : ascii <= 8'h63; // c
12'h023 : ascii <= 8'h64; // d
12'h024 : ascii <= 8'h65; // e
12'h02b : ascii <= 8'h66; // f
12'h034 : ascii <= 8'h67; // g
12'h033 : ascii <= 8'h68; // h
12'h043 : ascii <= 8'h69; // i
12'h03b : ascii <= 8'h6a; // j
12'h042 : ascii <= 8'h6b; // k
12'h04b : ascii <= 8'h6c; // l
12'h03a : ascii <= 8'h6d; // m
12'h031 : ascii <= 8'h6e; // n
12'h044 : ascii <= 8'h6f; // o
12'h04d : ascii <= 8'h70; // p
12'h015 : ascii <= 8'h71; // q
12'h02d : ascii <= 8'h72; // r
12'h01b : ascii <= 8'h73; // s
12'h02c : ascii <= 8'h74; // t
12'h03c : ascii <= 8'h75; // u
12'h02a : ascii <= 8'h76; // v
12'h01d : ascii <= 8'h77; // w
12'h022 : ascii <= 8'h78; // x
12'h035 : ascii <= 8'h79; // y
12'h01a : ascii <= 8'h7a; // z
12'h154 : ascii <= 8'h7b; // {
12'h15d : ascii <= 8'h7c; // |
12'h15b : ascii <= 8'h7d; // }
12'h10e : ascii <= 8'h7e; // ~
12'h?71 : ascii <= 8'h7f; // (Delete OR DEL on numeric keypad)
default : ascii <= 8'h2e; // '.' used for unlisted characters.
endcase
end
 
 
endmodule
 
//`undefine TOTAL_BITS
//`undefine EXTEND_CODE
//`undefine RELEASE_CODE
//`undefine LEFT_SHIFT
//`undefine RIGHT_SHIFT
 
//-------------------------------------------------------------------------------------
//
// 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
`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
);
 
// 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 ;
 
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.
 
//--------------------------------------------------------------------------
// 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_s <= ps2_clk_i;
ps2_data_s <= ps2_data_i;
end
 
// State register
always @(posedge clk)
begin : m1_state_register
if (reset) m1_state <= m1_rx_clk_h;
else m1_state <= 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;
ps2_data_hi_z <= 1;
tx_error_no_keyboard_ack <= 0;
enable_timer_60usec <= 0;
enable_timer_5usec <= 0;
 
case (m1_state)
 
m1_rx_clk_h :
begin
enable_timer_60usec <= 1;
if (tx_write) m1_next_state <= m1_tx_reset_timer;
else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
else m1_next_state <= m1_rx_clk_h;
end
 
m1_rx_falling_edge_marker :
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_rx_clk_l;
end
 
m1_rx_rising_edge_marker :
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_rx_clk_h;
end
 
 
m1_rx_clk_l :
begin
enable_timer_60usec <= 1;
if (tx_write) m1_next_state <= m1_tx_reset_timer;
else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
else m1_next_state <= m1_rx_clk_l;
end
 
m1_tx_reset_timer:
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_tx_force_clk_l;
end
 
m1_tx_force_clk_l :
begin
enable_timer_60usec <= 1;
ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
else m1_next_state <= m1_tx_force_clk_l;
end
 
m1_tx_first_wait_clk_h :
begin
enable_timer_5usec <= 1;
ps2_data_hi_z <= 0; // Start bit.
if (~ps2_clk_s && timer_5usec_done)
m1_next_state <= m1_tx_clk_l;
else
m1_next_state <= 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 <= 0;
if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
else m1_next_state <= m1_tx_first_wait_clk_l;
end
 
m1_tx_wait_clk_h :
begin
enable_timer_5usec <= 1;
ps2_data_hi_z <= q[0];
if (ps2_clk_s && timer_5usec_done)
m1_next_state <= m1_tx_rising_edge_marker;
else
m1_next_state <= m1_tx_wait_clk_h;
end
 
m1_tx_rising_edge_marker :
begin
ps2_data_hi_z <= q[0];
m1_next_state <= m1_tx_clk_h;
end
 
m1_tx_clk_h :
begin
ps2_data_hi_z <= q[0];
if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack;
else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
else m1_next_state <= m1_tx_clk_h;
end
 
m1_tx_clk_l :
begin
ps2_data_hi_z <= q[0];
if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
else m1_next_state <= m1_tx_clk_l;
end
 
m1_tx_wait_keyboard_ack :
begin
if (~ps2_clk_s && ps2_data_s)
m1_next_state <= m1_tx_error_no_keyboard_ack;
else if (~ps2_clk_s && ~ps2_data_s)
m1_next_state <= m1_tx_done_recovery;
else m1_next_state <= m1_tx_wait_keyboard_ack;
end
 
m1_tx_done_recovery :
begin
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
else m1_next_state <= m1_tx_done_recovery;
end
 
m1_tx_error_no_keyboard_ack :
begin
tx_error_no_keyboard_ack <= 1;
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
else m1_next_state <= m1_tx_error_no_keyboard_ack;
end
 
default : m1_next_state <= m1_rx_clk_h;
endcase
end
 
// State register
always @(posedge clk)
begin : m2_state_register
if (reset) m2_state <= m2_rx_data_ready_ack;
else m2_state <= 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'b0;
if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
else m2_next_state <= m2_rx_data_ready_ack;
end
m2_rx_data_ready:
begin
rx_data_ready <= 1'b1;
if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
else m2_next_state <= m2_rx_data_ready;
end
default : m2_next_state <= 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_keyboard_ack) // After tx is done.
) bit_count <= 0; // normal reset
else if (timer_60usec_done
&& (m1_state == m1_rx_clk_h)
&& (ps2_clk_s)
) bit_count <= 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 <= 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 <= 0;
else if (tx_write_ack_o) q <= {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 <= {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 <= 0;
else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1;
end
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1));
 
// This is the 5usec timer counter
always @(posedge clk)
begin
if (~enable_timer_5usec) timer_5usec_count <= 0;
else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
end
assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 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)
begin
if (reset || rx_output_event)
begin
hold_released <= 0;
end
else
begin
if (rx_shifting_done && released) hold_released <= 1;
end
end
 
// Output the special scan code flags, the scan code and the ascii
always @(posedge clk)
begin
if (reset)
begin
rx_released <= 0;
rx_scan_code <= 0;
end
else if (rx_output_strobe)
begin
rx_released <= hold_released;
rx_scan_code <= 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
 
/trunk/rtl/verilog/ps2_top.v
43,7 → 43,10
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
// Initial project import - working
//
//
 
`include "ps2_defines.v"
// synopsys translate_off
62,9 → 65,9
wb_dat_i,
wb_dat_o,
wb_ack_o,
wb_int_o,
 
wb_int_o,
 
ps2_kbd_clk_pad_i,
ps2_kbd_data_pad_i,
ps2_kbd_clk_pad_o,
71,6 → 74,17
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,
81,7 → 95,7
 
input [3:0] wb_sel_i ;
 
input [31:0]wb_adr_i,
input [31:0]wb_adr_i,
wb_dat_i ;
 
output [31:0] wb_dat_o ;
98,15 → 112,27
ps2_kbd_clk_pad_oe_o,
ps2_kbd_data_pad_oe_o ;
 
wire rx_extended,
rx_released,
rx_shift_key_on,
rx_data_ready,
`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_read_wb,
rx_read_tt,
tx_write,
tx_write_ack,
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_,
113,28 → 139,74
ps2_ctrl_kbd_clk,
inhibit_kbd_if ;
 
wire [7:0] rx_scan_code,
wire [7:0] rx_scan_code,
rx_translated_scan_code,
rx_ascii,
tx_data ;
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
ps2_io_ctrl i_ps2_io_ctrl_keyboard
(
.clk_i (wb_clk_i),
.rst_i (wb_rst_i),
.ps2_ctrl_kbd_clk_en_i_ (ps2_ctrl_kbd_clk_en_),
.ps2_ctrl_kbd_data_en_i_ (ps2_ctrl_kbd_data_en_),
.ps2_kbd_clk_pad_i (ps2_kbd_clk_pad_i),
.ps2_kbd_clk_pad_oe_o (ps2_kbd_clk_pad_oe_o),
.ps2_kbd_data_pad_oe_o (ps2_kbd_data_pad_oe_o),
.inhibit_kbd_if_i (inhibit_kbd_if),
.ps2_ctrl_kbd_clk_o (ps2_ctrl_kbd_clk)
.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)
);
 
ps2_keyboard #(`PS2_TIMER_60USEC_VALUE_PP, `PS2_TIMER_60USEC_BITS_PP, `PS2_TIMER_5USEC_VALUE_PP, `PS2_TIMER_5USEC_BITS_PP, 0)
`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)
);
 
`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),
143,16 → 215,13
.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_extended (rx_extended),
.rx_released (rx_released),
.rx_shift_key_on (rx_shift_key_on),
.rx_scan_code (rx_scan_code),
.rx_ascii (rx_ascii),
.rx_data_ready (rx_data_ready),
.rx_read (rx_read_tt),
.tx_data (tx_data),
.tx_write (tx_write),
.tx_write_ack_o (tx_write_ack),
.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)
);
169,18 → 238,31
.wb_dat_i (wb_dat_i),
.wb_dat_o (wb_dat_o),
.wb_ack_o (wb_ack_o),
 
.wb_int_o (wb_int_o),
 
.rx_scancode_i (rx_translated_scan_code),
.rx_data_ready_i (rx_translated_data_ready),
.rx_read_o (rx_read_wb),
.tx_data_o (tx_data),
.tx_write_o (tx_write),
.tx_write_ack_i (tx_write_ack),
.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_clk_i (ps2_kbd_clk_pad_i),
.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
195,12 → 277,11
.we_i (1'b0),
.re_i (1'b0),
.data_o (),
.rx_data_ready_i (rx_data_ready),
.rx_data_ready_i (rx_kbd_data_ready),
.rx_translated_data_ready_o (rx_translated_data_ready),
.rx_read_i (rx_read_wb),
.rx_read_o (rx_read_tt),
.rx_released_i (rx_released),
.rx_extended_i (rx_extended)
.rx_read_i (rx_kbd_read_wb),
.rx_read_o (rx_kbd_read_tt),
.rx_released_i (rx_released)
) ;
 
endmodule // ps2_top
/trunk/rtl/verilog/ps2_translation_table.v
43,7 → 43,10
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1 2002/02/18 16:16:56 mihad
// Initial project import - working
//
//
 
`include "ps2_defines.v"
 
67,7 → 70,6
rx_translated_data_ready_o,
rx_read_i,
rx_read_o,
rx_extended_i,
rx_released_i
) ;
 
90,8 → 92,7
output rx_translated_data_ready_o ;
output rx_read_o ;
 
input rx_extended_i,
rx_released_i ;
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 ;
110,17 → 111,17
 
`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_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
133,16 → 134,16
.WE (translation_table_write_enable),
.RST (reset_i)
) ;
 
`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 )
171,7 → 172,7
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] ;
179,15 → 180,15
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] ;
195,31 → 196,31
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] ;
236,6 → 237,6
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
`undef PS2_RAM_SELECTED
 
endmodule //ps2_translation_table
/trunk/rtl/verilog/ps2_wb_if.v
43,6 → 43,9
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// 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
//
70,18 → 73,31
wb_dat_i,
wb_dat_o,
wb_ack_o,
 
wb_int_o,
 
tx_write_ack_i,
tx_data_o,
tx_write_o,
tx_kbd_write_ack_i,
tx_kbd_data_o,
tx_kbd_write_o,
rx_scancode_i,
rx_data_ready_i,
rx_read_o,
rx_kbd_data_ready_i,
rx_kbd_read_o,
translate_o,
ps2_clk_i,
ps2_kbd_clk_i,
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,
105,17 → 121,17
output wb_int_o ;
reg wb_int_o ;
 
input tx_write_ack_i ;
input tx_kbd_write_ack_i ;
 
input [7:0] rx_scancode_i ;
input rx_data_ready_i ;
output rx_read_o ;
input rx_kbd_data_ready_i ;
output rx_kbd_read_o ;
 
output tx_write_o ;
output [7:0] tx_data_o ;
output tx_kbd_write_o ;
output [7:0] tx_kbd_data_o ;
 
output translate_o ;
input ps2_clk_i ;
input ps2_kbd_clk_i ;
 
output inhibit_kbd_if_o ;
 
122,21 → 138,55
reg [7:0] input_buffer,
output_buffer ;
 
assign tx_data_o = output_buffer ;
reg [7: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:24] ;
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_write_o = output_buffer_full ;
assign tx_kbd_write_o = output_buffer_full ;
 
wire system_flag ;
wire a2 = 1'b0 ;
wire kbd_inhibit = ps2_clk_i ;
wire mouse_output_buffer_full = 1'b0 ;
wire kbd_inhibit = ps2_kbd_clk_i ;
wire timeout = 1'b0 ;
wire perr = 1'b0 ;
 
wire [7:0] status_byte = {perr, timeout, mouse_output_buffer_full, kbd_inhibit, a2, system_flag, output_buffer_full, input_buffer_full} ;
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[2:0] == 3'h0) ;
160,16 → 210,26
begin
if ( wb_rst_i )
inhibit_kbd_if_o <= #1 1'b1 ;
else if ( ps2_clk_i && (rx_data_ready_i || enable1) )
else if ( ps2_kbd_clk_i && rx_kbd_data_ready_i && !enable1)
inhibit_kbd_if_o <= #1 1'b1 ;
else if ( !rx_data_ready_i && !enable1 )
else if ( !rx_kbd_data_ready_i || enable1 )
inhibit_kbd_if_o <= #1 1'b0 ;
 
end
 
wire interrupt2 = 1'b0 ;
wire enable2 = 1'b1 ;
`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} ;
200,7 → 260,7
if ( wb_rst_i )
current_command <= #1 8'h0 ;
else if ( send_command_reg )
current_command <= #1 wb_dat_i[31:24] ;
current_command <= #1 wb_dat_i_sampled ;
end
 
reg current_command_valid,
217,8 → 277,8
write_output_buffer_reg_previous <= #1 write_output_buffer_reg ;
end
 
wire invalidate_current_command =
current_command_valid &&
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) ) ||
233,7 → 293,7
current_command_valid <= #1 1'b0 ;
else if ( send_command_reg )
current_command_valid <= #1 1'b1 ;
 
end
 
reg write_command_byte ;
241,7 → 301,7
always@(
current_command or
command_byte or
write_output_buffer_reg_previous or
write_output_buffer_reg_previous or
current_command_valid or
output_buffer
)
266,7 → 326,7
current_command_returns_value = 1'b1 ;
current_command_output = 8'h00 ;
current_command_output_valid = 1'b1 ;
end
end
8'hA4:begin
current_command_returns_value = 1'b1 ;
current_command_output = 8'hF1 ;
278,13 → 338,17
8'hA6:begin
end
8'hA7:begin
end
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
current_command_output_valid = 1'b1 ;
`endif
end
8'hAA:begin
current_command_returns_value = 1'b1 ;
297,7 → 361,7
current_command_output_valid = 1'b1 ;
end
8'hAD:begin
end
end
8'hAE:begin
end
8'hAF:begin
305,7 → 369,7
current_command_output = 8'h00 ;
current_command_output_valid = 1'b1 ;
end
8'hC0:begin
8'hC0:begin
current_command_returns_value = 1'b1 ;
current_command_output = 8'hFF ;
current_command_output_valid = 1'b1 ;
330,6 → 394,11
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 ;
339,7 → 408,7
current_command_output = 8'hFF ;
current_command_output_valid = 1'b1 ;
end
endcase
endcase
end
 
reg cyc_i_previous ;
362,7 → 431,7
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)
391,18 → 460,30
begin
if ( wb_rst_i )
output_buffer_full <= #1 1'b0 ;
else if ( output_buffer_full && tx_write_ack_i)
output_buffer_full <= #1 1'b0 ;
else
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[31:24] ;
output_buffer <= #1 wb_dat_i_sampled ;
end
 
always@(posedge wb_clk_i or posedge wb_rst_i)
412,6 → 493,9
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
418,6 → 502,9
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
 
431,19 → 518,41
enable1 <= #1 1'b1 ;
else if ( write_command_byte )
enable1 <= #1 output_buffer[4] ;
 
end
 
wire write_input_buffer_from_command = current_command_valid && current_command_returns_value && current_command_output_valid ;
reg write_input_buffer_from_command_reg ;
`ifdef PS2_AUX
always@(posedge wb_clk_i or posedge wb_rst_i)
begin
if ( wb_rst_i )
write_input_buffer_from_command_reg <= #1 1'b0 ;
else
write_input_buffer_from_command_reg <= #1 write_input_buffer_from_command ;
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 )
450,10 → 559,22
input_buffer_full <= #1 1'b0 ;
else if ( read_input_buffer_reg )
input_buffer_full <= #1 1'b0 ;
else if ( (write_input_buffer_from_command && !write_input_buffer_from_command_reg) || (rx_data_ready_i && !enable1) )
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
461,33 → 582,74
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 && !write_input_buffer_from_command_reg)
else if ( write_input_buffer_from_command )
input_buffer_filled_from_command <= #1 1'b1 ;
end
 
reg rx_data_ready_reg ;
always@(posedge wb_clk_i or posedge wb_rst_i)
`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
if ( wb_rst_i )
rx_data_ready_reg <= #1 1'b0 ;
else if ( input_buffer_filled_from_command )
rx_data_ready_reg <= #1 1'b0 ;
else
rx_data_ready_reg <= #1 rx_data_ready_i ;
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
 
wire input_buffer_value_change = (rx_data_ready_i && !rx_data_ready_reg && !enable1) || (write_input_buffer_from_command && !write_input_buffer_from_command_reg) ;
`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 ( input_buffer_value_change )
input_buffer <= #1 current_command_valid && current_command_returns_value ? current_command_output : rx_scancode_i ;
else if ( load_input_buffer_value )
input_buffer <= #1 value_to_load_in_input_buffer ;
end
 
assign rx_read_o = enable1 || rx_data_ready_i && !input_buffer_filled_from_command && read_input_buffer_reg ;
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 )
495,7 → 657,27
else if ( read_input_buffer_reg || enable1 || !interrupt1)
wb_int_o <= #1 1'b0 ;
else
wb_int_o <= #1 input_buffer_full ;
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
/trunk/sim/rtl_sim/run/run_ps2_sim.scr
45,6 → 45,9
#// CVS Revision History
#//
#// $Log: not supported by cvs2svn $
#// Revision 1.2 2002/02/20 15:20:11 mihad
#// Little/big endian changes incorporated
#//
#// Revision 1.1.1.1 2002/02/18 16:16:55 mihad
#// Initial project import - working
#//
60,23 → 63,26
echo '-DEFINE "PS2_NUM_OF_EXTENDED_SCANCODES 38"' >> ./ncvlog.args
echo '-DEFINE "SIM"' >> ./ncvlog.args
 
if ( $# > 0 ) then
if ( $# == 1 ) then
switch ( $1 )
case xilinx:
echo '-DEFINE "XILINX"' >> ./ncvlog.args
breaksw
set current_par = 0
set output_waveform = 0
set xilinx = 0
while ( $current_par < $# )
@ current_par = $current_par + 1
switch ( $argv[$current_par] )
case xilinx:
echo '-DEFINE "XILINX"' >> ./ncvlog.args
@ xilinx = 1
breaksw
case wave:
@ output_waveform = 1
breaksw
default:
echo 'Unknown option "'$argv[$current_par]'"!'
exit
breaksw
endsw
end
 
default:
echo 'Unknown option "'$1'"!'
exit
breaksw
endsw
else
echo "Wrong number of arguments" ; exit
endif
endif
 
echo "-LOGFILE ../log/ncvlog.log" >> ./ncvlog.args
 
foreach filename ( `cat ../bin/rtl_file_list` )
87,14 → 93,10
echo "../../../bench/verilog/"$filename >> ./ncvlog.args
end
 
if ( $# > 0 ) then
switch( $1 )
case xilinx:
foreach filename ( `cat ../bin/xilinx_file_list` )
echo "../../../../xilinx_blocks/"$filename >> ./ncvlog.args
end
breaksw
endsw
if ( $xilinx ) then
foreach filename ( `cat ../bin/xilinx_file_list` )
echo "../../../../xilinx_blocks/"$filename >> ./ncvlog.args
end
endif
 
ncvlog -f ./ncvlog.args
108,12 → 110,8
echo "-ACCESS +RWC" >> ./ncelab.args
echo "worklib.ps2_test_bench" >> ./ncelab.args
 
if ( $# > 0 ) then
switch ( $1 )
case xilinx:
echo "worklib.glbl" >> ./ncelab.args
breaksw
endsw
if ( $xilinx ) then
echo "worklib.glbl" >> ./ncelab.args
endif
 
ncelab -f ./ncelab.args
126,9 → 124,14
echo "-LOGFILE ../log/ncsim.log" >> ./ncsim.args
echo "worklib.ps2_test_bench:rtl" >> ./ncsim.args
 
echo "database -open waves -shm -into ../out/waves.shm" > ./ncsim.tcl
echo "probe -create -database waves ps2_test_bench -shm -all -depth all" >> ./ncsim.tcl
echo "run" >> ./ncsim.tcl
if ( $output_waveform ) then
echo "database -open waves -shm -into ../out/waves.shm" > ./ncsim.tcl
echo "probe -create -database waves ps2_test_bench -shm -all -depth all" >> ./ncsim.tcl
echo "run" >> ./ncsim.tcl
else
echo "run" > ./ncsim.tcl
endif
 
echo "quit" >> ./ncsim.tcl
 
ncsim -f ./ncsim.args
/trunk/sim/rtl_sim/bin/rtl_file_list
1,4 → 1,5
ps2_keyboard.v
ps2_mouse.v
ps2_top.v
ps2_translation_table.v
ps2_wb_if.v

powered by: WebSVN 2.1.0

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