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 30 to Rev 31
    Reverse comparison

Rev 30 → Rev 31

/tags/asyst_3/rtl/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
tags/asyst_3/rtl/verilog/ps2_mouse.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/asyst_3/rtl/verilog/ps2_wb_if.v =================================================================== --- tags/asyst_3/rtl/verilog/ps2_wb_if.v (nonexistent) +++ tags/asyst_3/rtl/verilog/ps2_wb_if.v (revision 31) @@ -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: tags/asyst_3/rtl/verilog/ps2_keyboard.v =================================================================== --- tags/asyst_3/rtl/verilog/ps2_keyboard.v (nonexistent) +++ tags/asyst_3/rtl/verilog/ps2_keyboard.v (revision 31) @@ -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 +
tags/asyst_3/rtl/verilog/ps2_keyboard.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/asyst_3/rtl/verilog/ps2_defines.v =================================================================== --- tags/asyst_3/rtl/verilog/ps2_defines.v (nonexistent) +++ tags/asyst_3/rtl/verilog/ps2_defines.v (revision 31) @@ -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
tags/asyst_3/rtl/verilog/ps2_defines.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/asyst_3/rtl/verilog/ps2_top.v =================================================================== --- tags/asyst_3/rtl/verilog/ps2_top.v (nonexistent) +++ tags/asyst_3/rtl/verilog/ps2_top.v (revision 31) @@ -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: tags/asyst_3/rtl/verilog/ps2_translation_table.v =================================================================== --- tags/asyst_3/rtl/verilog/ps2_translation_table.v (nonexistent) +++ tags/asyst_3/rtl/verilog/ps2_translation_table.v (revision 31) @@ -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: tags/asyst_3/rtl/verilog/ps2_io_ctrl.v =================================================================== --- tags/asyst_3/rtl/verilog/ps2_io_ctrl.v (nonexistent) +++ tags/asyst_3/rtl/verilog/ps2_io_ctrl.v (revision 31) @@ -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: tags/asyst_3/rtl/verilog/timescale.v =================================================================== --- tags/asyst_3/rtl/verilog/timescale.v (nonexistent) +++ tags/asyst_3/rtl/verilog/timescale.v (revision 31) @@ -0,0 +1 @@ +`timescale 1ns/1ps \ No newline at end of file

powered by: WebSVN 2.1.0

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