Jste zde

Hrátky s hradlovými poli - 5.

Jednou z periferií kitu, se kterým si hrajeme, je také port pro sériovou komunikaci RS 232. Pokládám proto za logické ukázat, jak tohoto portu můžeme využít ke komunikaci mezi např. PC a hradlovým polem. Tento komunikační modul vzniknul na naší škole pro realizaci maturitního výrobku.

Port RS232

     Komunikaci přes tento port lze charakterizovat jak sériovou, asynchronní, duplexní, s volitelným režimem. Napěťové úrovně neodpovídají TTL úrovním. Podrobnosti najde zájemce např. na stránkách http://rs232.hw.cz/ . Pro další výklad zde však musím uvést, že přenos probíhá konstantní rychlostí v tzv. rámcích.

     Jak ukazuje obrázek, klidový stav je dán úrovní log1 na datovém vodiči. Přenos pak začíná Start bitem s úrovní log0. Následuje přenos datových bitů v počtu podle nastavení režimu. Přenášená informace pak může být doplněna Paritním bitem. Ukončení přenosu je zasláním Stop bitu, který může být zdvojený. Pak už následuje nový přenos nebo klidový stav.
Protože je přenos asynchronní, musí být nějakým způsobem synchronizována činnost přijímače. Toho je dosaženo vyhodnocením sestupné hrany Start impulzu a samozřejmě musí být předem dohodnuta přenosová rychlost. Ta se udává v bitech za sekundu a jednotkou je Baud.

Protože tento port dává velkou spoustu variací nastavení, je třeba se rozhodnout, zda bude univerzálně nastavitelný, nebo bude mít pevně zvolenu jednu z možností. Pro výukové účely byla vybrána druhá varianta a přenos bude nastaven 8 bitový, bez paritního bitu, s jedním Stop bitem a přenosovou rychlostí 115 200.

Programové řešení

     Protože program je určen pro výuku, opět byl celý rozdělen na několik bloků a ty pak byly propojeny ve formě blokového schématu.

     Jak je vidět, je celá komunikace rozdělena do dvou částí. Vysílací Tx a přijímací Rx. Už na první pohled je zřejmé, že vysílač je poměrně jednoduchý. Složitost přijímače je dána tím, že musí být detekován Start bit a jeho sestupná hrana, musí být zajištěna synchronizace s přenosovou rychlostí vysílače a v neposlední řadě musí být také vyhodnoceno ukončení přenosu.

baud

Tento blok tvoří časovou základnu pro zvolenou rychlost komunikace, tj. 115 200 Baud. Tato část programu je v souboru baud.vhd.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity baud is
    Port ( clk : in  STD_LOGIC;
           BaudTick : out  STD_LOGIC);
end baud;

architecture Behavioral of baud is
signal tim : STD_LOGIC_VECTOR (8 downto 0) := "000000000" ;
begin

process (clk) begin
      if clk"event and clk = "1" then
         tim <= tim + 1;
           if tim = "110110010" then 
              BaudTick <= "1";
                tim <= (others => "0");
           else 
             BaudTick <= "0";
      end if;
   end if;
end process;
                         

end Behavioral;

PosCount

Je čtyř bitový čítač, který slouží k řízení paralelně sériového převodu přenášených dat. V downloadu je to soubor PosCount.vhd.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PosCount is
    Port ( tim : in  STD_LOGIC;
             clk : in  STD_LOGIC;
           pos : out  STD_LOGIC_VECTOR (3 downto 0));
end PosCount;

architecture Behavioral of PosCount is
signal count: STD_LOGIC_VECTOR (3 downto 0):= "0000";
begin

process (clk) 
begin
   if clk="1" and clk"event then
        if tim = "1" then
      count <= count + 1;
          end if;
   end if;
end process;

pos <= count;

end Behavioral;

TxModul

Modul představuje srdce celého řešení. K převodu paralelních dat na sériové se používá princip, který zde byl již několikrát použit. Musím se však zmínit o vstupu TxStart, kterým lze řídit odesílání jednotlivých dat. V tomto případě je vstup připojen na log 1 což znamená, že data (ty jsou zadávána z osmice přepínačů) jsou odesílána opakovaně. Příslušný soubor je Tx.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity TxModul is
    Port ( Tx : out  STD_LOGIC;
              TxStart: in  STD_LOGIC;
              clk : in  STD_LOGIC;
              pos : in  STD_LOGIC_VECTOR (3 downto 0);
     pos1: in  STD_LOGIC_VECTOR (7 downto 0));
end TxModul;

architecture Behavioral of TxModul is
signal int : STD_LOGIC;
begin
process (pos, clk, pos1) begin
      if clk"event and clk = "1" then
if TxStart = "1" then
          case (pos (3 downto 0)) is      
          when "0010" => int <= "0";                      --start
          when "0011" => int <= pos1(0);                    --b0
          when "0100" => int <= pos1(1);          --b1     
          when "0101" => int <= pos1(2);                    --b2
          when "0110" => int <= pos1(3);          --b3
          when "0111" => int <= pos1(4);                  --b4
          when "1000" => int <= pos1(5);                   --b5
          when "1001" => int <= pos1(6);          --b6
          when "1010" => int <= pos1(7);           --b7
          when "1011" => int <= "1";                      --stop
                when others => int <= "1";                         
          end case;
     end if;
       end if;
end process;
Tx <= int;

end Behavioral;

Baud16Rx

