library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity uart_tx is port( i_clk_baudrate : in std_logic; i_reset_n : in std_logic; i_tx_send : in std_logic; i_msb_first : in std_logic; i_tx_data_vec : in std_logic_vector(7 downto 0); o_tx_pin : out std_logic; o_tx_sent : out std_logic ); end; architecture uart_tx_rtl of uart_tx is type z_uart_t is (idle, sending); constant c_START_BIT : std_logic := '0'; constant c_STOP_BIT : std_logic := '1'; signal s_tx_buf_vec : std_logic_vector(7 downto 0) := x"00"; function reverse_any_vector (a: in std_logic_vector) return std_logic_vector is variable result: std_logic_vector(a'RANGE); alias aa: std_logic_vector(a'REVERSE_RANGE) is a; begin for i in aa'RANGE loop result(i) := aa(i); end loop; return result; end; -- function reverse_any_vector begin uart_tx_main_proc: process(i_clk_baudrate) variable z_uart : z_uart_t := idle; variable v_trans_cnt : integer range 0 to 10 := 0; begin if rising_edge(i_clk_baudrate) then -- Syncrhonous reset only. if (i_reset_n = '0') then o_tx_pin <= '1'; o_tx_sent <= '1'; z_uart := idle; else case z_uart is when idle => if (i_tx_send = '1') then if (i_msb_first = '1') then s_tx_buf_vec <= i_tx_data_vec; else s_tx_buf_vec <= reverse_any_vector(i_tx_data_vec); end if; o_tx_sent <= '0'; o_tx_pin <= c_START_BIT; z_uart := sending; end if; when sending => if (v_trans_cnt >= 8) then v_trans_cnt := 0; o_tx_sent <= '1'; o_tx_pin <= c_STOP_BIT; z_uart := idle; else o_tx_pin <= s_tx_buf_vec(7-v_trans_cnt); v_trans_cnt := v_trans_cnt + 1; end if; end case; end if; -- reset end if; -- clk end process uart_tx_main_proc; -- main end;