-- -------------------------------------------------------------------------- -- -- 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.all; entity uart_rx is generic( F_CLK : natural := 50_000_000; -- System clock speed BAUD_RATE : natural := 115_200 -- Desired baudrate ); port( clk : in std_logic; -- System clock @ F_CLK rst_a : in std_logic; -- Asynchronous reset data : out std_logic_vector; -- Receive payload word (width determines width of UART payload) data_valid : out std_logic; -- Data is valid serial_in_a : in std_logic -- UART RX line (asynchronous) @ BAUDRATE ); end entity uart_rx; architecture rtl of uart_rx is signal serial_in : std_logic; constant BITCLK_MAX : integer := integer(real(F_CLK) / real(BAUD_RATE)); constant BITCLK_START : integer := BITCLK_MAX / 2; signal bitclk_cnt : integer range 0 to BITCLK_MAX; signal bit_stb : std_logic; constant BITCNT_MAX : integer := 10; signal cnt : integer range 0 to BITCNT_MAX; signal busy : std_logic; begin synchronizer_rx_inst : entity work.synchronizer generic map( init_value => '1' ) port map( clk => clk, rst => rst_a, data_in_a(0) => serial_in_a, data_out(0) => serial_in ); rx : process(clk, rst_a) is begin if rst_a then cnt <= 0; data_valid <= '0'; elsif rising_edge(clk) then data_valid <= '0'; if (cnt = 0 and serial_in = '0') or bit_stb = '1' then if cnt = BITCNT_MAX then cnt <= 0; data_valid <= '1'; else data <= serial_in & data(7 downto 1); cnt <= cnt + 1; end if; end if; end if; end process rx; busy <= '1' when cnt /= 0 else '0'; bitclk : process(clk, rst_a) is begin if rst_a then bit_stb <= '0'; bitclk_cnt <= 0; elsif rising_edge(clk) then bit_stb <= '0'; if not busy then bitclk_cnt <= BITCLK_START; 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;