Aktuální adresář: FITkit /
trunk /
fpga /
ctrls /
infra /
sirc_full.vhd
1 -- sirc_full.vhd: Sony SIRC 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_SIRC is
49
50 --signaly prijimace
51 type FSMstate is (S_IDLE, S_LEAD1, S_LEAD2, S_SPACE, S_BSTART, S_BIT0, S_BIT1, S_STORE0, S_STORE1, S_12_FINISH, S_15_FINISH, S_20_FINISH);
52
53 signal pstate : FSMstate;
54 signal nstate : FSMState;
55 signal cnt : std_logic_vector(14 downto 0);
56 signal sh_reg : std_logic_vector(19 downto 0);
57 signal dout : std_logic_vector(22 downto 0);
58 signal reccount : std_logic_vector(4 downto 0);
59 signal format_out : std_logic_vector(22 downto 0);
60 signal format : std_logic_vector(1 downto 0);
61 signal sh_rst : std_logic;
62 signal sh_wr : std_logic;
63 signal sh_val : std_logic;
64 signal tim_rst : std_logic;
65 signal data12_valid : std_logic;
66 signal data15_valid : std_logic;
67 signal data20_valid : std_logic;
68 signal ir_reg_a : std_logic;
69 signal ir_reg_b : std_logic;
70 signal ir_down : std_logic;
71 signal ir_up : std_logic;
72
73 --signaly vysilace
74 type TFSMstate is (S_IDLE, S_LOAD, S_HEADER, S_SPACE, S_DECISION, S_BIT0, S_BIT1, S_SHIFT, S_WAIT, S_TMRRST);
75
76 signal tr_pstate : TFSMstate;
77 signal tr_nstate : TFSMState;
78 signal gtics : std_logic_vector(6 downto 0);
79 signal space_cnt : std_logic_vector(11 downto 0);
80 signal tcnt : std_logic_vector(7 downto 0);
81 signal bitcount : std_logic_vector(4 downto 0);
82 signal comp_val : std_logic_vector(4 downto 0);
83 signal sh_outreg : std_logic_vector(19 downto 0);
84 signal din : std_logic_vector(19 downto 0);
85 signal tx_init : std_logic;
86 signal irout : std_logic;
87 signal out_en : std_logic;
88 signal all_sent : std_logic;
89 signal write_en : std_logic;
90 signal dshift : std_logic;
91 signal gen_cmp : std_logic;
92 signal tics_rst : std_logic;
93 signal sh_load : std_logic;
94
95 begin
96
97 DATA_12_VLD <= data12_valid;
98 DATA_15_VLD <= data15_valid;
99 DATA_20_VLD <= data20_valid;
100
101 --mapovani bitu na sbernici:
102 -- | 00000000 | 000 ADR4- ADR0 | 0 CMD6 - CMD0 | 12 bit verze
103 -- | 00000000 | ADR7 - ADR0 | 0 CMD6 - CMD0 | 15 bit verze
104 -- | EX7 - EX0| 000 ADR4- ADR0 | 0 CMD6 - CMD0 | 20 bit verze
105 DATA_OUT <= dout(22 downto 7)&'0'&dout(6 downto 0);
106
107
108 --multiplexer pro vyber vyrianty ulozeni (12bit / 15 / 20 bit)
109 format_out <= "00000000000"&sh_reg(19 downto 15)&sh_reg(14 downto 8) when (format = "00") else
110 "00000000"&sh_reg(19 downto 12)&sh_reg(11 downto 5) when (format = "01") else
111 sh_reg(19 downto 12)&"000"&sh_reg(11 downto 7)&sh_reg(6 downto 0);
112
113
114 --klopny obvod D pro pomatovani prijatych dat (do prichodu dalsich...)
115 process(RST,CLK)
116 begin
117 if (RST='1') then
118 dout <= (others => '0');
119 elsif (CLK'event) and (CLK='1') then
120 if ((data12_valid or data15_valid or data20_valid)='1') then
121 dout <= format_out;
122 end if;
123 end if;
124 end process;
125
126
127 --detektor vzestupne a sestupne hrany
128 process(RST,CLK)
129 begin
130 if (RST = '1') then
131 ir_reg_a <= '1';
132 ir_reg_b <= '1';
133 elsif (CLK'event) and (CLK = '1') then
134 ir_reg_a <= IR_IN;
135 ir_reg_b <= ir_reg_a;
136 end if;
137 end process;
138 ir_down <= ir_reg_b and (not ir_reg_a);
139 ir_up <= ( not ir_reg_b) and ir_reg_a;
140
141
142 --citac casu pro mereni delky pulzu
143 process(CLK,tim_rst)
144 begin
145 if (tim_rst='1') then
146 cnt <= (others => '0');
147 elsif (CLK'event) and (CLK='1') then
148 cnt <= cnt + 1;
149 end if;
150 end process;
151
152
153 --pocitadlo prijatych bitu (stejny reset jako posuvny registr!)
154 process (sh_rst, CLK)
155 begin
156 if (sh_rst='1') then
157 reccount <= (others => '0');
158 elsif (CLK='1') and (CLK'event) then
159 if (sh_wr='1') then
160 reccount <= reccount+1;
161 end if;
162 end if;
163 end process;
164
165
166 --posuvny registr vystupu
167 -- msb | ADR4 - ADR0 | CMD6 - CMD0 | 00000000 | lsb
168 -- msb | ADR7 - ADR0 | CMD6 - CMD0 | 00000 | lsb
169 -- msb | EXT7 - EXT0 | ADR4 - ADR0 | CMD6 - CMD0 | lsb
170 process(sh_rst,CLK)
171 begin
172 if (sh_rst='1') then
173 sh_reg <= (others => '0');
174 elsif (CLK'event) and (CLK='1') then
175 if (sh_wr='1') then
176 sh_reg <= sh_val & sh_reg(19 downto 1);
177 end if;
178 end if;
179 end process;
180
181
182 --FSM Present State logic
183 process(RST,CLK)
184 begin
185 if (RST='1') then
186 pstate <= S_IDLE;
187 elsif (CLK'event) and (CLK='1') then
188 pstate <= nstate;
189 end if;
190 end process;
191
192
193 --FSM Next State logic
194 process(pstate,ir_down,ir_up,cnt,reccount)
195 begin
196 nstate <= S_IDLE;
197 tim_rst <= '0';
198 case pstate is
199
200 when S_IDLE =>
201 tim_rst <= '1';
202 nstate <= S_IDLE;
203 if (ir_down='1') then --sestupnou hranou zacni casovat
204 nstate <= S_LEAD1;
205 end if;
206
207 when S_LEAD1 =>
208 nstate <= S_LEAD1;
209 if (cnt="100000110101001") then --vstup do validniho pasma (2.28ms = -5%)
210 nstate <= S_LEAD2;
211 elsif (ir_up='1') then --leader konci moc brzo -> chyba
212 nstate <= S_IDLE;
213 end if;
214
215 when S_LEAD2 =>
216 nstate <= S_LEAD2;
217 if (cnt="100100010010011") then --timeout (2.52ms = +5%) -> chyba
218 nstate <= S_IDLE;
219 elsif (ir_up='1') then --nacten 2.4ms leader code, pokracuj
220 tim_rst <= '1';
221 nstate <= S_SPACE;
222 end if;
223
224 when S_SPACE =>
225 nstate <= S_SPACE;
226 if (ir_down='1') then
227 tim_rst <= '1';
228 nstate <= S_BSTART; --zacatek dalsiho pulzu -> OK
229 elsif (cnt="001001000100101") then --timeout 630us pro mezeru:
230 if (reccount="01100") then
231 nstate <= S_12_FINISH; --nacteno 12 bitu -> OK
232 elsif (reccount="01111") then
233 nstate <= S_15_FINISH; --nacteno 15 bitu -> OK
234 elsif (reccount="10100") then
235 nstate <= S_20_FINISH; --nacteno 20 bitu -> OK
236 else
237 nstate <= S_IDLE; --pocet nesedi -> CHYBA!
238 end if;
239 end if;
240
241 when S_BSTART => --zacatek nacitani BITu
242 nstate <= S_BSTART;
243 if (ir_up='1') then --nesmi prijit konec pulzu
244 nstate <= S_IDLE;
245 elsif (cnt="001000001101010") then --vstup do bitu 0 (570us = -5%)
246 nstate <= S_BIT0;
247 end if;
248
249 when S_BIT0 =>
250 nstate <= S_BIT0;
251 if (ir_up='1') then
252 nstate <= S_STORE0; --nacten bit o hodnote '0'
253 elsif (cnt="001100111101011") then -- 0.9ms = prechod do nacitani 1
254 nstate <= S_BIT1; -- ( = stred mezi 0.6ms a 1.2ms)
255 end if;
256
257 when S_BIT1 =>
258 nstate <= S_BIT1;
259 if (ir_up='1') then
260 nstate <= S_STORE1; --nacten bit o hodnote '1'
261 elsif (cnt="010010101010011") then -- 1.29ms (= +8%) timeout -> chyba
262 nstate <= S_IDLE;
263 end if;
264
265 when S_STORE0 =>
266 tim_rst <= '1';
267 nstate <= S_SPACE;
268
269 when S_STORE1 =>
270 tim_rst <= '1';
271 nstate <= S_SPACE;
272
273 when S_12_FINISH =>
274 nstate <= S_IDLE;
275
276 when S_15_FINISH =>
277 nstate <= S_IDLE;
278
279 when S_20_FINISH =>
280 nstate <= S_IDLE;
281
282 when others => null;
283 end case;
284 end process;
285
286
287 --FSM Output logic
288 process(pstate)
289 begin
290 sh_rst <= '0';
291 sh_wr <= '0';
292 sh_val <= '0';
293 data12_valid <= '0';
294 data15_valid <= '0';
295 data20_valid <= '0';
296 format <= "00";
297
298 case pstate is
299 when S_IDLE =>
300 sh_rst <= '1';
301
302 when S_STORE0 =>
303 sh_wr <= '1';
304
305 when S_STORE1 =>
306 sh_val <= '1';
307 sh_wr <= '1';
308
309 when S_12_FINISH =>
310 data12_valid <= '1';
311
312 when S_15_FINISH =>
313 data15_valid <= '1';
314 format <= "01";
315
316 when S_20_FINISH =>
317 data20_valid <= '1';
318 format <= "10";
319
320 when others => null;
321 end case;
322 end process;
323
324 ------------------------------ vysilac ----------------------------------------
325
326 --mapovani na vstup:
327 -- kus sbernice je sdilen -> nutne osetrit v SW aby nesla zadat vetsi adresa!
328 -- | ADR4 - ADR0 | CMD6 - CMD0 | 12bit
329 -- | ADR7 - ADR5 | ADR4 - ADR0 | CMD6 - CMD0 | 15bit
330 -- | EXT7 - EXT3 | EXT2 - EXT0 | ADR4 - ADR0 | CMD6 - CMD0 | 20bit
331 din <= DATA_IN(23 downto 19)&(DATA_IN(18 downto 16) or DATA_IN(15 downto 13))&DATA_IN(12 downto 8)&DATA_IN(6 downto 0);
332
333 IR_OUT <= irout when (out_en='1') else
334 '0';
335
336 --generator 40kHz (92 x SMCLK) !!!!!!!!!!!!!!!!
337 gen_cmp <= '1' when (gtics="1011100") else '0';
338 process (tx_init,CLK)
339 begin
340 if (tx_init='1') then
341 gtics <= (others => '0');
342 irout <= '0';
343 elsif (CLK='1') and (CLK'event) then
344 if (gen_cmp='1') then
345 gtics <= (others => '0');
346 irout <= not irout;
347 else
348 gtics <= gtics + 1;
349 end if;
350 end if;
351 end process;
352
353
354 --pocitadlo 40kHz pulzu (casovani delek)
355 process (tics_rst, CLK)
356 begin
357 if (tics_rst='1') then
358 tcnt <= (others => '0');
359 elsif (CLK='1') and (CLK'event) then
360 if (gen_cmp='1') then
361 tcnt <= tcnt+1;
362 end if;
363 end if;
364 end process;
365
366
367 --posuvny registr s paralelnim vstupem
368 process(CLK)
369 begin
370 if (CLK'event and CLK='1') then
371 if (sh_load='1') then
372 sh_outreg <= din;
373 elsif (dshift='1') then
374 sh_outreg <= '0' & sh_outreg(19 downto 1);
375 end if;
376 end if;
377 end process;
378
379
380 --pocitadlo vyslanych bitu
381 process (tx_init, CLK)
382 begin
383 if (tx_init='1') then
384 bitcount <= (others => '0');
385 elsif (CLK='1') and (CLK'event) then
386 if (dshift='1') then
387 bitcount <= bitcount+1;
388 end if;
389 end if;
390 end process;
391
392
393 --generovani zapisoveho signalu
394 write_en <= (WRITE_12_EN or WRITE_15_EN or WRITE_20_EN);
395
396
397 --D flipflop pro pomatovani hodnoty ke komparaci (pocet bitu)
398 process(CLK)
399 begin
400 if (CLK'event) and (CLK='1') then
401 if (write_en='1') then
402 if (WRITE_12_EN='1') then
403 comp_val <= "01100"; --12 bitu
404 elsif (WRITE_15_EN='1') then
405 comp_val <= "01111"; --15 bitu
406 else
407 comp_val <= "10100"; --20 bitu
408 end if;
409 end if;
410 end if;
411 end process;
412
413
414 --komparator vraci '1' pokud se pocet vyslanych bitu shoduje s danou verzi protokolu
415 all_sent <= '1' when (bitcount=comp_val) else
416 '0';
417
418
419 --pocitadlo doby za jakou se bude opakovat ramec
420 process (tx_init, CLK)
421 begin
422 if (tx_init='1') then
423 space_cnt <= (others => '0');
424 elsif (CLK='1') and (CLK'event) then
425 if (gen_cmp='1') then
426 space_cnt <= space_cnt+1;
427 end if;
428 end if;
429 end process;
430
431
432 --FSM Present State logic
433 process(RST,CLK)
434 begin
435 if (RST='1') then
436 tr_pstate <= S_IDLE;
437 elsif (CLK'event) and (CLK='1') then
438 tr_pstate <= tr_nstate;
439 end if;
440 end process;
441
442
443 --FSM Next State logic
444 process(tr_pstate,write_en,tcnt,all_sent,sh_outreg)
445 begin
446 tr_nstate <= S_IDLE;
447
448 case tr_pstate is
449
450 when S_IDLE =>
451 tr_nstate <= S_IDLE;
452 if (write_en='1') then
453 tr_nstate <= S_LOAD;
454 end if;
455
456 when S_LOAD => -- naplneni posuvneho registru
457 tr_nstate <= S_HEADER;
458
459 when S_HEADER => -- 2.4ms header
460 tr_nstate <= S_HEADER;
461 if (tcnt="11000000") then
462 tr_nstate <= S_TMRRST;
463 end if;
464
465 when S_TMRRST =>
466 tr_nstate <= S_SPACE;
467
468 when S_SPACE => -- 0.6ms space
469 tr_nstate <= S_SPACE;
470 if (tcnt="00110000") then
471 tr_nstate <= S_DECISION;
472 end if;
473
474 when S_DECISION =>
475 if (all_sent='1') then --pokud vse preneseno, prejdi na cekani
476 tr_nstate <= S_WAIT;
477 elsif (sh_outreg(0)='1') then
478 tr_nstate <= S_BIT1; --bude se prenaset log 1
479 else
480 tr_nstate <= S_BIT0; --jinak 0
481 end if;
482
483 when S_BIT0 => -- 0.6ms mark pro logickou uroven 0
484 tr_nstate <= S_BIT0;
485 if (tcnt="00110000") then
486 tr_nstate <= S_SHIFT;
487 end if;
488
489 when S_BIT1 => -- 1.2ms mark pro logickou uroven 1
490 tr_nstate <= S_BIT1;
491 if (tcnt="01100000") then
492 tr_nstate <= S_SHIFT;
493 end if;
494
495 when S_SHIFT => --posuv datoveho registru doprava
496 tr_nstate <= S_SPACE;
497
498 when S_WAIT => --ceka do doby 42ms, pak ukonci BUSY priznak
499 tr_nstate <= S_WAIT;
500 if (space_cnt="110100100000") then
501 tr_nstate <= S_IDLE;
502 end if;
503
504 when others => null;
505 end case;
506 end process;
507
508
509 --FSM Output logic
510 process(tr_pstate)
511 begin
512 tx_init <= '0';
513 BUSY <= '1';
514 sh_load <= '0';
515 out_en <= '0';
516 dshift <= '0';
517 tics_rst <= '0';
518
519 case tr_pstate is
520 when S_IDLE =>
521 tics_rst <= '1';
522 tx_init <= '1';
523 BUSY <= '0';
524
525 when S_LOAD =>
526 tics_rst <= '1';
527 sh_load <= '1';
528 tx_init <= '1';
529
530 when S_HEADER =>
531 out_en <= '1';
532
533 when S_TMRRST =>
534 tics_rst <= '1';
535
536 when S_DECISION =>
537 tics_rst <= '1';
538
539 when S_SHIFT =>
540 dshift <= '1';
541 tics_rst <= '1';
542
543 when S_BIT1 =>
544 out_en <= '1';
545
546 when S_BIT0 =>
547 out_en <= '1';
548
549 when others => null;
550 end case;
551 end process;
552
553 end full;
554