1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
/*
* PS2 Mouse Interface
* Copyright (C) 2010 Donna Polehn <dpolehn@verizon.net>
*
* This file is part of the Zet processor. This processor is free
* hardware; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software
* Foundation; either version 3, or (at your option) any later version.
*
* Zet is distrubuted 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 General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Zet; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
module ps2_mouse (
input clk, // Clock Input
input reset, // Reset Input
inout ps2_clk, // PS2 Clock, Bidirectional
inout ps2_dat, // PS2 Data, Bidirectional
input [7:0] the_command, // Command to send to mouse
input send_command, // Signal to send
output command_was_sent, // Signal command finished sending
output error_communication_timed_out,
output [7:0] received_data, // Received data
output received_data_en, // If 1 - new data has been received
output start_receiving_data,
output wait_for_incoming_data
);
// --------------------------------------------------------------------
// Internal wires and registers Declarations
// --------------------------------------------------------------------
wire ps2_clk_posedge; // Internal Wires
wire ps2_clk_negedge;
reg [7:0] idle_counter; // Internal Registers
reg ps2_clk_reg;
reg ps2_data_reg;
reg last_ps2_clk;
reg [2:0] ns_ps2_transceiver; // State Machine Registers
reg [2:0] s_ps2_transceiver;
// --------------------------------------------------------------------
// Constant Declarations
// --------------------------------------------------------------------
localparam PS2_STATE_0_IDLE = 3'h0, // states
PS2_STATE_1_DATA_IN = 3'h1,
PS2_STATE_2_COMMAND_OUT = 3'h2,
PS2_STATE_3_END_TRANSFER = 3'h3,
PS2_STATE_4_END_DELAYED = 3'h4;
// --------------------------------------------------------------------
// Finite State Machine(s)
// --------------------------------------------------------------------
always @(posedge clk) begin
if(reset == 1'b1) s_ps2_transceiver <= PS2_STATE_0_IDLE;
else s_ps2_transceiver <= ns_ps2_transceiver;
end
always @(*) begin
ns_ps2_transceiver = PS2_STATE_0_IDLE; // Defaults
case (s_ps2_transceiver)
PS2_STATE_0_IDLE:
begin
if((idle_counter == 8'hFF) && (send_command == 1'b1))
ns_ps2_transceiver = PS2_STATE_2_COMMAND_OUT;
else if ((ps2_data_reg == 1'b0) && (ps2_clk_posedge == 1'b1))
ns_ps2_transceiver = PS2_STATE_1_DATA_IN;
else ns_ps2_transceiver = PS2_STATE_0_IDLE;
end
PS2_STATE_1_DATA_IN:
begin
// if((received_data_en == 1'b1) && (ps2_clk_posedge == 1'b1))
if((received_data_en == 1'b1)) ns_ps2_transceiver = PS2_STATE_0_IDLE;
else ns_ps2_transceiver = PS2_STATE_1_DATA_IN;
end
PS2_STATE_2_COMMAND_OUT:
begin
if((command_was_sent == 1'b1) || (error_communication_timed_out == 1'b1))
ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER;
else ns_ps2_transceiver = PS2_STATE_2_COMMAND_OUT;
end
PS2_STATE_3_END_TRANSFER:
begin
if(send_command == 1'b0) ns_ps2_transceiver = PS2_STATE_0_IDLE;
else if((ps2_data_reg == 1'b0) && (ps2_clk_posedge == 1'b1))
ns_ps2_transceiver = PS2_STATE_4_END_DELAYED;
else ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER;
end
PS2_STATE_4_END_DELAYED:
begin
if(received_data_en == 1'b1) begin
if(send_command == 1'b0) ns_ps2_transceiver = PS2_STATE_0_IDLE;
else ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER;
end
else ns_ps2_transceiver = PS2_STATE_4_END_DELAYED;
end
default:
ns_ps2_transceiver = PS2_STATE_0_IDLE;
endcase
end
// --------------------------------------------------------------------
// Sequential logic
// --------------------------------------------------------------------
always @(posedge clk) begin
if(reset == 1'b1) begin
last_ps2_clk <= 1'b1;
ps2_clk_reg <= 1'b1;
ps2_data_reg <= 1'b1;
end
else begin
last_ps2_clk <= ps2_clk_reg;
ps2_clk_reg <= ps2_clk;
ps2_data_reg <= ps2_dat;
end
end
always @(posedge clk) begin
if(reset == 1'b1) idle_counter <= 6'h00;
else if((s_ps2_transceiver == PS2_STATE_0_IDLE) && (idle_counter != 8'hFF))
idle_counter <= idle_counter + 6'h01;
else if (s_ps2_transceiver != PS2_STATE_0_IDLE)
idle_counter <= 6'h00;
end
// --------------------------------------------------------------------
// Combinational logic
// --------------------------------------------------------------------
assign ps2_clk_posedge = ((ps2_clk_reg == 1'b1) && (last_ps2_clk == 1'b0)) ? 1'b1 : 1'b0;
assign ps2_clk_negedge = ((ps2_clk_reg == 1'b0) && (last_ps2_clk == 1'b1)) ? 1'b1 : 1'b0;
assign start_receiving_data = (s_ps2_transceiver == PS2_STATE_1_DATA_IN);
assign wait_for_incoming_data = (s_ps2_transceiver == PS2_STATE_3_END_TRANSFER);
// --------------------------------------------------------------------
// Internal Modules
// --------------------------------------------------------------------
ps2_mouse_cmdout mouse_cmdout (
.clk (clk), // Inputs
.reset (reset),
.the_command (the_command),
.send_command (send_command),
.ps2_clk_posedge (ps2_clk_posedge),
.ps2_clk_negedge (ps2_clk_negedge),
.ps2_clk (ps2_clk), // Bidirectionals
.ps2_dat (ps2_dat),
.command_was_sent (command_was_sent), // Outputs
.error_communication_timed_out (error_communication_timed_out)
);
ps2_mouse_datain mouse_datain (
.clk (clk), // Inputs
.reset (reset),
.wait_for_incoming_data (wait_for_incoming_data),
.start_receiving_data (start_receiving_data),
.ps2_clk_posedge (ps2_clk_posedge),
.ps2_clk_negedge (ps2_clk_negedge),
.ps2_data (ps2_data_reg),
.received_data (received_data), // Outputs
.received_data_en (received_data_en)
);
endmodule
|