UART (Universal asynchronous receiver/transmitter – Evrensel eşzamanlı olmaya alıcı/verici) paralel ve seri formlar arasında data çevrim işlemi yapan bilgisayar donanım parçasından biridir. UART’lar RS-232, RS-485 gibi yaygın iletişim standartları ile birlikte kullanılır.
Aşağıda VHDL dilinde UART modülü ile data alma ve gönderme işlemlerinin gerçekleştirildiği örnekler verilmiştir.
Örnek 1: Aşağıda UART protokoklü kullanarak data gönderim işlemninin yapıldığı UART_tx.vhd VHDL kodu erilmiştir. UART_tx varlığımıza ilişkin generic bildirimleri 7-10. satırlarda yapılmıştır. generic bildirimi içerisinde yapılan değerler kullanılarak 23. satırda her bir bit değeri için gerekli saat darbesi sayısı hesaplanmaktadır. Port bildirim işlemleri 11-18 satırları arasında yapılmaktıdır. UART_tx varlığımız 1 bitlik başla biti, 1 bitlik bitir biti ve 8 bitlik data gönderecek şekilde tasarlanmıştır. t_UART_tx tipinde tanımlı r_UART_tx sinyali başlangıç durumunda BOSTA durumundadır ve in_tx_basla giriş portu değerinin ‘1’ olmasını beklemektedir. in_tx_basla giriş portu değerinin ‘1’ olması ile birlikte, r_data sinyaline in_txt_data giriş portu değeri atanmaktadır ve r_UART_tx sinyali BASLA durumuna dallanır. BASLA durumunda başla biti gönderim işlemi yapılmaktadır. Yani CLK_BIT sabitinin değeri kadar saat darbesinde bu durum içerisinde beklenmekte ve out_tx_cikis portuna ‘1’ değeri gönderilmektedir. CLK_BIT sayısı kadar saat darbesi beklendikten sonra r_UART_tx sinyali GONDER durumuna dallanır. Bu durumda r_data sinyalinin en anlamsız bitinden en anlamlı bitine doğru tüm datalar CLK_BIT sayısı kadar saat darbesi süresi ile gönderilmektedir. Yani bu durum içerisinde 8 x CLK_BIT saat darbesi kadar beklenmektedir. Tüm bitlerin gönderim işleminden sonra r_UART_tx sinyali BITIR durumuna dallanır. Bu durum içerisinde bitir biti gönderim işlemi yapılmaktadır. Yani CLK_BIT sabitinin değeri kadar saat darbesinde bu durum içerisinde beklenmekte ve out_tx_cikis portuna ‘1’ değeri gönderilmektedir. CLK_BIT sayısı kadar saat darbesi beklendikten sonra r_UART_tx sinyali TAMAM durumuna dallanır. TAMAM durumunda r_tx_tamam sinyali ‘1’ değerini alarak data gönderim işleminin bittiği bildirilmektedir ve r_UART_tx sinyali BOSTA durumuna dallanır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_SIGNED.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity UART_tx is Generic ( CLK_FREKANS : integer := 100000000; -- 100 MHz BOUDRATE : integer := 115200 ); Port( in_clk : in std_logic; in_rst : in std_logic; in_tx_basla : in std_logic; in_tx_data : in std_logic_vector(7 downto 0); out_tx : out std_logic; out_tx_tamam : out std_logic ); end UART_tx; architecture Behavioral of UART_tx is constant CLK_BIT : integer := CLK_FREKANS / BOUDRATE + 1; type t_UART_tx is (BOSTA, BASLA, GONDER, BITIR, TAMAM); signal r_UART_tx : t_UART_tx := BOSTA; signal r_clk_sayac : integer range 0 to CLK_BIT - 1 := 0; signal r_data_ind : integer range 0 to 7 := 0; signal r_data : std_logic_vector(7 downto 0) := (others => '0'); signal r_tx : std_logic := '1'; signal r_tx_tamam : std_logic := '0'; begin out_tx <= r_tx; out_tx_tamam <= r_tx_tamam; process(in_clk, in_rst) begin if in_rst = '1' then r_UART_tx <= BOSTA; r_clk_sayac <= 0; r_data_ind <= 0; r_data <= (others => '0'); r_tx <= '1'; r_tx_tamam <= '0'; elsif rising_edge(in_clk) then r_tx_tamam <= '0'; case r_UART_tx is when BOSTA => r_tx <= '1'; r_clk_sayac <= 0; r_data_ind <= 0; if in_tx_basla = '1' then r_data <= in_tx_data; r_UART_tx <= BASLA; end if; when BASLA => r_tx <= '0'; if r_clk_sayac = CLK_BIT - 1 then r_clk_sayac <= 0; r_UART_tx <= GONDER; else r_clk_sayac <= r_clk_sayac + 1; end if; when GONDER => r_tx <= r_data(r_data_ind); if r_clk_sayac = CLK_BIT - 1 then r_clk_sayac <= 0; if r_data_ind = 7 then r_data_ind <= 0; r_UART_tx <= BITIR; else r_data_ind <= r_data_ind + 1; end if; else r_clk_sayac <= r_clk_sayac + 1; end if; when BITIR => r_tx <= '1'; if r_clk_sayac = CLK_BIT - 1 then r_clk_sayac <= 0; r_UART_tx <= TAMAM; else r_clk_sayac <= r_clk_sayac + 1; end if; when TAMAM => r_tx <= '1'; r_tx_tamam <= '1'; r_UART_tx <= BOSTA; when others => NULL; end case; end if; end process; end Behavioral;
Örnek 2: Aşağıda UART protokoklü kullanarak data alım işlemininin yapıldığı UART_rx.vhd VHDL kodu erilmiştir. UART_rx varlığımıza ilişkin generic bildirimleri 7-10. satırlarda yapılmıştır. generic bildirimi içerisinde yapılan değerler kullanılarak 22. satırda her bir bit değeri için gerekli saat darbesi sayısı hesaplanmaktadır. Port bildirim işlemleri 11-17 satırları arasında yapılmaktıdır. UART_rx varlığımız 8 bitlik data alacak şekilde tasarlanmıştır. 48. satırda saat darbelerinin farklı olmasından dolayı domain eşleştirme işlemi yapılmaktadır. t_UART_rx tipinde tanımlı r_UART_rx sinyali başlangıç durumunda BOSTA durumundadır ve r_rx_cnt sinyalin ilk 2 bitinin değerinin “10” olması beklemektedir.r_rx_cnt sinyalin ilk 2 bitinin değerinin “10” olması ile r_UART_rx sinyali BASLA durumuna dallanır. BASLA durumunda CLK_BIT sabitinin değerinin yarısı kadar beklenmektedir. CLK_BIT/2 sayısı kadar saat darbesi beklendikten sonra r_UART_rx sinyali DATA_AL durumuna dallanır. Bu durumda CLK_BIT sayısı kadar saat darbesi süresi kadar beklendikten sonra r_data sinyalinin en anlamsız bitinden en anlamlı bitine doğru datalar yazılmaktadır. Yani bu durum içerisinde 8 x CLK_BIT saat darbesi kadar beklenmektedir. Tüm bitlerin alınma işleminden sonra r_UART_rx sinyali BITIR durumuna dallanır. Bu durum içerisinde bitir CLK_BIT sabitinin değeri kadar saat darbesi beklendikten sonra r_UART_rx sinyali TAMAM durumuna dallanır. TAMAM durumunda r_rx_tamam sinyali ‘1’ değerini alarak data alım işleminin bittiği bildirilmektedir ve r_UART_rx sinyali BOSTA durumuna dallanır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_SIGNED.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity UART_rx is Generic ( CLK_FREKANS : integer := 100000000; BOUDRATE : integer := 115200 ); Port( in_clk : in std_logic; in_rst : in std_logic; in_rx : in std_logic; out_rx_data : out std_logic_vector(7 downto 0); out_rx_tamam : out std_logic ); end UART_rx; architecture Behavioral of UART_rx is constant CLK_BIT : integer := CLK_FREKANS / BOUDRATE + 1; type t_UART_rx is (BOSTA, BASLA, DATA_AL, BITIR, TAMAM); signal r_UART_rx : t_UART_rx := BOSTA; signal r_clk_sayac : integer range 0 to CLK_BIT - 1 := 0; signal r_data_ind : integer range 0 to 7 := 0; signal r_data : std_logic_vector(7 downto 0) := (others => '0'); signal r_rx_tamam : std_logic := '0'; signal r_rx_cnt : std_logic_vector(2 downto 0) := (others => '0'); begin out_rx_data <= r_data; out_rx_tamam <= r_rx_tamam; process(in_clk) begin if in_rst = '1' then r_UART_rx <= BOSTA; r_clk_sayac <= 0; r_data_ind <= 0; r_data <= (others => '0'); r_rx_cnt <= (others => '0'); r_rx_tamam <= '0'; elsif rising_edge(in_clk) then r_rx_cnt <= r_rx_cnt(1 downto 0) & in_rx; r_rx_tamam <= '0'; case r_UART_rx is when BOSTA => if r_rx_cnt(2 downto 1) = "10" then r_UART_rx <= BASLA; end if; when BASLA => if r_clk_sayac = (CLK_BIT - 1) / 2 then r_clk_sayac <= 0; r_UART_rx <= DATA_AL; else r_clk_sayac <= r_clk_sayac + 1; end if; when DATA_AL => r_data(r_data_ind) <= r_rx_cnt(2); if r_clk_sayac = CLK_BIT - 1 then r_clk_sayac <= 0; if r_data_ind = 7 then r_data_ind <= 0; r_UART_rx <= BITIR; else r_data_ind <= r_data_ind + 1; end if; else r_clk_sayac <= r_clk_sayac + 1; end if; when BITIR => if r_clk_sayac = CLK_BIT - 1 then r_clk_sayac <= 0; r_UART_rx <= TAMAM; else r_clk_sayac <= r_clk_sayac + 1; end if; when TAMAM => r_rx_tamam <= '1'; r_UART_rx <= BOSTA; when others => NULL; end case; end if; end process; end Behavioral;
Örnek 3: Aşağıda UART protokoklü kullanarak data alım-gönderim işlemininin yapıldığı UART_main.vhd VHDL kodu erilmiştir. UART_main varlığımıza ilişkin port bildirim işlemleri 12-18 satırları arasında yapılmaktıdır. UART_rx varlığımız UART_rx alt devresinden aldığı dataları UART_tx alt devresi ile göndermek üzere tasarlanmıştır. UART_tx alt devresi component tanımlama işlemleri 15-28. satırlar arasında, bağlantı işlemleri ise 97-109. satırlar arasında yapılmaktadır. UART_rx alt devresi component tanımlama işlemleri 30-42. satırlar arasında, bağlantı işlemleri ise 84-95. satırlar arasında yapılmaktadır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity UART_main is Port ( in_clk : in std_logic; in_rst : in std_logic; in_rx : in std_logic; out_tx : out std_logic ); end UART_main; architecture Behavioral of UART_main is component UART_tx Generic ( CLK_FREKANS : integer := 100000000; BOUDRATE : integer := 115200 ); Port( in_clk : in std_logic; in_rst : in std_logic; in_tx_basla : in std_logic; in_tx_data : in std_logic_vector(7 downto 0); out_tx : out std_logic; out_tx_tamam : out std_logic ); end component; component UART_rx Generic ( CLK_FREKANS : integer := 100000000; BOUDRATE : integer := 115200 ); Port( in_clk : in std_logic; in_rst : in std_logic; in_rx : in std_logic; out_rx_data : out std_logic_vector(7 downto 0); out_rx_tamam : out std_logic ); end component; type t_Data_Cntrl is (BOSTA, DATA_AL, DATA_GONDER); signal r_Data_Cntrl : t_Data_Cntrl := BOSTA; signal r_tx_basla : std_logic := '0'; signal r_tx_tamam : std_logic := '0'; signal r_rx_tamam : std_logic := '0'; signal r_data : std_logic_vector(7 downto 0); signal r_rx_data : std_logic_vector(7 downto 0); signal r_tx_data : std_logic_vector(7 downto 0); begin process(in_clk, in_rst) begin if in_rst = '1' then r_Data_Cntrl <= BOSTA; r_data <= (others => '0'); elsif rising_edge(in_clk) then r_tx_basla <= '0'; case r_Data_Cntrl is when BOSTA => r_Data_Cntrl <= DATA_AL; when DATA_AL => if r_rx_tamam = '1' then r_tx_data <= r_rx_data; r_tx_basla <= '1'; end if; when DATA_GONDER => if r_tx_tamam = '1' then r_Data_Cntrl <= BOSTA; end if; when others => NULL; end case; end if; end process; UART_rx_map : UART_rx Generic map( CLK_FREKANS => 100000000, --100 MHz BOUDRATE => 115200 ) Port map( in_clk => in_clk, in_rst => in_rst, in_rx => in_rx, out_rx_data => r_rx_data, out_rx_tamam => r_rx_tamam ); UART_tx_map : UART_tx Generic map( CLK_FREKANS => 100000000, --100 MHz BOUDRATE => 115200 ) Port map( in_clk => in_clk, in_rst => in_rst, in_tx_basla => r_tx_basla, in_tx_data => r_tx_data, out_tx => out_tx, out_tx_tamam => r_tx_tamam ); end Behavioral;
UART_main modülümüzün test işlemleri için Realterm programı kullanılmıştır. Realterm programında Display sekmesinde Display As’de Hex[space] seçilerek ekranda gösterilecek karakter formatı seçilmektedir (Şekil 1).

