-- -------------------------------------------------------------------------- -- -- uart_tx.vhd: Basic UART (tx) -- -- Copyright (C) 2017 Markus Koch -- -- This Source Code Form is subject to the terms of the Mozilla Public -- License, v. 2.0. If a copy of the MPL was not distributed with this -- file, You can obtain one at http://mozilla.org/MPL/2.0/. -- -------------------------------------------------------------------------- -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity uart_tx is port( clk : in std_logic; rst : in std_logic; data : in std_logic_vector(7 downto 0); byte_ready : in std_logic; busy : out std_logic; ckDiv : in std_logic_vector(15 downto 0); parityEnable : in std_logic; parityOdd : in std_logic; twoStopBits : in std_logic; tx : out std_logic ); end entity uart_tx; architecture RTL of uart_tx is type state_t is (IDLE, START, TRANSMIT, PARITY, STOP); signal state : state_t; signal clkDivider : unsigned(15 downto 0); signal data_i : std_logic_vector(7 downto 0); signal bitCounter : integer range 0 to 7; signal parity_calc : std_logic; begin txFSM : process(ckDiv, clk, parityOdd, rst) is begin if rst = '1' then data_i <= x"00"; state <= IDLE; tx <= '1'; bitCounter <= 0; busy <= '0'; clkDivider <= unsigned(ckDiv); parity_calc <= parityOdd; elsif rising_edge(clk) then busy <= '1'; if (clkDivider = 0) then clkDivider <= unsigned(ckDiv); else clkDivider <= clkDivider - 1; end if; case state is when IDLE => busy <= '0'; tx <= '1'; if byte_ready = '1' then data_i <= data; state <= START; clkDivider <= unsigned(ckDiv); bitCounter <= 0; parity_calc <= parityOdd; busy <= '1'; tx <= '1'; end if; when START => tx <= '0'; state <= TRANSMIT; when TRANSMIT => if (clkDivider = to_unsigned(0, clkDivider'length)) then tx <= data_i(bitCounter); if data_i(bitCounter) = '1' then parity_calc <= not parity_calc; end if; if bitCounter = 7 then bitCounter <= 0; if parityEnable = '1' then state <= PARITY; else state <= STOP; end if; else bitCounter <= bitCounter + 1; end if; end if; when PARITY => if (clkDivider = to_unsigned(0, clkDivider'length)) then tx <= parity_calc; state <= STOP; end if; when STOP => if (clkDivider = to_unsigned(0, clkDivider'length)) then tx <= '1'; bitCounter <= bitCounter + 1; if (bitCounter = 1 and twoStopBits = '0') or (bitCounter = 2 and twoStopBits = '1') then state <= IDLE; end if; end if; end case; end if; end process txFSM; end architecture RTL;