1/*****************************************************************************
2 *                                                                           *
3 * Module:       Altera_UP_PS2                                               *
4 * Description:                                                              *
5 *      This module communicates with the PS2 core.                          *
6 *                                                                           *
7 * www.eecg.toronto.edu/~jayar/ece241_08F/AudioVideoCores/ps2/ps2.html       *
8 *****************************************************************************/
9
10module ps2controller #(parameter INITIALIZE_MOUSE = 0) (
11
12    // Inputs
13    CLOCK_50,
14    reset,
15
16    the_command,
17    send_command,
18
19    // Bidirectionals
20    PS2_CLK,                    // PS2 Clock
21    PS2_DAT,                    // PS2 Data
22
23    // Outputs
24    command_was_sent,
25    error_communication_timed_out,
26
27    received_data,
28    received_data_en            // If 1 - new data has been received
29);
30
31/*****************************************************************************
32 *                             Port Declarations                             *
33 *****************************************************************************/
34
35// Inputs
36input           CLOCK_50;
37input           reset;
38input    [7:0]  the_command;
39input           send_command;
40
41// Bidirectionals
42inout           PS2_CLK;
43inout           PS2_DAT;
44
45// Outputs
46output          command_was_sent;
47output          error_communication_timed_out;
48
49output   [7:0]  received_data;
50output          received_data_en;
51
52// ---------------------------------------------------------------------
53wire     [7:0]  the_command_w;
54wire            send_command_w,
55                command_was_sent_w,
56                error_communication_timed_out_w;
57
58generate
59
60    if (INITIALIZE_MOUSE) begin
61
62        assign the_command_w        = init_done ? the_command : 8'hf4;
63        assign send_command_w       = init_done ? send_command : (!command_was_sent_w && !error_communication_timed_out_w);
64        assign command_was_sent     = init_done ? command_was_sent_w : 0;
65        assign error_communication_timed_out = init_done ? error_communication_timed_out_w : 1;
66
67        reg init_done;
68
69        always @(posedge CLOCK_50)
70
71            if (reset) init_done <= 0;
72            else if (command_was_sent_w) init_done <= 1;
73
74    end else
75    begin
76
77        assign the_command_w    = the_command;
78        assign send_command_w   = send_command;
79        assign command_was_sent = command_was_sent_w;
80        assign error_communication_timed_out = error_communication_timed_out_w;
81
82    end
83
84endgenerate
85
86/*****************************************************************************
87 *                           Constant Declarations                           *
88 *****************************************************************************/
89// states
90localparam
91    PS2_STATE_0_IDLE                = 3'h0,
92    PS2_STATE_1_DATA_IN             = 3'h1,
93    PS2_STATE_2_COMMAND_OUT         = 3'h2,
94    PS2_STATE_3_END_TRANSFER        = 3'h3,
95    PS2_STATE_4_END_DELAYED         = 3'h4;
96
97/*****************************************************************************
98 *                 Internal wires and registers Declarations                 *
99 *****************************************************************************/
100
101// Internal Wires
102wire    ps2_clk_posedge;
103wire    ps2_clk_negedge;
104wire    start_receiving_data;
105wire    wait_for_incoming_data;
106
107// Internal Registers
108reg        [7:0]    idle_counter;
109
110reg                 ps2_clk_reg;
111reg                 ps2_data_reg;
112reg                 last_ps2_clk;
113
114// State Machine Registers
115reg        [2:0]    ns_ps2_transceiver;
116reg        [2:0]    s_ps2_transceiver;
117
118/*****************************************************************************
119 *                         Finite State Machine(s)                           *
120 *****************************************************************************/
121
122always @(posedge CLOCK_50)
123begin
124
125    if (reset == 1'b1)
126        s_ps2_transceiver <= PS2_STATE_0_IDLE;
127    else
128        s_ps2_transceiver <= ns_ps2_transceiver;
129end
130
131always @(*)
132begin
133
134    // Defaults
135    ns_ps2_transceiver = PS2_STATE_0_IDLE;
136
137    case (s_ps2_transceiver)
138
139        /* Ожидание */
140        PS2_STATE_0_IDLE:
141
142            begin
143
144                if ((idle_counter == 8'hFF) && (send_command == 1'b1))
145                    ns_ps2_transceiver = PS2_STATE_2_COMMAND_OUT;
146
147                else if ((ps2_data_reg == 1'b0) && (ps2_clk_posedge == 1'b1))
148                    ns_ps2_transceiver = PS2_STATE_1_DATA_IN;
149
150                else
151                    ns_ps2_transceiver = PS2_STATE_0_IDLE;
152            end
153
154        /* Получение данных */
155        PS2_STATE_1_DATA_IN:
156
157            begin
158
159                if ((received_data_en == 1'b1)/* && (ps2_clk_posedge == 1'b1)*/)
160                    ns_ps2_transceiver = PS2_STATE_0_IDLE;
161                else
162                    ns_ps2_transceiver = PS2_STATE_1_DATA_IN;
163            end
164
165        /* Команда */
166        PS2_STATE_2_COMMAND_OUT:
167
168            begin
169                if ((command_was_sent == 1'b1) || (error_communication_timed_out == 1'b1))
170                     ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER;
171                else ns_ps2_transceiver = PS2_STATE_2_COMMAND_OUT;
172            end
173
174        /* Завершение передачи */
175        PS2_STATE_3_END_TRANSFER:
176
177            begin
178                if (send_command == 1'b0)
179                    ns_ps2_transceiver = PS2_STATE_0_IDLE;
180
181                else if ((ps2_data_reg == 1'b0) && (ps2_clk_posedge == 1'b1))
182                    ns_ps2_transceiver = PS2_STATE_4_END_DELAYED;
183
184                else
185                    ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER;
186            end
187
188        /* Завершение передачи с задержкой */
189        PS2_STATE_4_END_DELAYED:
190
191            begin
192
193                if (received_data_en == 1'b1)
194                begin
195
196                    if (send_command == 1'b0)
197                        ns_ps2_transceiver = PS2_STATE_0_IDLE;
198                    else
199                        ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER;
200                end
201                else
202                    ns_ps2_transceiver = PS2_STATE_4_END_DELAYED;
203            end
204
205        /* Все другие статусы */
206        default:
207            ns_ps2_transceiver = PS2_STATE_0_IDLE;
208
209    endcase
210end
211
212/*****************************************************************************
213 *                             Sequential logic                              *
214 *****************************************************************************/
215
216always @(posedge CLOCK_50)
217begin
218
219    if (reset == 1'b1)
220    begin
221
222        last_ps2_clk    <= 1'b1;
223        ps2_clk_reg     <= 1'b1;
224        ps2_data_reg    <= 1'b1;
225
226    end
227    else
228    begin
229
230        last_ps2_clk    <= ps2_clk_reg;
231        ps2_clk_reg     <= PS2_CLK;
232        ps2_data_reg    <= PS2_DAT;
233
234    end
235end
236
237always @(posedge CLOCK_50)
238begin
239
240    if (reset == 1'b1)
241        idle_counter <= 6'h00;
242
243    else if ((s_ps2_transceiver == PS2_STATE_0_IDLE) && (idle_counter != 8'hFF))
244        idle_counter <= idle_counter + 6'h01;
245
246    else if (s_ps2_transceiver != PS2_STATE_0_IDLE)
247        idle_counter <= 6'h00;
248end
249
250/*****************************************************************************
251 *                            Combinational logic                            *
252 *****************************************************************************/
253
254assign ps2_clk_posedge         = ((ps2_clk_reg == 1'b1) && (last_ps2_clk == 1'b0)) ? 1'b1 : 1'b0;
255assign ps2_clk_negedge         = ((ps2_clk_reg == 1'b0) && (last_ps2_clk == 1'b1)) ? 1'b1 : 1'b0;
256assign start_receiving_data    = (s_ps2_transceiver == PS2_STATE_1_DATA_IN);
257assign wait_for_incoming_data  = (s_ps2_transceiver == PS2_STATE_3_END_TRANSFER);
258
259/*****************************************************************************
260 *                              Internal Modules                             *
261 *****************************************************************************/
262
263Altera_UP_PS2_Data_In PS2_Data_In
264(
265    // Inputs
266    .clk                        (CLOCK_50),
267    .reset                      (reset),
268
269    .wait_for_incoming_data     (wait_for_incoming_data),
270    .start_receiving_data       (start_receiving_data),
271
272    .ps2_clk_posedge            (ps2_clk_posedge),
273    .ps2_clk_negedge            (ps2_clk_negedge),
274    .ps2_data                   (ps2_data_reg),
275
276    // Bidirectionals Outputs
277    .received_data              (received_data),
278    .received_data_en           (received_data_en)
279);
280
281Altera_UP_PS2_Command_Out PS2_Command_Out (
282
283    // Inputs
284    .clk                (CLOCK_50),
285    .reset              (reset),
286    .the_command        (the_command_w),
287    .send_command       (send_command_w),
288    .ps2_clk_posedge    (ps2_clk_posedge),
289    .ps2_clk_negedge    (ps2_clk_negedge),
290
291    // Bidirectionals
292    .PS2_CLK            (PS2_CLK),
293     .PS2_DAT           (PS2_DAT),
294
295    // Outputs
296    .command_was_sent               (command_was_sent_w),
297    .error_communication_timed_out  (error_communication_timed_out_w)
298);
299
300endmodule