Şekil 1 UART_main modülü test işlemleri – 1
Port sekmesinde Baud sekmesinde 115200, Port sekmesinde ise \VCP0 seçilmektedir. Daha sonra Change butonuna basılarak değişiklikler yapılmaktadır (Şekil 2).

Şekil 2 UART_main modülü test işlemleri – 2
Send sekmesinde UART protokülü ile FPGA’ya göndermek istediğimiz datayı hex sayı formatında yazarak Send Numbers butonuna basılır. UART_main modülü aldığı datayı tekrar göndermek üzere tasarlandığından dolayı ekranda gönderilen data görülmektedir (Şekil 3).

Şekil 3 UART_main modülü test işlemleri – 3
Hocam Merhabalar,
Kodlarınız üzerinde denemeler yaparken, her byte veri gönderildikten sonra bir byte boşluk bırakılıp sonra diğer byte yazlıyor. Yani 5 byte gönderdiysem eğer 1, 3 ve 5. bytler görünüyor sadece. Bunun sebebi nedir öğrenmek istiyorum. Teşekkürler
Merhaba Cihat,
Buradaki kod doğrudan bir byte okuyup onu geri dönderiyor. Eğer Sen ardışık 5 byte göndereceksen ona göre düzenleme yapmalısın. Senin 2. ve 4. bytlerinda durum makinası gönderme durumunda olduğu için o bilgileri göremiyorsun.