-- -------------------------------------------------------------------------- -- -- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs -- -- -------------------------------------------------------------------------- -- -- TODO -- -------------------------------------------------------------------------- -- -- Author : Markus Koch -- Contributors : None -- License : Mozilla Public License (MPL) Version 2 -- -------------------------------------------------------------------------- -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.round; entity uart_tx is generic( F_CLK : integer := 50_000_000; -- System clock speed BAUD_RATE : integer := 115_200 -- Desired baudrate ); port( clk : in std_logic; -- System clock @ F_CLK rst_a : in std_logic; -- Asynchronous reset data : in std_logic_vector; -- Data to send (width determines width of UART payload) data_valid : in std_logic; -- Data is valid, TX at next opportunity data_latched : out std_logic; -- The data word has been latched, go ahead and apply the next one, or negate data_valid to end the transaction after the current word busy : out std_logic; -- The core is busy transmitting a data word serial_out : out std_logic -- UART TX line ); end entity uart_tx; architecture rtl of uart_tx is constant COUNTER_MAX : natural := 10; signal sr : std_logic_vector((data'length + 1) - 1 downto 0); signal bit_cnt : integer range 0 to COUNTER_MAX; constant BITCLK_MAX : integer := integer(real(F_CLK) / real(BAUD_RATE)); signal bitclk_cnt : integer range 0 to BITCLK_MAX; signal bit_stb : std_logic; begin tx_fsm : process(clk, rst_a) is begin if (rst_a = '1') then sr <= (others => '1'); bit_cnt <= 0; data_latched <= '0'; elsif (rising_edge(clk)) then data_latched <= '0'; if ((bit_stb = '1') or (bit_cnt = 0)) then sr <= '1' & sr(sr'high downto 1); if (bit_cnt = 0) then if (data_valid = '1') then data_latched <= '1'; sr <= data & '0'; bit_cnt <= COUNTER_MAX; end if; else bit_cnt <= bit_cnt - 1; end if; end if; end if; end process tx_fsm; serial_out <= sr(0); -- @suppress PID1: Not a readback signal busy <= '1' when (bit_cnt /= 0) or (data_valid = '1') else '0'; bitclk : process(clk, rst_a) is begin if rst_a then bit_stb <= '0'; bitclk_cnt <= BITCLK_MAX; elsif rising_edge(clk) then bit_stb <= '0'; if not busy then bitclk_cnt <= BITCLK_MAX; else if bitclk_cnt = 0 then bitclk_cnt <= BITCLK_MAX; bit_stb <= '1'; else bitclk_cnt <= bitclk_cnt - 1; end if; end if; end if; end process bitclk; end architecture rtl;