---------------------------------------------------------------------------- -- uart.vhd -- Universal Asynchronous Receiver Transmitter -- Version 1.0 -- -- Copyright (C) 2015 H.Poetzl -- -- This program is free software: you can redistribute it and/or -- modify it under the terms of the GNU General Public License -- as published by the Free Software Foundation, either version -- 2 of the License, or (at your option) any later version. -- ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.ALL; entity uart_filter is generic ( SAMPLE_COUNT : natural := 5 ); port ( clk : in std_logic; -- ser_in : in std_logic; -- ser_out : out std_logic ); end entity uart_filter; architecture RTL of uart_filter is begin filter_proc : process(clk, ser_in) constant sample_lo_c : natural := SAMPLE_COUNT*1/3; constant sample_hi_c : natural := SAMPLE_COUNT*2/3; variable shift_v : std_logic_vector(SAMPLE_COUNT downto 0) := (others => '0'); variable count_v : natural range 0 to SAMPLE_COUNT; variable out_v : std_logic := '1'; begin if rising_edge(clk) then shift_v := shift_v(SAMPLE_COUNT-1 downto 0) & ser_in; count_v := 0; for I in SAMPLE_COUNT-1 downto 0 loop if shift_v(I) = '1' then count_v := count_v + 1; end if; end loop; if count_v > sample_hi_c then out_v := '1'; elsif count_v <= sample_lo_c then out_v := '0'; end if; end if; ser_out <= out_v; end process; end RTL; library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.ALL; entity uart_rx is generic ( DATA_BITS : natural := 8; STOP_BITS : natural := 1; PARITY_BITS : natural := 0; SAMPLE_COUNT : natural := 5 ); port ( clk : in std_logic; -- ser : in std_logic; idle : out std_logic; state : out std_logic_vector (2 downto 0); -- data : out std_logic_vector (DATA_BITS-1 downto 0); valid : out std_logic; parity : out std_logic ); end entity uart_rx; architecture RTL of uart_rx is type rx_state is (idle_s, start_s, data_s, parity_s, stop_s); begin sample_proc : process(clk, ser) constant sample_c : natural := SAMPLE_COUNT/2; variable state_v : rx_state := idle_s; variable last_v : std_logic := '0'; variable bcnt_v : integer; variable cnt_v : integer range 0 to SAMPLE_COUNT; variable data_v : std_logic_vector(0 to DATA_BITS-1) := (others => '0'); variable parity_v : std_logic_vector(0 to PARITY_BITS) := (others => '0'); begin if rising_edge(clk) then valid <= '0'; idle <= '0'; with state_v select state <= "000" when idle_s, "001" when start_s, "010" when data_s, "011" when parity_s, "100" when stop_s; case state_v is when idle_s => idle <= '1'; if last_v = '1' and ser = '0' then state_v := start_s; cnt_v := 0; end if; when start_s => cnt_v := cnt_v + 1; if cnt_v = SAMPLE_COUNT then state_v := data_s; bcnt_v := DATA_BITS - 1; cnt_v := 0; end if; when data_s => cnt_v := cnt_v + 1; if cnt_v = sample_c then data_v(bcnt_v) := ser; elsif cnt_v = SAMPLE_COUNT then if bcnt_v > 0 then bcnt_v := bcnt_v - 1; else if PARITY_BITS > 0 then state_v := parity_s; bcnt_v := PARITY_BITS - 1; else state_v := stop_s; bcnt_v := STOP_BITS - 1; end if; end if; cnt_v := 0; end if; when parity_s => cnt_v := cnt_v + 1; if cnt_v = sample_c then parity_v(bcnt_v) := ser; elsif cnt_v = SAMPLE_COUNT then if bcnt_v > 0 then bcnt_v := bcnt_v - 1; else state_v := stop_s; bcnt_v := STOP_BITS - 1; end if; cnt_v := 0; end if; when stop_s => cnt_v := cnt_v + 1; if cnt_v = SAMPLE_COUNT then if bcnt_v > 0 then bcnt_v := bcnt_v - 1; -- check stop bit else state_v := idle_s when ser = '1' or last_v = '0' else start_s; cnt_v := 0; data <= data_v; parity <= parity_v(0); -- check stop bit valid <= '1'; end if; end if; end case; last_v := ser; end if; end process; end RTL; library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.ALL; entity uart_tx is generic ( DATA_BITS : natural := 8; STOP_BITS : natural := 1; PARITY_BITS : natural := 0; SAMPLE_COUNT : natural := 5 ); port ( clk : in std_logic; -- data : in std_logic_vector(DATA_BITS-1 downto 0); valid : in std_logic; -- ser : out std_logic; idle : out std_logic; state : out std_logic_vector (2 downto 0) ); end entity uart_tx; architecture RTL of uart_tx is type tx_state is (idle_s, start_s, data_s, parity_s, stop_s); begin gen_proc : process(clk) variable state_v : tx_state := idle_s; variable bcnt_v : integer; variable cnt_v : integer range 0 to SAMPLE_COUNT; variable data_v : std_logic_vector(0 to DATA_BITS-1) := (others => '0'); variable parity_v : std_logic_vector(0 to PARITY_BITS) := (others => '0'); begin if rising_edge(clk) then idle <= '0'; with state_v select state <= "000" when idle_s, "001" when start_s, "010" when data_s, "011" when parity_s, "100" when stop_s; case state_v is when idle_s => ser <= '1'; if valid = '1' then data_v := data; state_v := start_s; cnt_v := 0; end if; idle <= '1'; when start_s => cnt_v := cnt_v + 1; ser <= '0'; if cnt_v = SAMPLE_COUNT then state_v := data_s; bcnt_v := DATA_BITS - 1; cnt_v := 0; end if; when data_s => cnt_v := cnt_v + 1; ser <= data_v(bcnt_v); if cnt_v = SAMPLE_COUNT then if bcnt_v > 0 then bcnt_v := bcnt_v - 1; else if PARITY_BITS > 0 then state_v := parity_s; bcnt_v := PARITY_BITS - 1; else state_v := stop_s; bcnt_v := STOP_BITS - 1; end if; end if; cnt_v := 0; end if; when parity_s => cnt_v := cnt_v + 1; ser <= parity_v(bcnt_v); if cnt_v = SAMPLE_COUNT then if bcnt_v > 0 then bcnt_v := bcnt_v - 1; else state_v := stop_s; bcnt_v := STOP_BITS - 1; end if; cnt_v := 0; end if; when stop_s => cnt_v := cnt_v + 1; ser <= '1'; if cnt_v = SAMPLE_COUNT - 1 then if bcnt_v = 0 then state_v := idle_s; end if; elsif cnt_v = SAMPLE_COUNT then if bcnt_v > 0 then bcnt_v := bcnt_v - 1; end if; cnt_v := 0; end if; end case; end if; end process; end RTL;