1/*****************************************************************************
2 *                                                                           *
3 * Module:       Altera_UP_PS2_Data_In                                       *
4 * Description:                                                              *
5 *      This module accepts incoming data from a PS2 core.                   *
6 *                                                                           *
7 *****************************************************************************/
8
9module Altera_UP_PS2_Data_In (
10
11    // Inputs
12    clk,
13    reset,
14    wait_for_incoming_data,
15    start_receiving_data,
16    ps2_clk_posedge,
17    ps2_clk_negedge,
18    ps2_data,
19
20    // Outputs
21    received_data,
22    received_data_en            // If 1 - new data has been received
23);
24
25/*****************************************************************************
26 *                             Port Declarations                             *
27 *****************************************************************************/
28// Inputs
29input   clk;
30input   reset;
31input   wait_for_incoming_data;
32input   start_receiving_data;
33input   ps2_clk_posedge;
34input   ps2_clk_negedge;
35input   ps2_data;
36
37
38// Outputs
39output reg [7:0]    received_data;
40output reg          received_data_en;
41
42/*****************************************************************************
43 *                           Constant Declarations                           *
44 *****************************************************************************/
45// states
46localparam  PS2_STATE_0_IDLE            = 3'h0,
47            PS2_STATE_1_WAIT_FOR_DATA   = 3'h1,
48            PS2_STATE_2_DATA_IN         = 3'h2,
49            PS2_STATE_3_PARITY_IN       = 3'h3,
50            PS2_STATE_4_STOP_IN         = 3'h4;
51
52/*****************************************************************************
53 *                 Internal wires and registers Declarations                 *
54 *****************************************************************************/
55// Internal Wires
56reg [3:0]   data_count;
57reg [7:0]   data_shift_reg;
58
59// State Machine Registers
60reg [2:0]   ns_ps2_receiver;
61reg [2:0]   s_ps2_receiver;
62
63/*****************************************************************************
64 *                         Finite State Machine(s)                           *
65 *****************************************************************************/
66
67always @(posedge clk)
68begin
69
70    if (reset == 1'b1)
71        s_ps2_receiver <= PS2_STATE_0_IDLE;
72    else
73        s_ps2_receiver <= ns_ps2_receiver;
74end
75
76always @(*)
77begin
78
79    // Defaults
80    ns_ps2_receiver = PS2_STATE_0_IDLE;
81
82    case (s_ps2_receiver)
83
84        PS2_STATE_0_IDLE:
85
86            begin
87                if ((wait_for_incoming_data == 1'b1) && (received_data_en == 1'b0))
88                    ns_ps2_receiver = PS2_STATE_1_WAIT_FOR_DATA;
89
90                else if ((start_receiving_data == 1'b1) && (received_data_en == 1'b0))
91                    ns_ps2_receiver = PS2_STATE_2_DATA_IN;
92
93                else
94                    ns_ps2_receiver = PS2_STATE_0_IDLE;
95            end
96
97        PS2_STATE_1_WAIT_FOR_DATA:
98
99            begin
100                if ((ps2_data == 1'b0) && (ps2_clk_posedge == 1'b1))
101                    ns_ps2_receiver = PS2_STATE_2_DATA_IN;
102                else if (wait_for_incoming_data == 1'b0)
103                    ns_ps2_receiver = PS2_STATE_0_IDLE;
104                else
105                    ns_ps2_receiver = PS2_STATE_1_WAIT_FOR_DATA;
106            end
107
108        PS2_STATE_2_DATA_IN:
109
110            begin
111                if ((data_count == 3'h7) && (ps2_clk_posedge == 1'b1))
112                    ns_ps2_receiver = PS2_STATE_3_PARITY_IN;
113                else
114                    ns_ps2_receiver = PS2_STATE_2_DATA_IN;
115            end
116
117        PS2_STATE_3_PARITY_IN:
118
119            begin
120                if (ps2_clk_posedge == 1'b1)
121                    ns_ps2_receiver = PS2_STATE_4_STOP_IN;
122                else
123                    ns_ps2_receiver = PS2_STATE_3_PARITY_IN;
124            end
125
126        PS2_STATE_4_STOP_IN:
127
128            begin
129                if (ps2_clk_posedge == 1'b1)
130                    ns_ps2_receiver = PS2_STATE_0_IDLE;
131                else
132                    ns_ps2_receiver = PS2_STATE_4_STOP_IN;
133            end
134
135        default:
136
137            begin
138                ns_ps2_receiver = PS2_STATE_0_IDLE;
139            end
140
141    endcase
142end
143
144/*****************************************************************************
145 *                             Sequential logic                              *
146 *****************************************************************************/
147
148always @(posedge clk)
149begin
150
151    if (reset == 1'b1)
152        data_count    <= 3'h0;
153
154    else if ((s_ps2_receiver == PS2_STATE_2_DATA_IN) && (ps2_clk_posedge == 1'b1))
155        data_count    <= data_count + 3'h1;
156
157    else if (s_ps2_receiver != PS2_STATE_2_DATA_IN)
158        data_count    <= 3'h0;
159end
160
161always @(posedge clk)
162begin
163
164    if (reset == 1'b1)
165        data_shift_reg <= 8'h00;
166
167    else if ((s_ps2_receiver == PS2_STATE_2_DATA_IN) && (ps2_clk_posedge == 1'b1))
168        data_shift_reg <= {ps2_data, data_shift_reg[7:1]};
169end
170
171always @(posedge clk)
172begin
173
174    if (reset == 1'b1)
175        received_data <= 8'h00;
176
177    else if (s_ps2_receiver == PS2_STATE_4_STOP_IN)
178        received_data <= data_shift_reg;
179end
180
181always @(posedge clk)
182begin
183
184    if (reset == 1'b1)
185        received_data_en    <= 1'b0;
186
187    else if ((s_ps2_receiver == PS2_STATE_4_STOP_IN) && (ps2_clk_posedge == 1'b1))
188        received_data_en    <= 1'b1;
189    else
190        received_data_en    <= 1'b0;
191end
192
193endmodule