Aktuální adresář: FITkit /
trunk /
fpga /
ctrls /
infra /
nec_full.vhd
1 -- nec_full.vhd: NEC code IR transciever
2 -- Copyright (C) 2009 Brno University of Technology,
3 -- Faculty of Information Technology
4 -- Author(s): Michal RĹŻĹľek <xruzek01 AT stud.fit.vutbr.cz>
5 --
6 -- LICENSE TERMS
7 --
8 -- Redistribution and use in source and binary forms, with or without
9 -- modification, are permitted provided that the following conditions
10 -- are met:
11 -- 1. Redistributions of source code must retain the above copyright
12 -- notice, this list of conditions and the following disclaimer.
13 -- 2. Redistributions in binary form must reproduce the above copyright
14 -- notice, this list of conditions and the following disclaimer in
15 -- the documentation and/or other materials provided with the
16 -- distribution.
17 -- 3. All advertising materials mentioning features or use of this software
18 -- or firmware must display the following acknowledgement:
19 --
20 -- This product includes software developed by the University of
21 -- Technology, Faculty of Information Technology, Brno and its
22 -- contributors.
23 --
24 -- 4. Neither the name of the Company nor the names of its contributors
25 -- may be used to endorse or promote products derived from this
26 -- software without specific prior written permission.
27 --
28 -- This software or firmware is provided ``as is'', and any express or implied
29 -- warranties, including, but not limited to, the implied warranties of
30 -- merchantability and fitness for a particular purpose are disclaimed.
31 -- In no event shall the company or contributors be liable for any
32 -- direct, indirect, incidental, special, exemplary, or consequential
33 -- damages (including, but not limited to, procurement of substitute
34 -- goods or services; loss of use, data, or profits; or business
35 -- interruption) however caused and on any theory of liability, whether
36 -- in contract, strict liability, or tort (including negligence or
37 -- otherwise) arising in any way out of the use of this software, even
38 -- if advised of the possibility of such damage.
39 --
40 -- $Id$
41 --
42 --
43 library IEEE;
44 use IEEE.STD_LOGIC_1164.ALL;
45 use IEEE.STD_LOGIC_ARITH.ALL;
46 use IEEE.STD_LOGIC_UNSIGNED.ALL;
47
48 architecture full of ir_NEC is
49
50 --signaly prijimace
51 type FSMstate is (S_IDLE, S_LEAD1, S_LEAD2, S_REP, S_NORM, S_BIT0, S_BIT1, S_STORE0, S_STORE1, S_CHECK, S_COMPLETE,S_DATA_REP);
52
53 signal pstate : FSMstate;
54 signal nstate : FSMState;
55 signal cnt : std_logic_vector(16 downto 0);
56 signal rep_tmr : std_logic_vector(19 downto 0);
57 signal sh_reg : std_logic_vector(32 downto 0);
58 signal dout : std_logic_vector(23 downto 0);
59 signal sh_rst : std_logic;
60 signal sh_wr : std_logic;
61 signal sh_val : std_logic;
62 signal tim_rst : std_logic;
63 signal data_valid : std_logic;
64 signal recv_complet : std_logic;
65 signal ir_reg_a : std_logic;
66 signal ir_reg_b : std_logic;
67 signal ir_down : std_logic;
68 signal ir_up : std_logic;
69 signal check_ok : std_logic;
70 signal repeat_data : std_logic;
71 signal rep_tout : std_logic;
72 signal last_valid : std_logic;
73 signal rep_tmr_rst : std_logic;
74
75 --signaly vysilace
76 type TFSMstate is (S_IDLE, S_LOAD, S_HEADER, S_NORM, S_MARK, S_BIT0, S_BIT1, S_SHIFT, S_STOP,
77 S_TMRRST1, S_TMRRST2, S_TMRRST3, S_TMRRST4, S_WAIT, S_REPEAT);
78
79 signal tr_pstate : TFSMstate;
80 signal tr_nstate : TFSMState;
81 signal gtics : std_logic_vector(6 downto 0);
82 signal space_cnt : std_logic_vector(13 downto 0);
83 signal tcnt : std_logic_vector(9 downto 0);
84 signal bitcount : std_logic_vector(4 downto 0);
85 signal sh_outreg : std_logic_vector(31 downto 0);
86 signal din : std_logic_vector(31 downto 0);
87 signal irout : std_logic;
88 signal out_en : std_logic;
89 signal gen_cmp : std_logic;
90 signal tx_init : std_logic;
91 signal tics_rst : std_logic;
92 signal dshift : std_logic;
93 signal sh_load : std_logic;
94 signal is_repeat : std_logic;
95
96 begin
97
98 --kontrola prijatych dat na spravnost (komparator)
99 check_ok <= '1' when (sh_reg(24 downto 17) = not sh_reg(32 downto 25)) else
100 '0';
101
102
103 data_valid <= recv_complet and check_ok;
104 DATA_VLD <= data_valid or repeat_data;
105
106
107 --mapovani bitu na sbernici:
108 -- msb | ADR15 - ADR0 | CMD7 - CMD0 | lsb
109 DATA_OUT <= dout(15 downto 0) & dout(23 downto 16);
110
111
112 --klopny obvod RS drzici informaci u platosti predchozich dat
113 last_valid <= '1' when (data_valid='1') else
114 '0' when (rep_tout='1') else
115 last_valid;
116
117 --komparator pro definovani maximalni doby cekani na opakovaci pulz (115ms = cca +5%)
118 rep_tout <= '1' when (rep_tmr="11001111000000000000") else
119 '0';
120
121 rep_tmr_rst <= data_valid or repeat_data or rep_tout;
122
123 --klopny obvod D pro pomatovani prijatych dat (do prichodu dalsich...)
124 process(RST,CLK)
125 begin
126 if (RST='1') then
127 dout <= (others => '0');
128 elsif (CLK'event) and (CLK='1') then
129 if (data_valid='1') then
130 dout <= sh_reg(24 downto 1); --nezajima nas negovana podoba commandu
131 end if;
132 end if;
133 end process;
134
135
136 --detektor vzestupne a sestupne hrany
137 process(RST,CLK)
138 begin
139 if (RST = '1') then
140 ir_reg_a <= '1';
141 ir_reg_b <= '1';
142 elsif (CLK'event) and (CLK = '1') then
143 ir_reg_a <= IR_IN;
144 ir_reg_b <= ir_reg_a;
145 end if;
146 end process;
147 ir_down <= ir_reg_b and (not ir_reg_a);
148 ir_up <= ( not ir_reg_b) and ir_reg_a;
149
150
151 --citac casu pro mereni delky pulzu
152 process(CLK,tim_rst)
153 begin
154 if (tim_rst='1') then
155 cnt <= (others => '0');
156 elsif (CLK'event) and (CLK='1') then
157 cnt <= cnt + 1;
158 end if;
159 end process;
160
161
162 --citac casu pro odpocet delky opakovaciho intervalu
163 process(CLK, rep_tmr_rst)
164 begin
165 if (rep_tmr_rst='1') then
166 rep_tmr <= (others => '0');
167 elsif (CLK'event) and (CLK='1') then
168 rep_tmr <= rep_tmr + 1;
169 end if;
170 end process;
171
172
173 --posuvny registr vystupu
174 -- msb | CMD'7 - CMD'0 | CMD7 - CMD0 | ADR15 - ADR0 | 1 lsb
175 process(sh_rst,CLK)
176 begin
177 if (sh_rst='1') then
178 sh_reg <= "100000000000000000000000000000000";
179 elsif (CLK'event) and (CLK='1') then
180 if (sh_wr='1') then
181 sh_reg <= sh_val & sh_reg(32 downto 1);
182 end if;
183 end if;
184 end process;
185
186
187 --FSM Present State logic
188 process(RST,CLK)
189 begin
190 if (RST='1') then
191 pstate <= S_IDLE;
192 elsif (CLK'event) and (CLK='1') then
193 pstate <= nstate;
194 end if;
195 end process;
196
197
198 --FSM Next State logic
199 process(pstate,ir_down,ir_up,cnt,last_valid,sh_reg)
200 begin
201 nstate <= S_IDLE;
202 tim_rst <= '0';
203 case pstate is
204
205 when S_IDLE =>
206 tim_rst <= '1';
207 nstate <= S_IDLE;
208 if (ir_down='1') then --sestupnou hranou zacni casovat
209 nstate <= S_LEAD1;
210 end if;
211
212 when S_LEAD1 =>
213 nstate <= S_LEAD1;
214 if (cnt="01111011000111101") then --vstup do validniho pasma (8.55ms = -5%)
215 nstate <= S_LEAD2;
216 elsif (ir_up='1') then --leader konci moc brzo -> chyba
217 nstate <= S_IDLE;
218 end if;
219
220 when S_LEAD2 =>
221 nstate <= S_LEAD2;
222 if (cnt="10001000000101000") then --timeout (9.45ms) (+5%)
223 nstate <= S_IDLE;
224 elsif (ir_up='1') then --nacten 9ms leader code, pokracuj
225 tim_rst <= '1';
226 nstate <= S_REP; --detekci typu ramce (REP/NORM)
227 end if;
228
229 when S_REP =>
230 nstate <= S_REP;
231 if (cnt="00110000111101100") then --prepnuti na normalni (3.4ms)
232 nstate <= S_NORM; --(stred mezi 4.5ms a 2.25ms)
233 elsif (ir_down='1') then
234 if (last_valid='1') then
235 nstate <= S_DATA_REP;
236 else
237 nstate <= S_IDLE;
238 end if;
239 end if;
240
241 when S_NORM =>
242 nstate <= S_NORM;
243 if (cnt="01000100000010100") then --vyprseni limitu (4.725ms = +5%)
244 nstate <= S_IDLE;
245 elsif (ir_down='1') then
246 tim_rst <= '1';
247 nstate <= S_BIT0; --vlastni nacitani bitu
248 end if;
249
250 when S_BIT0 =>
251 nstate <= S_BIT0;
252 if (cnt="00011000011110110") then --prepnuti na bit o log 1 (1.7ms)
253 nstate <= S_BIT1; --(stred mezi 1.125ms a 2.25ms)
254 elsif (ir_down='1') then
255 nstate <= S_STORE0; --nacten bit o hodnote "0"
256 end if;
257
258 when S_BIT1 =>
259 nstate <= S_BIT1;
260 if (cnt="00100010000001110") then --vyprseni limitu (2.363ms = +5%)
261 nstate <= S_IDLE;
262 elsif (ir_down='1') then
263 nstate <= S_STORE1; --nacten bit o hodnote "1"
264 end if;
265
266 when S_STORE0 =>
267 tim_rst <= '1';
268 nstate <= S_CHECK;
269
270 when S_STORE1 =>
271 tim_rst <= '1';
272 nstate <= S_CHECK;
273
274 when S_CHECK =>
275 tim_rst <= '1';
276 nstate <= S_BIT0;
277 if (sh_reg(0)='1') then
278 nstate <= S_COMPLETE;
279 end if;
280
281 when S_COMPLETE =>
282 nstate <= S_IDLE;
283
284 when S_DATA_REP =>
285 nstate <= S_IDLE;
286
287 when others => null;
288 end case;
289 end process;
290
291
292 --FSM Output logic
293 process(pstate)
294 begin
295 sh_rst <= '0';
296 recv_complet <= '0';
297 sh_wr <= '0';
298 sh_val <= '0';
299 repeat_data <= '0';
300
301 case pstate is
302 when S_IDLE =>
303 sh_rst <= '1';
304
305 when S_STORE0 =>
306 sh_wr <= '1';
307
308 when S_STORE1 =>
309 sh_val <= '1';
310 sh_wr <= '1';
311
312 when S_COMPLETE =>
313 recv_complet <= '1';
314
315 when S_DATA_REP =>
316 repeat_data <= '1';
317
318 when others => null;
319 end case;
320 end process;
321
322 ------------vysilac--------------------------------------------------------
323
324 --mapovani vstupnich dat do posuvneho registru
325 -- | neg CMD7 - CMD0 | CMD7 - CMD0 | ADR15 - ADR0 |
326 din <= (not DATA_IN(7 downto 0)) & DATA_IN(7 downto 0) & DATA_IN (23 downto 8);
327
328
329 IR_OUT <= irout when (out_en='1') else
330 '0';
331
332 --generator 38kHz (97 x SMCLK) !!!!!!!!!!!!!!!!
333 gen_cmp <= '1' when (gtics="1100001") else '0';
334 process (tx_init,CLK)
335 begin
336 if (tx_init='1') then
337 gtics <= (others => '0');
338 irout <= '0';
339 elsif (CLK='1') and (CLK'event) then
340 if (gen_cmp='1') then
341 gtics <= (others => '0');
342 irout <= not irout;
343 else
344 gtics <= gtics + 1;
345 end if;
346 end if;
347 end process;
348
349
350 --pocitadlo 38kHz pulzu
351 process (tics_rst, CLK)
352 begin
353 if (tics_rst='1') then
354 tcnt <= (others => '0');
355 elsif (CLK='1') and (CLK'event) then
356 if (gen_cmp='1') then
357 tcnt <= tcnt+1;
358 end if;
359 end if;
360 end process;
361
362
363 --pocitadlo vyslanych bitu
364 process (tx_init, CLK)
365 begin
366 if (tx_init='1') then
367 bitcount <= (others => '0');
368 elsif (CLK='1') and (CLK'event) then
369 if (dshift='1') then
370 bitcount <= bitcount+1;
371 end if;
372 end if;
373 end process;
374
375
376 --pocitadlo delky za jakou se bude opakovat ramec
377 process (tx_init, CLK)
378 begin
379 if (tx_init='1') then
380 space_cnt <= (others => '0');
381 elsif (CLK='1') and (CLK'event) then
382 if (gen_cmp='1') then
383 space_cnt <= space_cnt+1;
384 end if;
385 end if;
386 end process;
387
388
389 --posuvny registr s paralelnim vstupem
390 process(CLK)
391 begin
392 if (CLK'event and CLK='1') then
393 if (sh_load='1') then
394 sh_outreg <= din;
395 elsif (dshift='1') then
396 sh_outreg <= '0' & sh_outreg(31 downto 1);
397 end if;
398 end if;
399 end process;
400
401
402 -- registr uchovavaji informaci zda jde o normalni ci opakovaci ramec
403 process(CLK)
404 begin
405 if (CLK'event and CLK='1') then
406 if (WR_REPEAT='1') then
407 is_repeat <= '1';
408 elsif (WRITE_EN='1') then
409 is_repeat <= '0';
410 end if;
411 end if;
412 end process;
413
414
415 --FSM Present State logic
416 process(RST,CLK)
417 begin
418 if (RST='1') then
419 tr_pstate <= S_IDLE;
420 elsif (CLK'event) and (CLK='1') then
421 tr_pstate <= tr_nstate;
422 end if;
423 end process;
424
425
426 --FSM Next State logic
427 process(tr_pstate,WRITE_EN,WR_REPEAT,tcnt,bitcount,space_cnt,sh_outreg)
428 begin
429 tr_nstate <= S_IDLE;
430
431 case tr_pstate is
432
433 when S_IDLE =>
434 tr_nstate <= S_IDLE;
435 if (WRITE_EN='1') then
436 tr_nstate <= S_LOAD;
437 elsif (WR_REPEAT='1') then
438 tr_nstate <= S_HEADER;
439 end if;
440
441 when S_LOAD =>
442 tr_nstate <= S_HEADER;
443
444 when S_HEADER => -- 9ms header
445 tr_nstate <= S_HEADER;
446 if (tcnt="1010101100") then
447 tr_nstate <= S_TMRRST1;
448 end if;
449
450 when S_TMRRST1 =>
451 tr_nstate <= S_NORM;
452 if (is_repeat='1') then
453 tr_nstate <= S_REPEAT;
454 end if;
455
456 when S_REPEAT => -- 2.25ms space
457 tr_nstate <= S_REPEAT;
458 if (tcnt="0010101010") then
459 tr_nstate <= S_TMRRST4;
460 end if;
461
462 when S_NORM => -- 4.5ms space
463 tr_nstate <= S_NORM;
464 if (tcnt="0101010110") then
465 tr_nstate <= S_TMRRST2;
466 end if;
467
468 when S_TMRRST2 =>
469 tr_nstate <= S_MARK;
470
471 when S_MARK => -- 560us mark
472 tr_nstate <= S_MARK;
473 if (tcnt="0000101010") then
474 tr_nstate <= S_TMRRST3;
475 end if;
476
477 when S_TMRRST3 =>
478 if (sh_outreg(0)='1') then
479 tr_nstate <= S_BIT1;
480 else
481 tr_nstate <= S_BIT0;
482 end if;
483
484 when S_BIT0 => -- 565us space
485 tr_nstate <= S_BIT0;
486 if (tcnt="0000101010") then
487 tr_nstate <= S_SHIFT;
488 end if;
489
490 when S_BIT1 => -- 1690us space
491 tr_nstate <= S_BIT1;
492 if (tcnt="0010000000") then
493 tr_nstate <= S_SHIFT;
494 end if;
495
496 when S_SHIFT =>
497 tr_nstate <= S_TMRRST2;
498 if (bitcount="11111") then
499 tr_nstate <= S_TMRRST4;
500 end if;
501
502 when S_TMRRST4 =>
503 tr_nstate <= S_STOP;
504
505 when S_STOP => -- 560us stopbit mark
506 tr_nstate <= S_STOP;
507 if (tcnt="0000101010") then
508 tr_nstate <= S_WAIT;
509 end if;
510
511 when S_WAIT => --ceka 8208 tiku, pak ukonci BUSY priznak
512 tr_nstate <= S_WAIT;
513 if (space_cnt="10000000010000") then
514 tr_nstate <= S_IDLE;
515 end if;
516
517 when others => null;
518 end case;
519 end process;
520
521
522 --FSM Output logic
523 process(tr_pstate)
524 begin
525 tx_init <= '0';
526 BUSY <= '1';
527 sh_load <= '0';
528 out_en <= '0';
529 dshift <= '0';
530 tics_rst <= '0';
531
532 case tr_pstate is
533 when S_IDLE =>
534 tics_rst <= '1';
535 tx_init <= '1';
536 BUSY <= '0';
537
538 when S_LOAD =>
539 tics_rst <= '1';
540 sh_load <= '1';
541 tx_init <= '1';
542
543 when S_HEADER =>
544 out_en <= '1';
545
546 when S_TMRRST1 =>
547 tics_rst <= '1';
548
549 when S_TMRRST2 =>
550 tics_rst <= '1';
551
552 when S_MARK =>
553 out_en <= '1';
554
555 when S_TMRRST3 =>
556 tics_rst <= '1';
557
558 when S_SHIFT =>
559 dshift <= '1';
560
561 when S_TMRRST4 =>
562 tics_rst <= '1';
563
564 when S_STOP =>
565 out_en <= '1';
566
567 when others => null;
568 end case;
569 end process;
570
571 end full;
572