Tento blok vytváří na straně přijímače časovou základnu s 16 násobnou frekvencí než na straně vysílače. To je podmínkou dobré synchronizace s vysílačem Příslušný soubor Baud16Rx.vhd je k dispozici opět v downloadu.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Baud16Rx is
    Port ( clk : in  STD_LOGIC;
           Baud16Tick : out  STD_LOGIC);
end Baud16Rx;

architecture Behavioral of Baud16Rx is
signal tim: STD_LOGIC_VECTOR(4 downto 0) := "00000";
begin

process (clk) begin
      if clk"event and clk = "1" then
         tim <= tim + 1;
           if tim = "11011" then 
              Baud16Tick <= "1";
                tim <= (others => "0");
           else 
             Baud16Tick <= "0";
      end if;
   end if;
end process;

end Behavioral;

Start                                                                                                  

Úkolem tohoto bloku je detekovat sestupnou hranu Start bitu, tedy detekovat začátek přenosu. V downloadu je to soubor start.vhd.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity start is
    Port ( clk, RxDS, ResS : in  STD_LOGIC;
           enable : out  STD_LOGIC);
end start;

architecture Behavioral of start is

begin

process (clk)
begin
   if clk"event and clk="1" then  
      if ResS="1" then   
         enable <= "0";
      elsif RxDS ="0" then
         enable <= "1";
      end if;
   end if;
end process;
end Behavioral;

RxCount

Tento blok využívá výstupů předchozích dvou a tvoří jej osmi bitový čítač, jehož spuštění je synchronizováno s vysíláním. Odpovídající soubor je v downloadu jako RxCount.vhd.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity RxCount is
    Port ( clk, baud16tick, en, reset : in  STD_LOGIC;
           CountRx : out  STD_LOGIC_VECTOR (7 downto 0));
end RxCount;

architecture Behavioral of RxCount is
signal count: STD_LOGIC_VECTOR (7 downto 0) := "00000000";
begin

process (clk, reset) 
begin
   if reset="1" then 
      count <= (others => "0");
   elsif clk="1" and clk"event then
      if en="1" then
   if baud16tick = "1" then
            count <= count + 1;
end if;
      end if;
   end if;
end process;
CountRx <= count;


end Behavioral;

SerPar

Jak již název napovídá, je tento blok určen k převodu sériové informace na vstupu na paralelní informaci na výstupu. I tento princip již zde byl dříve ukázán a soubor SerPar.vhd je rovněž v downloadu.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SerPar is
    Port ( PosCount : in  STD_LOGIC_VECTOR (7 downto 0);
           clk, RxDSer : in  STD_LOGIC;
           Data : out  STD_LOGIC_VECTOR (7 downto 0));
end SerPar;

architecture Behavioral of SerPar is
signal inter : STD_LOGIC_VECTOR (7 downto 0);
signal inter1: STD_LOGIC;
begin

process(clk)
begin
   if ( clk"event and clk ="1") then 
      case PosCount is
         when "00011000" => inter(0) <= RxDSer; --b0
         when "00101000" => inter(1) <= RxDSer; --b1
         when "00111000" => inter(2) <= RxDSer; --b2
         when "01001000" => inter(3) <= RxDSer; --b3
         when "01011000" => inter(4) <= RxDSer; --b4
         when "01101000" => inter(5) <= RxDSer; --b5
         when "01111000" => inter(6) <= RxDSer; --b6
         when "10001000" => inter(7) <= RxDSer; --b7
         when others => inter1 <= RxDSer ;
      end case;
   end if;
end process;

Data <= inter;

end Behavioral;

reset

Úkolem tohoto obvodu je detekce konce přenosu. Příslušný soubor je reset.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity reset is
    Port ( count152 : in  STD_LOGIC_VECTOR (7 downto 0);
     RxDRes, clk : in STD_LOGIC;
               res , DataReady : out  STD_LOGIC);
end reset;

architecture Behavioral of reset is
signal inter : STD_LOGIC_VECTOR (1 downto 0);
begin

process(clk)
   begin
      if ( clk"event and clk ="1") then
          if RxDRes = "1" then
              case count152 is
                  when "10010111" => inter <= "10";
                  when "10011000" => inter <= "01";
                  when others => inter <= "00";
              end case;
          else
              case count152 is
         when "10010111" => inter <= "00";
                  when "10011000" => inter <= "01";
                  when others => inter <= "00";
             end case;
          end if;
      end if;
end process;

res <= inter(0);

DataReady <= inter(1);

end Behavioral;

RxModul

Poslední částí přijímače portu RS 232 je modul, který přebírá uchovává přijatá data. Příslušný soubor se nazývá RxModul.vhd.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity RxModul is
    Port ( clk, en : in  STD_LOGIC;
           Data : in  STD_LOGIC_VECTOR (7 downto 0);
           DataOut : out  STD_LOGIC_VECTOR (7 downto 0));
end RxModul;

architecture Behavioral of RxModul is

begin

process (clk)
begin
   if (clk"event and clk="1") then 
      if en = "1" then 
         DataOut <= Data;
      end if; 
   end if;
end process;
 
end Behavioral;

Závěr

     Samozřejmě v downloadu, kromě příslušných souborů, najdete také ucf soubor potřebný při fyzické zkoušce programu. Pokud tedy nahrajete program do obvodu a připojíte kit na COM port počítače, můžete pomocí vhodného komunikačního programu vzájemnou komunikaci vyzkoušet. Výborný program najdete na stránkách www.papouch.com/ jako COM Port Monitor.

Jiří Král
jiri.kral@ roznovskastredni.cz

Downloads&Odkazy

Hodnocení článku: