uart_rx: ein prozessmodell. spart weitere 3 logic elements :P
[hwmod.git] / src / ps2 / ps2_transceiver_beh.vhd
1 -------------------------------------------------------------------------\r
2 --\r
3 -- Filename: ps2_transceiver_beh.vhd\r
4 -- =========\r
5 --\r
6 -- Short Description:\r
7 -- ==================\r
8 --   Behavioral implementation of the PS/2 transceiver\r
9 --\r
10 -------------------------------------------------------------------------\r
11 \r
12 library ieee;\r
13 use ieee.std_logic_1164.all;\r
14 \r
15 architecture beh of ps2_transceiver is\r
16   constant PREPARE_TIMEOUT1_MAX : integer := CLK_FREQ / 5000; -- 200 us\r
17   constant PREPARE_TIMEOUT2_MAX : integer := CLK_FREQ / 100000; -- 10 us\r
18   type PS2_TRANSCEIVER_STATE_TYPE is\r
19   (\r
20     IDLE,\r
21 \r
22     PREPARE_SEND_ASSIGN_CLK, PREPARE_SEND_WAIT1, PREPARE_SEND_DATA, PREPARE_SEND_WAIT2,\r
23     PREPARE_SEND_RELEASE_CLK, SEND_WAIT_DATA0, SEND_DATA0, SEND_WAIT_DATA1, SEND_DATA1,\r
24     SEND_WAIT_DATA2, SEND_DATA2, SEND_WAIT_DATA3, SEND_DATA3, SEND_WAIT_DATA4, SEND_DATA4,\r
25     SEND_WAIT_DATA5, SEND_DATA5, SEND_WAIT_DATA6, SEND_DATA6, SEND_WAIT_DATA7, SEND_DATA7,\r
26     SEND_WAIT_PARITY, SEND_PARITY, SEND_WAIT_STOP, SEND_STOP, SEND_WAIT_ACK1, SEND_WAIT_ACK2,\r
27     SEND_READ_ACK, SEND_FINISH,\r
28      \r
29     RECEIVE_START, RECEIVE_WAIT_DATA0, RECEIVE_DATA0, RECEIVE_WAIT_DATA1, RECEIVE_DATA1,\r
30     RECEIVE_WAIT_DATA2, RECEIVE_DATA2, RECEIVE_WAIT_DATA3, RECEIVE_DATA3, RECEIVE_WAIT_DATA4,\r
31     RECEIVE_DATA4, RECEIVE_WAIT_DATA5, RECEIVE_DATA5, RECEIVE_WAIT_DATA6, RECEIVE_DATA6,\r
32     RECEIVE_WAIT_DATA7, RECEIVE_DATA7, RECEIVE_WAIT_PARITY, RECEIVE_PARITY, RECEIVE_WAIT_STOP,\r
33     RECEIVE_STOP\r
34   );\r
35   signal ps2_transceiver_state, ps2_transceiver_state_next : PS2_TRANSCEIVER_STATE_TYPE;\r
36   signal ps2_clk_last, ps2_clk_internal, ps2_clk_next, ps2_clk_hz, ps2_clk_hz_next : std_logic;\r
37   signal ps2_data_internal, ps2_data_next, ps2_data_hz, ps2_data_hz_next : std_logic;\r
38   signal ps2_clk_sync, ps2_data_sync : std_logic_vector(1 to SYNC_STAGES);\r
39   signal output_data_next, output_data_internal : std_logic_vector(7 downto 0);\r
40   signal parity, parity_next : std_logic;\r
41   signal new_data_next : std_logic;\r
42   signal prepare_timeout1, prepare_timeout1_next : integer range 0 to PREPARE_TIMEOUT1_MAX;\r
43   signal prepare_timeout2, prepare_timeout2_next : integer range 0 to PREPARE_TIMEOUT2_MAX;\r
44 begin\r
45 \r
46   process(ps2_transceiver_state, ps2_clk_sync(SYNC_STAGES), ps2_clk_last, ps2_data_sync(SYNC_STAGES), send_request, prepare_timeout1, prepare_timeout2, output_data_internal)\r
47   begin\r
48     ps2_transceiver_state_next <= ps2_transceiver_state;\r
49    \r
50     case ps2_transceiver_state is\r
51       when IDLE =>        \r
52         if ps2_clk_sync(SYNC_STAGES) = '1' and ps2_clk_last = '0' then\r
53           if ps2_data_sync(SYNC_STAGES) = '0' then\r
54             ps2_transceiver_state_next <= RECEIVE_START;\r
55           end if;\r
56         elsif send_request = '1' then\r
57           ps2_transceiver_state_next <= PREPARE_SEND_ASSIGN_CLK;\r
58         end if;\r
59 \r
60 \r
61       when PREPARE_SEND_ASSIGN_CLK =>\r
62         ps2_transceiver_state_next <= PREPARE_SEND_WAIT1;\r
63       when PREPARE_SEND_WAIT1 =>\r
64         if prepare_timeout1 = PREPARE_TIMEOUT1_MAX - 1 then\r
65           ps2_transceiver_state_next <= PREPARE_SEND_DATA;\r
66         end if;\r
67       when PREPARE_SEND_DATA =>\r
68         ps2_transceiver_state_next <= PREPARE_SEND_WAIT2;\r
69       when PREPARE_SEND_WAIT2 =>\r
70         if prepare_timeout2 = PREPARE_TIMEOUT2_MAX - 1 then\r
71           ps2_transceiver_state_next <= PREPARE_SEND_RELEASE_CLK;\r
72         end if;\r
73       when PREPARE_SEND_RELEASE_CLK =>\r
74         ps2_transceiver_state_next <= SEND_WAIT_DATA0;\r
75       when SEND_WAIT_DATA0 =>\r
76         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
77           ps2_transceiver_state_next <= SEND_DATA0;\r
78         end if;\r
79       when SEND_DATA0 =>\r
80         ps2_transceiver_state_next <= SEND_WAIT_DATA1;\r
81       when SEND_WAIT_DATA1 =>\r
82         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
83           ps2_transceiver_state_next <= SEND_DATA1;\r
84         end if;\r
85       when SEND_DATA1 =>\r
86         ps2_transceiver_state_next <= SEND_WAIT_DATA2;\r
87       when SEND_WAIT_DATA2 =>\r
88         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
89           ps2_transceiver_state_next <= SEND_DATA2;\r
90         end if;\r
91       when SEND_DATA2 =>\r
92         ps2_transceiver_state_next <= SEND_WAIT_DATA3;\r
93       when SEND_WAIT_DATA3 =>\r
94         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
95           ps2_transceiver_state_next <= SEND_DATA3;\r
96         end if;\r
97       when SEND_DATA3 =>\r
98         ps2_transceiver_state_next <= SEND_WAIT_DATA4;\r
99       when SEND_WAIT_DATA4 =>\r
100         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
101           ps2_transceiver_state_next <= SEND_DATA4;\r
102         end if;\r
103       when SEND_DATA4 =>\r
104         ps2_transceiver_state_next <= SEND_WAIT_DATA5;\r
105       when SEND_WAIT_DATA5 =>\r
106         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
107           ps2_transceiver_state_next <= SEND_DATA5;\r
108         end if;\r
109       when SEND_DATA5 =>\r
110         ps2_transceiver_state_next <= SEND_WAIT_DATA6;\r
111       when SEND_WAIT_DATA6 =>\r
112         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
113           ps2_transceiver_state_next <= SEND_DATA6;\r
114         end if;\r
115       when SEND_DATA6 =>\r
116         ps2_transceiver_state_next <= SEND_WAIT_DATA7;\r
117       when SEND_WAIT_DATA7 =>\r
118         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
119           ps2_transceiver_state_next <= SEND_DATA7;\r
120         end if;\r
121       when SEND_DATA7 =>\r
122         ps2_transceiver_state_next <= SEND_WAIT_PARITY;\r
123       when SEND_WAIT_PARITY =>\r
124         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
125           ps2_transceiver_state_next <= SEND_PARITY;\r
126         end if;\r
127       when SEND_PARITY =>\r
128         ps2_transceiver_state_next <= SEND_WAIT_STOP;\r
129       when SEND_WAIT_STOP =>\r
130         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
131           ps2_transceiver_state_next <= SEND_STOP;\r
132         end if;\r
133       when SEND_STOP =>\r
134         ps2_transceiver_state_next <= SEND_WAIT_ACK1;      \r
135       when SEND_WAIT_ACK1 =>\r
136         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then -- ACK is written by device\r
137           ps2_transceiver_state_next <= SEND_WAIT_ACK2;\r
138         end if;\r
139       when SEND_WAIT_ACK2 =>\r
140         if ps2_clk_sync(SYNC_STAGES) = '1' and ps2_clk_last = '0' then -- ACK is valid\r
141           ps2_transceiver_state_next <= SEND_READ_ACK;\r
142         end if;\r
143       when SEND_READ_ACK =>\r
144         ps2_transceiver_state_next <= SEND_FINISH;\r
145       when SEND_FINISH =>\r
146         ps2_transceiver_state_next <= IDLE;\r
147 \r
148       \r
149       \r
150       when RECEIVE_START =>\r
151         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA0;\r
152       when RECEIVE_WAIT_DATA0 =>\r
153         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
154           ps2_transceiver_state_next <= RECEIVE_DATA0;\r
155         end if;\r
156       when RECEIVE_DATA0 =>\r
157         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA1;\r
158       when RECEIVE_WAIT_DATA1 =>\r
159         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
160           ps2_transceiver_state_next <= RECEIVE_DATA1;\r
161         end if;\r
162       when RECEIVE_DATA1 =>\r
163         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA2;\r
164       when RECEIVE_WAIT_DATA2 =>\r
165         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
166           ps2_transceiver_state_next <= RECEIVE_DATA2;\r
167         end if;\r
168       when RECEIVE_DATA2 =>\r
169         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA3;\r
170       when RECEIVE_WAIT_DATA3 =>\r
171         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
172           ps2_transceiver_state_next <= RECEIVE_DATA3;\r
173         end if;\r
174       when RECEIVE_DATA3 =>\r
175         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA4;\r
176       when RECEIVE_WAIT_DATA4 =>\r
177         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
178           ps2_transceiver_state_next <= RECEIVE_DATA4;\r
179         end if;\r
180       when RECEIVE_DATA4 =>\r
181         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA5;\r
182       when RECEIVE_WAIT_DATA5 =>\r
183         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
184           ps2_transceiver_state_next <= RECEIVE_DATA5;\r
185         end if;\r
186       when RECEIVE_DATA5 =>\r
187         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA6;\r
188       when RECEIVE_WAIT_DATA6 =>\r
189         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
190           ps2_transceiver_state_next <= RECEIVE_DATA6;\r
191         end if;\r
192       when RECEIVE_DATA6 =>\r
193         ps2_transceiver_state_next <= RECEIVE_WAIT_DATA7;\r
194       when RECEIVE_WAIT_DATA7 =>\r
195         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
196           ps2_transceiver_state_next <= RECEIVE_DATA7;\r
197         end if;\r
198       when RECEIVE_DATA7 =>\r
199         ps2_transceiver_state_next <= RECEIVE_WAIT_PARITY;\r
200       when RECEIVE_WAIT_PARITY =>\r
201         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
202           ps2_transceiver_state_next <= RECEIVE_PARITY;\r
203         end if;\r
204       when RECEIVE_PARITY =>\r
205         ps2_transceiver_state_next <= RECEIVE_WAIT_STOP;\r
206       when RECEIVE_WAIT_STOP =>     \r
207         if ps2_clk_sync(SYNC_STAGES) = '0' and ps2_clk_last = '1' then\r
208           ps2_transceiver_state_next <= RECEIVE_STOP;\r
209         end if;\r
210       when RECEIVE_STOP =>\r
211         ps2_transceiver_state_next <= IDLE;\r
212     end case;\r
213   end process;\r
214   \r
215   process(ps2_transceiver_state, ps2_data_internal, ps2_clk_internal, parity, input_data, ps2_data_sync(SYNC_STAGES), output_data_internal, prepare_timeout1, prepare_timeout2, ps2_clk_hz, ps2_data_hz)\r
216   begin\r
217     input_data_send_ok <= '0';\r
218     input_data_send_finished <= '0';\r
219     ps2_data_next <= ps2_data_internal;\r
220     ps2_data_hz_next <= ps2_data_hz;\r
221     ps2_clk_next <= ps2_clk_internal;\r
222     ps2_clk_hz_next <= ps2_clk_hz;\r
223     parity_next <= parity;\r
224     output_data_next <= output_data_internal;\r
225     new_data_next <= '0';\r
226     prepare_timeout1_next <= prepare_timeout1;\r
227     prepare_timeout2_next <= prepare_timeout2;\r
228     \r
229     case ps2_transceiver_state is\r
230       when IDLE =>        \r
231         ps2_clk_next <= '1';\r
232         ps2_clk_hz_next <= '1';\r
233         ps2_data_next <= '1';\r
234         ps2_data_hz_next <= '1';\r
235 \r
236       when PREPARE_SEND_ASSIGN_CLK =>\r
237         ps2_clk_next <= '0';\r
238         ps2_clk_hz_next <= '0';\r
239         parity_next <= '1';\r
240         prepare_timeout1_next <= 0;\r
241       when PREPARE_SEND_WAIT1 =>\r
242         prepare_timeout1_next <= prepare_timeout1 + 1;\r
243       when PREPARE_SEND_DATA =>\r
244         ps2_data_next <='0';\r
245         ps2_data_hz_next <= '0';\r
246         prepare_timeout2_next <= 0;\r
247       when PREPARE_SEND_WAIT2 =>\r
248         prepare_timeout2_next <= prepare_timeout2 + 1;\r
249       when PREPARE_SEND_RELEASE_CLK =>\r
250         ps2_clk_next <= '1';\r
251         ps2_clk_hz_next <= '1';\r
252       when SEND_WAIT_DATA0 =>\r
253         null;\r
254       when SEND_DATA0 =>\r
255         ps2_data_next <= input_data(0);\r
256         parity_next <= parity xor input_data(0);\r
257       when SEND_WAIT_DATA1 =>\r
258         null;\r
259       when SEND_DATA1 =>\r
260         ps2_data_next <=input_data(1);\r
261         parity_next <= parity xor input_data(1);\r
262       when SEND_WAIT_DATA2 =>\r
263         null;\r
264       when SEND_DATA2 =>\r
265         ps2_data_next <=input_data(2);\r
266         parity_next <= parity xor input_data(2);\r
267       when SEND_WAIT_DATA3 =>\r
268         null;\r
269       when SEND_DATA3 =>\r
270         ps2_data_next <=input_data(3);\r
271         parity_next <= parity xor input_data(3);\r
272       when SEND_WAIT_DATA4 =>\r
273         null;\r
274       when SEND_DATA4 =>\r
275         ps2_data_next <=input_data(4);\r
276         parity_next <= parity xor input_data(4);\r
277       when SEND_WAIT_DATA5 =>\r
278         null;\r
279       when SEND_DATA5 =>\r
280         ps2_data_next <=input_data(5);\r
281         parity_next <= parity xor input_data(5);\r
282       when SEND_WAIT_DATA6 =>\r
283         null;\r
284       when SEND_DATA6 =>\r
285         ps2_data_next <=input_data(6);\r
286         parity_next <= parity xor input_data(6);\r
287       when SEND_WAIT_DATA7 =>\r
288         null;\r
289       when SEND_DATA7 =>\r
290         ps2_data_next <=input_data(7);\r
291         parity_next <= parity xor input_data(7);\r
292       when SEND_WAIT_PARITY =>\r
293         null;\r
294       when SEND_PARITY =>\r
295         ps2_data_next <= parity;\r
296       when SEND_WAIT_STOP =>\r
297         null;\r
298       when SEND_STOP =>\r
299         ps2_data_next <='1';\r
300         ps2_data_hz_next <='1';\r
301       when SEND_WAIT_ACK1 =>\r
302         null;\r
303       when SEND_WAIT_ACK2 =>\r
304         null;\r
305       when SEND_READ_ACK =>\r
306         input_data_send_ok <= not ps2_data_sync(SYNC_STAGES);\r
307         input_data_send_finished <= '1';\r
308       when SEND_FINISH =>\r
309             \r
310       when RECEIVE_START =>\r
311         null;\r
312       when RECEIVE_WAIT_DATA0 =>\r
313         null;\r
314       when RECEIVE_DATA0 =>\r
315         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
316       when RECEIVE_WAIT_DATA1 =>\r
317         null;\r
318       when RECEIVE_DATA1 =>\r
319         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
320       when RECEIVE_WAIT_DATA2 =>\r
321         null;\r
322       when RECEIVE_DATA2 =>\r
323         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
324       when RECEIVE_WAIT_DATA3 =>\r
325         null;\r
326       when RECEIVE_DATA3 =>\r
327         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
328       when RECEIVE_WAIT_DATA4 =>\r
329         null;\r
330       when RECEIVE_DATA4 =>\r
331         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
332       when RECEIVE_WAIT_DATA5 =>\r
333         null;\r
334       when RECEIVE_DATA5 =>\r
335         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
336       when RECEIVE_WAIT_DATA6 =>\r
337         null;\r
338       when RECEIVE_DATA6 =>\r
339         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
340       when RECEIVE_WAIT_DATA7 =>\r
341         null;\r
342       when RECEIVE_DATA7 =>\r
343         output_data_next <= ps2_data_sync(SYNC_STAGES) & output_data_internal(7 downto 1);\r
344       when RECEIVE_WAIT_PARITY =>\r
345         null;\r
346       when RECEIVE_PARITY =>\r
347         null; -- Currently igonring parity\r
348       when RECEIVE_WAIT_STOP =>\r
349         null;\r
350       when RECEIVE_STOP =>\r
351         new_data_next <= '1';\r
352     end case;\r
353   end process;\r
354   \r
355   process(sys_clk, sys_res_n)\r
356   begin\r
357     if sys_res_n = '0' then\r
358       ps2_transceiver_state <= IDLE;\r
359       ps2_clk_last <= '1';\r
360       ps2_clk_internal <= '1';\r
361       ps2_clk_hz <= '1';\r
362       ps2_data_internal <= '1';\r
363       ps2_data_hz <= '1';\r
364       output_data_internal <= (others => '0');\r
365       parity <= '0';\r
366       new_data <= '0';\r
367       prepare_timeout1 <= 0;\r
368       prepare_timeout2 <= 0;\r
369       ps2_clk_sync <= (others => '1');\r
370       ps2_data_sync <= (others => '1');\r
371     elsif rising_edge(sys_clk) then\r
372       ps2_transceiver_state <= ps2_transceiver_state_next;\r
373       ps2_clk_last <= ps2_clk_sync(SYNC_STAGES);\r
374       ps2_clk_internal <= ps2_clk_next;\r
375       ps2_clk_hz <= ps2_clk_hz_next;\r
376       ps2_data_internal <= ps2_data_next;\r
377       ps2_data_hz <= ps2_data_hz_next;\r
378       output_data_internal <= output_data_next;\r
379       parity <= parity_next;\r
380       new_data <= new_data_next;\r
381       prepare_timeout1 <= prepare_timeout1_next;\r
382       prepare_timeout2 <= prepare_timeout2_next;\r
383       ps2_clk_sync(1) <= ps2_clk;\r
384       ps2_data_sync(1) <= ps2_data;\r
385       for i in 2 to SYNC_STAGES loop\r
386         ps2_clk_sync(i) <= ps2_clk_sync(i - 1);\r
387         ps2_data_sync(i) <= ps2_data_sync(i - 1);\r
388       end loop;\r
389     end if;\r
390   end process;\r
391   ps2_clk <= ps2_clk_internal when ps2_clk_hz = '0'\r
392              else 'Z';\r
393   ps2_data <= ps2_data_internal when ps2_data_hz = '0'\r
394              else 'Z';\r
395   output_data <= output_data_internal;\r
396 end architecture beh;\r