Čeština / English
Login

SVN Repository / Prohlížení

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  
Zobrazeno: 679483x Naposledy: 25.6.2022 22:30:45