Aktuální adresář: FITkit /
trunk /
fpga /
ctrls /
infra /
rc5_full.vhd
1 -- rc5_full.vhd: Philips RC5x 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_RC5 is
49
50 ------ signaly prijimace --------
51 type FSMstate is (S_IDLE, S_WAIT, S_RECV, S_CNTRSET, S_SPACE1, S_SPACE2, S_COMPLETE);
52
53 signal pstate : FSMstate;
54 signal nstate : FSMState;
55
56 signal cnt : std_logic_vector(18 downto 0);
57 signal cnt_rst : std_logic;
58 signal cnt_en : std_logic;
59
60 signal ir_reg_a : std_logic;
61 signal ir_reg_b : std_logic;
62 signal ir_down : std_logic;
63 signal ir_up : std_logic;
64
65 signal timeout_en : std_logic;
66 signal timeout : std_logic;
67 signal reset : std_logic; --reset prijimace
68
69 signal sh_wr : std_logic;
70 signal sh_en : std_logic;
71 signal sh_rst : std_logic;
72 signal sh_val : std_logic;
73 signal data_shreg : std_logic_vector(13 downto 0);
74 signal dout : std_logic_vector(12 downto 0);
75 signal data_valid : std_logic;
76
77
78 -------- signaly vysilace ---------
79 type TrFSMstate is (S_IDLE, S_LOAD, S_TRANS, S_WAIT);
80
81 signal tr_pstate : TrFSMstate;
82 signal tr_nstate : TrFSMstate;
83
84 signal tx_init : std_logic; --reset komponent vysilace
85 signal gen_cmp : std_logic;
86 signal dclk : std_logic;
87 signal sh_load : std_logic;
88 signal data_end : std_logic;
89 signal frame_end : std_logic;
90 signal out_en : std_logic;
91
92 signal din : std_logic_vector(13 downto 0);
93 signal sh_reg : std_logic_vector(13 downto 0);
94 signal gtics : std_logic_vector(6 downto 0);
95 signal pcount : std_logic_vector(12 downto 0);
96
97 -------------------------------------------------------------------------------
98 begin
99
100 --------- POPIS PRIJIMACE --------
101
102 DATA_VLD <= data_valid;
103
104 --mapovani 13bitu dat na 24bit sbernici:
105 -- msb | 0 0 0 0 0 0 0 TB | 0 0 0 ADR4 - ADR0 | 0 CMD6 - CMD0 | lsb
106 DATA_OUT <= "0000000"&dout(11)&"000"&dout(10 downto 6)&'0'&(not dout(12))&dout(5 downto 0);
107
108 --klopny obvod D pro pomatovani prijatych dat (do prichodu dalsich...)
109 process(RST,CLK)
110 begin
111 if (RST='1') then
112 dout <= (others => '0');
113 elsif (CLK'event) and (CLK='1') then
114 if (data_valid='1') then
115 dout <= data_shreg(12 downto 0);
116 end if;
117 end if;
118 end process;
119
120 --detektor vzestupne a sestupne hrany
121 process(reset,CLK)
122 begin
123 if (reset = '1') then
124 ir_reg_a <= '1';
125 ir_reg_b <= '1';
126 elsif (CLK'event) and (CLK = '1') then
127 ir_reg_a <= IR_IN;
128 ir_reg_b <= ir_reg_a;
129 end if;
130 end process;
131 ir_down <= ir_reg_b and (not ir_reg_a);
132 ir_up <= ( not ir_reg_b) and ir_reg_a;
133
134
135 --hodnota do shift registru dana smerem hrany (dolu=1, nahoru=0)
136 --staci ir_down protoze nemuzou nikdy byt oba v "1"
137 sh_val <= ir_down;
138
139
140 --signal povoluje zapis do posuvneho registru, v pripade nejake hrany
141 sh_wr <= (ir_down or ir_up) and sh_en;
142
143
144 --po dosazeni urciteho casu generovan timeout
145 --timeout za 2*889us + 1/4*889us
146 timeout <= '1' when (cnt="0000011100110011011") else '0';
147
148 --signal reset jednak vstupnim RST, dale take timeoutem
149 reset <= RST or (timeout and timeout_en);
150
151 --posuvny registr vystupu / format dat v data_shreg:
152 -- msb | SB | CMD6 | TB | ADR4 - ADR0 | CMD5 - CMD0 | lsb
153 process(sh_rst,CLK)
154 begin
155 if (sh_rst='1') then
156 data_shreg <= "00000000000001";
157 elsif (CLK'event) and (CLK='1') then
158 if (sh_wr='1') then
159 data_shreg <= data_shreg(12 downto 0) & sh_val;
160 end if;
161 end if;
162 end process;
163
164
165 --citac casu
166 process(CLK,cnt_rst)
167 begin
168 if (cnt_rst='1') then
169 cnt <= (others => '0');
170 elsif (CLK'event) and (CLK='1') then
171 if (cnt_en='1') then
172 cnt <= cnt + 1;
173 end if;
174 end if;
175 end process;
176
177
178 --FSM Present State logic
179 process(reset,CLK)
180 begin
181 if (reset='1') then
182 pstate <= S_IDLE;
183 elsif (CLK'event) and (CLK='1') then
184 pstate <= nstate;
185 end if;
186 end process;
187
188
189 --FSM Next State logic
190 process(pstate,ir_down,sh_wr,cnt,data_shreg)
191 begin
192 nstate <= S_IDLE;
193 case pstate is
194
195 when S_IDLE =>
196 nstate <= S_IDLE;
197 if (ir_down='1') then
198 nstate <= S_WAIT;
199 end if;
200
201 when S_WAIT =>
202 nstate <= S_WAIT;
203 --dalsi korektni pulz ocekavan za 889us + 3/4*889us
204 if (cnt="0000010110011001110") then
205 nstate <= S_RECV;
206 end if;
207
208 when S_RECV =>
209 nstate <= S_RECV;
210 if (data_shreg(13)='1') then
211 nstate <= S_SPACE1;
212 elsif (sh_wr='1') then
213 nstate <= S_CNTRSET;
214 end if;
215
216 when S_CNTRSET =>
217 nstate <= S_WAIT;
218
219 when S_SPACE1 =>
220 nstate <= S_SPACE2;
221
222 when S_SPACE2 =>
223 nstate <= S_SPACE2;
224 if (ir_down='1') then
225 nstate <= S_IDLE;
226 --po dobu 71ms nesmi prijit zadny pulz! (113ms perioda ramcu)
227 elsif (cnt="1111111111111111111") then
228 nstate <= S_COMPLETE;
229 end if;
230
231 when S_COMPLETE =>
232 nstate <= S_IDLE;
233
234 when others => null;
235 end case;
236 end process;
237
238
239 --FSM Output logic
240 process(pstate)
241 begin
242 cnt_rst <= '0';
243 sh_rst <= '0';
244 data_valid <= '0';
245 sh_en <= '0';
246 cnt_en <= '0';
247 timeout_en <= '1';
248 case pstate is
249 when S_IDLE =>
250 cnt_rst <= '1';
251 sh_rst <= '1';
252
253 when S_WAIT =>
254 cnt_en <= '1';
255
256 when S_RECV =>
257 sh_en <= '1';
258 cnt_en <= '1';
259
260 when S_CNTRSET =>
261 cnt_rst <= '1';
262
263 when S_SPACE1 =>
264 cnt_rst <= '1';
265
266 when S_SPACE2 =>
267 cnt_en <= '1';
268 timeout_en <= '0';
269
270 when S_COMPLETE =>
271 data_valid <= '1';
272
273 when others => null;
274 end case;
275 end process;
276
277
278 --------- POPIS VYSILACE --------
279
280 --mapovani: msb | SB | CMD6 | TB | ADR4 - ADR0 | CMD5 - CMD0 | lsb
281 din <= '1'&(not DATA_IN(6))&DATA_IN(16)&DATA_IN(12 downto 8)&DATA_IN(5 downto 0);
282
283 IR_OUT <= pcount(0) when (((dclk xor sh_reg(13)) and out_en)='1') else '0';
284
285 --generator 36kHz (102 * SMCLK)
286 gen_cmp <= '1' when (gtics="1100101") else '0';
287 process (tx_init,CLK)
288 begin
289 if (tx_init='1') then
290 gtics <= (others => '0');
291 elsif (CLK='1') and (CLK'event) then
292 if (gen_cmp='1') then
293 gtics <= (others => '0');
294 else
295 gtics <= gtics + 1;
296 end if;
297 end if;
298 end process;
299
300
301 --pocitadlo 36kHz pulzu
302 process (tx_init, CLK)
303 begin
304 if (tx_init='1') then
305 pcount <= (others => '0');
306 elsif (CLK='1') and (CLK'event) then
307 if (gen_cmp='1') then
308 pcount <= pcount+1;
309 end if;
310 end if;
311 end process;
312
313
314 --komparator pro detekci konce prenosu posledniho bitu
315 data_end <= '1' when (pcount="0011011000000") else
316 '0';
317
318 --komparator pro detekci konce prenosu celeho ramce
319 frame_end <= '1' when (pcount="1111111111111") else
320 '0';
321
322 --datove hodiny (32*36kHz)
323 dclk <= pcount(6);
324
325
326 --posuvny registr s asynchronnim paralelnim vstupem
327 process(dclk,sh_load)
328 begin
329 if (sh_load='1') then
330 sh_reg <= din;
331 elsif (dclk'event and dclk='1') then
332 sh_reg <= sh_reg(12 downto 0) & '0';
333 end if;
334 end process;
335
336
337 --FSM Present State logic
338 process(RST,CLK)
339 begin
340 if (RST='1') then
341 tr_pstate <= S_IDLE;
342 elsif (CLK'event) and (CLK='1') then
343 tr_pstate <= tr_nstate;
344 end if;
345 end process;
346
347
348 --FSM Next State logic
349 process(tr_pstate,WRITE_EN,data_end,frame_end)
350 begin
351 tr_nstate <= S_IDLE;
352 case tr_pstate is
353
354 when S_IDLE =>
355 tr_nstate <= S_IDLE;
356 if (WRITE_EN='1') then
357 tr_nstate <= S_LOAD;
358 end if;
359
360 when S_LOAD =>
361 tr_nstate <= S_TRANS;
362
363 when S_TRANS =>
364 tr_nstate <= S_TRANS;
365 if (data_end='1') then
366 tr_nstate <= S_WAIT;
367 end if;
368
369 when S_WAIT =>
370 tr_nstate <= S_WAIT;
371 if (frame_end='1') then
372 tr_nstate <= S_IDLE;
373 end if;
374
375 when others => null;
376 end case;
377 end process;
378
379
380 --FSM Output logic
381 process(tr_pstate)
382 begin
383 tx_init <= '0';
384 BUSY <= '1';
385 sh_load <= '0';
386 out_en <= '0';
387
388 case tr_pstate is
389 when S_IDLE =>
390 tx_init <= '1';
391 BUSY <= '0';
392
393 when S_LOAD =>
394 tx_init <= '1';
395 sh_load <= '1';
396
397 when S_TRANS =>
398 out_en <= '1';
399
400 when others => null;
401 end case;
402 end process;
403
404 end full;
405
406