1//*****************************************************************************
2//*                                                                           *
3//* Module:       Altera_UP_PS2_Command_Out                                   *
4//* Description:                                                              *
5//*      This module sends commands out to the PS2 core.                      *
6//*                                                                           *
7//*****************************************************************************/
8
9module Altera_UP_PS2_Command_Out (
10
11    // Inputs
12    clk,
13    reset,
14    the_command,
15    send_command,
16    ps2_clk_posedge,
17    ps2_clk_negedge,
18
19    // Bidirectionals
20    PS2_CLK,
21    PS2_DAT,
22
23    // Outputs
24    command_was_sent,
25    error_communication_timed_out
26);
27
28/*****************************************************************************
29 *                           Parameter Declarations                          *
30 *****************************************************************************/
31
32// Timing info for initiating Host-to-Device communication
33//   when using a 50MHz system clock
34parameter    CLOCK_CYCLES_FOR_101US         = 5050;
35parameter    NUMBER_OF_BITS_FOR_101US       = 13;
36parameter    COUNTER_INCREMENT_FOR_101US    = 13'h0001;
37
38// Timing info for start of transmission error
39//   when using a 50MHz system clock
40parameter    CLOCK_CYCLES_FOR_15MS          = 750000;
41parameter    NUMBER_OF_BITS_FOR_15MS        = 20;
42parameter    COUNTER_INCREMENT_FOR_15MS     = 20'h00001;
43
44// Timing info for sending data error
45//   when using a 50MHz system clock
46parameter    CLOCK_CYCLES_FOR_2MS           = 100000;
47parameter    NUMBER_OF_BITS_FOR_2MS         = 17;
48parameter    COUNTER_INCREMENT_FOR_2MS      = 17'h00001;
49
50/*****************************************************************************
51 *                             Port Declarations                             *
52 *****************************************************************************/
53
54input           clk;
55input           reset;
56input   [7:0]   the_command;
57input           send_command;
58input           ps2_clk_posedge;
59input           ps2_clk_negedge;
60inout           PS2_CLK;
61inout           PS2_DAT;
62output  reg     command_was_sent;
63output  reg     error_communication_timed_out;
64
65/*****************************************************************************
66 *                           Constant Declarations                           *
67 *****************************************************************************/
68// states
69parameter   PS2_STATE_0_IDLE                        = 3'h0,
70            PS2_STATE_1_INITIATE_COMMUNICATION      = 3'h1,
71            PS2_STATE_2_WAIT_FOR_CLOCK              = 3'h2,
72            PS2_STATE_3_TRANSMIT_DATA               = 3'h3,
73            PS2_STATE_4_TRANSMIT_STOP_BIT           = 3'h4,
74            PS2_STATE_5_RECEIVE_ACK_BIT             = 3'h5,
75            PS2_STATE_6_COMMAND_WAS_SENT            = 3'h6,
76            PS2_STATE_7_TRANSMISSION_ERROR          = 3'h7;
77
78/*****************************************************************************
79 *                 Internal wires and registers Declarations                 *
80 *****************************************************************************/
81
82// Internal Registers
83reg [3:0]    cur_bit;
84reg [8:0]    ps2_command;
85
86reg [NUMBER_OF_BITS_FOR_101US:1]    command_initiate_counter;
87reg [NUMBER_OF_BITS_FOR_15MS:1]     waiting_counter;
88reg [NUMBER_OF_BITS_FOR_2MS:1]      transfer_counter;
89
90// State Machine Registers
91reg [2:0]    ns_ps2_transmitter;
92reg [2:0]    s_ps2_transmitter;
93
94/*****************************************************************************
95 *                         Finite State Machine(s)                           *
96 *****************************************************************************/
97
98always @(posedge clk)
99begin
100    if (reset == 1'b1)
101        s_ps2_transmitter <= PS2_STATE_0_IDLE;
102    else
103        s_ps2_transmitter <= ns_ps2_transmitter;
104end
105
106always @(*)
107begin
108
109    // Defaults
110    ns_ps2_transmitter = PS2_STATE_0_IDLE;
111
112    case (s_ps2_transmitter)
113
114        PS2_STATE_0_IDLE:
115
116            begin
117                if (send_command == 1'b1)
118                    ns_ps2_transmitter = PS2_STATE_1_INITIATE_COMMUNICATION;
119                else
120                    ns_ps2_transmitter = PS2_STATE_0_IDLE;
121            end
122
123        PS2_STATE_1_INITIATE_COMMUNICATION:
124
125            begin
126                if (command_initiate_counter == CLOCK_CYCLES_FOR_101US)
127                    ns_ps2_transmitter = PS2_STATE_2_WAIT_FOR_CLOCK;
128                else
129                    ns_ps2_transmitter = PS2_STATE_1_INITIATE_COMMUNICATION;
130            end
131
132        PS2_STATE_2_WAIT_FOR_CLOCK:
133
134            begin
135                if (ps2_clk_negedge == 1'b1)
136                    ns_ps2_transmitter = PS2_STATE_3_TRANSMIT_DATA;
137                else if (waiting_counter == CLOCK_CYCLES_FOR_15MS)
138                    ns_ps2_transmitter = PS2_STATE_7_TRANSMISSION_ERROR;
139                else
140                    ns_ps2_transmitter = PS2_STATE_2_WAIT_FOR_CLOCK;
141            end
142
143        PS2_STATE_3_TRANSMIT_DATA:
144
145            begin
146                if ((cur_bit == 4'd8) && (ps2_clk_negedge == 1'b1))
147                    ns_ps2_transmitter = PS2_STATE_4_TRANSMIT_STOP_BIT;
148                else if (transfer_counter == CLOCK_CYCLES_FOR_2MS)
149                    ns_ps2_transmitter = PS2_STATE_7_TRANSMISSION_ERROR;
150                else
151                    ns_ps2_transmitter = PS2_STATE_3_TRANSMIT_DATA;
152            end
153
154        PS2_STATE_4_TRANSMIT_STOP_BIT:
155
156            begin
157                if (ps2_clk_negedge == 1'b1)
158                    ns_ps2_transmitter = PS2_STATE_5_RECEIVE_ACK_BIT;
159                else if (transfer_counter == CLOCK_CYCLES_FOR_2MS)
160                    ns_ps2_transmitter = PS2_STATE_7_TRANSMISSION_ERROR;
161                else
162                    ns_ps2_transmitter = PS2_STATE_4_TRANSMIT_STOP_BIT;
163            end
164
165        PS2_STATE_5_RECEIVE_ACK_BIT:
166
167            begin
168                if (ps2_clk_posedge == 1'b1)
169                    ns_ps2_transmitter = PS2_STATE_6_COMMAND_WAS_SENT;
170                else if (transfer_counter == CLOCK_CYCLES_FOR_2MS)
171                    ns_ps2_transmitter = PS2_STATE_7_TRANSMISSION_ERROR;
172                else
173                    ns_ps2_transmitter = PS2_STATE_5_RECEIVE_ACK_BIT;
174            end
175
176        PS2_STATE_6_COMMAND_WAS_SENT:
177
178            begin
179                if (send_command == 1'b0)
180                    ns_ps2_transmitter = PS2_STATE_0_IDLE;
181                else
182                    ns_ps2_transmitter = PS2_STATE_6_COMMAND_WAS_SENT;
183            end
184
185        PS2_STATE_7_TRANSMISSION_ERROR:
186
187            begin
188                if (send_command == 1'b0)
189                    ns_ps2_transmitter = PS2_STATE_0_IDLE;
190                else
191                    ns_ps2_transmitter = PS2_STATE_7_TRANSMISSION_ERROR;
192            end
193
194        default:
195
196            begin
197                ns_ps2_transmitter = PS2_STATE_0_IDLE;
198            end
199
200    endcase
201end
202
203/*****************************************************************************
204 *                             Sequential logic                              *
205 *****************************************************************************/
206
207always @(posedge clk)
208begin
209    if (reset == 1'b1)
210        ps2_command <= 9'h000;
211    else if (s_ps2_transmitter == PS2_STATE_0_IDLE)
212        ps2_command <= {(^the_command) ^ 1'b1, the_command};
213end
214
215always @(posedge clk)
216begin
217
218    if (reset == 1'b1)
219        command_initiate_counter <= {NUMBER_OF_BITS_FOR_101US{1'b0}};
220
221    else if ((s_ps2_transmitter == PS2_STATE_1_INITIATE_COMMUNICATION) &&
222            (command_initiate_counter != CLOCK_CYCLES_FOR_101US))
223        command_initiate_counter <=
224            command_initiate_counter + COUNTER_INCREMENT_FOR_101US;
225
226    else if (s_ps2_transmitter != PS2_STATE_1_INITIATE_COMMUNICATION)
227        command_initiate_counter <= {NUMBER_OF_BITS_FOR_101US{1'b0}};
228end
229
230always @(posedge clk)
231begin
232    if (reset == 1'b1)
233        waiting_counter <= {NUMBER_OF_BITS_FOR_15MS{1'b0}};
234
235    else if ((s_ps2_transmitter == PS2_STATE_2_WAIT_FOR_CLOCK) &&
236            (waiting_counter != CLOCK_CYCLES_FOR_15MS))
237        waiting_counter <= waiting_counter + COUNTER_INCREMENT_FOR_15MS;
238
239    else if (s_ps2_transmitter != PS2_STATE_2_WAIT_FOR_CLOCK)
240        waiting_counter <= {NUMBER_OF_BITS_FOR_15MS{1'b0}};
241end
242
243always @(posedge clk)
244begin
245
246    if (reset == 1'b1)
247        transfer_counter <= {NUMBER_OF_BITS_FOR_2MS{1'b0}};
248    else
249    begin
250
251        if ((s_ps2_transmitter == PS2_STATE_3_TRANSMIT_DATA) ||
252            (s_ps2_transmitter == PS2_STATE_4_TRANSMIT_STOP_BIT) ||
253            (s_ps2_transmitter == PS2_STATE_5_RECEIVE_ACK_BIT))
254        begin
255            if (transfer_counter != CLOCK_CYCLES_FOR_2MS)
256                transfer_counter <= transfer_counter + COUNTER_INCREMENT_FOR_2MS;
257        end
258        else
259            transfer_counter <= {NUMBER_OF_BITS_FOR_2MS{1'b0}};
260    end
261end
262
263always @(posedge clk)
264begin
265
266    if (reset == 1'b1)
267        cur_bit <= 4'h0;
268    else if ((s_ps2_transmitter == PS2_STATE_3_TRANSMIT_DATA) &&
269            (ps2_clk_negedge == 1'b1))
270        cur_bit <= cur_bit + 4'h1;
271    else if (s_ps2_transmitter != PS2_STATE_3_TRANSMIT_DATA)
272        cur_bit <= 4'h0;
273end
274
275always @(posedge clk)
276begin
277
278    if (reset == 1'b1)
279        command_was_sent <= 1'b0;
280    else if (s_ps2_transmitter == PS2_STATE_6_COMMAND_WAS_SENT)
281        command_was_sent <= 1'b1;
282    else if (send_command == 1'b0)
283            command_was_sent <= 1'b0;
284end
285
286always @(posedge clk)
287begin
288
289    if (reset == 1'b1)
290        error_communication_timed_out <= 1'b0;
291    else if (s_ps2_transmitter == PS2_STATE_7_TRANSMISSION_ERROR)
292        error_communication_timed_out <= 1'b1;
293    else if (send_command == 1'b0)
294        error_communication_timed_out <= 1'b0;
295end
296
297/*****************************************************************************
298 *                            Combinational logic                            *
299 *****************************************************************************/
300
301assign PS2_CLK    = (s_ps2_transmitter == PS2_STATE_1_INITIATE_COMMUNICATION) ? 1'b0 : 1'bz;
302assign PS2_DAT    = (s_ps2_transmitter == PS2_STATE_3_TRANSMIT_DATA) ? ps2_command[cur_bit] :
303                    (s_ps2_transmitter == PS2_STATE_2_WAIT_FOR_CLOCK) ? 1'b0 :
304                    ((s_ps2_transmitter == PS2_STATE_1_INITIATE_COMMUNICATION) &&
305                    (command_initiate_counter[NUMBER_OF_BITS_FOR_101US] == 1'b1)) ? 1'b0 : 1'bz;
306
307endmodule