diff --git a/syn/UartTx.vhd b/syn/UartTx.vhd new file mode 100644 index 0000000..2af66b3 --- /dev/null +++ b/syn/UartTx.vhd @@ -0,0 +1,126 @@ +-- ====================================================================== +-- UART transmitter +-- Copyright (C) 2020 Torsten Meissner +------------------------------------------------------------------------- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public +-- License as published by the Free Software Foundation; either +-- version 3 of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License +-- along with this program; if not, write to the Free Software Foundation, +-- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +-- ====================================================================== + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + + +entity UartTx is + generic ( + DATA_LENGTH : positive range 5 to 9 := 8; + PARITY : boolean := false; -- not implemented yet + CLK_DIV : natural := 10 + ); + port ( + reset_n_i : in std_logic; -- async reset + clk_i : in std_logic; -- clock + data_i : in std_logic_vector(DATA_LENGTH-1 downto 0); -- data input + valid_i : in std_logic; -- input data valid + accept_o : out std_logic; -- inpit data accepted + tx_o : out std_logic -- uart tx data output + ); +end entity UartTx; + + + +architecture rtl of UartTx is + + + type t_uart_state is (IDLE, SEND); + signal s_uart_state : t_uart_state; + + signal s_data : std_logic_vector(DATA_LENGTH+1 downto 0); + signal s_clk_en : boolean; + + function odd_parity (data : in std_logic_vector(DATA_LENGTH-1 downto 0)) return std_logic is + variable v_data : std_logic := '0'; + begin + for i in data'range loop + v_data := v_data xor data(i); + end loop; + return not v_data; + end function odd_parity; + + +begin + + + ClkDivP : process (clk_i, reset_n_i) is + variable v_clk_cnt : natural range 0 to CLK_DIV-1; + begin + if (reset_n_i = '0') then + s_clk_en <= false; + v_clk_cnt := CLK_DIV-1; + elsif (rising_edge(clk_i)) then + if (s_uart_state = IDLE) then + v_clk_cnt := CLK_DIV-2; + s_clk_en <= false; + elsif (s_uart_state = SEND) then + if (v_clk_cnt = 0) then + v_clk_cnt := CLK_DIV-1; + s_clk_en <= true; + else + v_clk_cnt := v_clk_cnt - 1; + s_clk_en <= false; + end if; + end if; + end if; + end process ClkDivP; + + + TxP : process (clk_i, reset_n_i) is + variable v_bit_cnt : natural range 0 to s_data'length-1; + begin + if (reset_n_i = '0') then + s_uart_state <= IDLE; + s_data <= (0 => '1', others => '0'); + accept_o <= '0'; + v_bit_cnt := 0; + elsif (rising_edge(clk_i)) then + FsmL : case s_uart_state is + when IDLE => + accept_o <= '1'; + v_bit_cnt := s_data'length-1; + if (valid_i = '1' and accept_o = '1') then + accept_o <= '0'; + s_data <= '1' & data_i & '0'; + s_uart_state <= SEND; + end if; + when SEND => + if (s_clk_en) then + s_data <= '1' & s_data(s_data'length-1 downto 1); + if (v_bit_cnt = 0) then + accept_o <= '1'; + s_uart_state <= IDLE; + else + v_bit_cnt := v_bit_cnt - 1; + end if; + end if; + end case; + end if; + end process TxP; + + + tx_o <= s_data(0); + + +end architecture rtl;