Skocz do zawartości

Pomocna odpowiedź

Napisano (edytowany)

Cześć

W tym wpisie zamieszczam kody UART nadajnika i odbiornika.

Kod nadajnika:

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

entity UARTTX is
    Port ( 
           CLK   : in  STD_LOGIC; -- 100MHz
           RST   : in  STD_LOGIC; -- Reset aktywny = 0
           WR    : in  STD_LOGIC; -- impuls jednego taktu inicjujący zapis danych do transmitera
           DI    : in  STD_LOGIC_VECTOR (7 downto 0); -- dane wejściowe do wysłania
           ACK   : out STD_LOGIC; -- impuls jednego taktu potwierdzający koniec trasmisji
           TX    : out STD_LOGIC  -- wyjście danych UART prędkość 9600
         );
end UARTTX;

architecture Behavioral of UARTTX is

   signal Cnt : std_logic_vector (13 downto 0) := (others => '0');
   signal Shr : std_logic_vector (9 downto 0)  := (others => '1');
   signal CntEn : std_logic := '0';
   signal Sp, ACK0, ACK1 : std_logic;

begin


   -- Wyznaczanie punktów czasowych
   Sp <= '1' when Cnt = "10100010110000" else '0'; -- 10 417 taktów zegara, ok 104,17 μ s
   
   process(CLK, RST)
   begin
      if RST = '0' then
         Shr <= (others => '1');
         Cnt <= (others => '0');
      elsif rising_edge(CLK) then
         -- Detekcja zbocza opadającego sygnału CntEn do wygenerowania impulsu ACK
         ACK0 <= CntEn;
         ACK1 <= ACK0;
         if CntEn = '1' then
            if Sp = '1' then
               Cnt <= (others => '0');
               -- Sprawdzenie, czy w rejestrze przesuwnym pozostał tylko ostatni bit stopu
               if Shr(9 downto 0) = "0000000001" then
                  CntEn <= '0'; -- Zakończenie transmisji
               else
                  Shr <= '0' & Shr(9 downto 1); -- Przesunięcie bitowe w prawo
               end if;
            else
               Cnt <= Cnt + 1;
            end if;
         else
            if WR = '1' then
               CntEn <= '1';
               -- Załadowanie ramki: Bit stopu ('1') & Dane (8 bitów) & Bit startu ('0')
               Shr <= "1" & DI & '0';
            end if;
            Cnt <= (others => '0');
         end if;
      end if;
   end process;

   -- Wygenerowanie szpilki ACK (jeden takt zegara) po opadnięciu flagi CntEn
   ACK <= ACK1 and not ACK0;
   
   -- Wyprowadzenie najmłodszego bitu rejestru na linię TX
   TX <= Shr(0);

end Behavioral;

Kod odbiornika:

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

entity UARTRX is
    Port ( 
           CLK : in  STD_LOGIC; --100MHZ
           RST : in  STD_LOGIC; --Reset aktywny = 0
           RX  : in  STD_LOGIC; --Wejście danych UART 9600
           ACK : out STD_LOGIC; --Impuls jednego taktu potwierdzającego koniec transmisji 
           DO  : out STD_LOGIC_VECTOR (7 downto 0) --wyjście danych próbkowanych na linii UART
         );
end UARTRX;

architecture Behavioral of UARTRX is

   signal Cnt : std_logic_vector (12 downto 0);
   signal Shr : std_logic_vector (9 downto 0) := (others => '1');
   signal Sp, ACK0, RX0, RX1 : std_logic;
   signal CntEn : std_logic := '0';
   signal Bp : std_logic := '0';

begin

   -- Wyznaczanie punktów czasowych
   Sp <= '1' when Cnt = "1010001011000" else '0'; -- 5208 taktów, ok 52,08 μs.
   
   process(CLK, RST)
   begin
      if RST = '0' then
         Shr <= (others => '1');
         Cnt <= (others => '0');
         DO <= (others => '1');
         CntEn <= '0';
         Bp <= '0';
      elsif rising_edge(CLK) then
         -- Dwustopniowy rejestr synchronizacji wejścia (eliminacja metastabilności)
         RX0 <= RX;
         RX1 <= RX0;
         ACK0 <= CntEn;
         ACK <= ACK0 and not CntEn;
         if CntEn = '1' then
            if Sp = '1' then
               Bp <= not Bp;
               Cnt <= (others => '0');
               if Bp = '0' then
                  -- Sprawdzenie bitu startu (0) oraz stopu (1) na krańcach rejestru przesuwnego
                  if ((Shr(9) = '1') and (Shr(0) = '0')) then
                     DO <= Shr(8 downto 1); -- Przepisanie odebranych danych na wyjście
                     Shr <= (others => '1');
                     Cnt <= (others => '0');
                     CntEn <= '0';
                     Bp <= '1';
                  else
                     Shr <= RX1 & Shr(9 downto 1);
                  end if;
               end if;
            else
               Cnt <= Cnt + 1;
            end if;
         else
            -- Wykrycie zbocza opadającego bitu startu
            if ((RX1 = '0') and (RX0 = '0')) then
               Bp <= '0';
               CntEn <= '1';
            end if;
         end if;
      end if;
   end process; 


end Behavioral;

 

 Moduły UARTTX i UARTRX można połączyć w module nadrzędnym sterującym sygnałami.
W zrzucie ekranu po niżej jest zobrazowane działanie modułu nadrzędnego który odbiera dane 16 bit i po weryfikacji je odsyła. Aplikacja na komputerze weryfikuje dane i potwierdza ich poprawność:

image.thumb.png.0ba955d1c0bc74bfcd9f707483a3ebdd.png

Edytowano przez kroszkanorber
  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...