library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.gen_pkg.all; entity uart_rx is port( sys_clk : in std_logic; sys_res : in std_logic; txd : in std_logic; -- warning: this is asynchronous input! tx_data : out std_logic_vector(7 downto 0); -- map this to a larger register with containing input tx_new : out std_logic ); end entity uart_rx; architecture beh of uart_rx is constant timer_max : integer := 35; constant counter_max : integer := 9; constant samples : integer := 8; type STATE_UART_RX is (IDLE, BUSY, DONE); signal timer, timer_next : integer range 0 to 65535; signal counter, counter_next : integer range 0 to 15; signal sample_counter, sample_counter_next : integer range 0 to counter_max-1; signal state, state_next : STATE_UART_RX; signal sync1, sync2, txd_next: std_logic; --synchronizers FIXME! -- these are internal signals that are actually used as in and output signal tx_data_prev : std_logic_vector(7 downto 0); signal tx_new_i : std_logic; signal shift, shift_value, shift_reset : std_logic; begin tx_new <= tx_new_i; process(sys_clk, sys_res) begin if (sys_res = '0') then -- Set reset state state <= IDLE; tx_data_prev <= X"00"; txd_next <= '0'; --fixme: syncronizers! sync2 <= '0'; sync1 <= '0'; timer <= 0; counter <= 0; elsif rising_edge(sys_clk) then -- Store next state state <= state_next; if (shift = '1') then tx_data(7 downto 1) <= tx_data_prev(6 downto 1); tx_data(0) <= shift_value; elsif ( shift_reset = '1') then tx_data <= X"00"; end if; txd_next <= sync2; --fixme: syncronizers! sync2 <= sync1; sync1 <= txd; counter <= counter_next; sample_counter <= sample_counter_next; timer <= timer_next; end if; end process; process(state, txd, counter) begin state_next <= state; shift <= '0'; shift_reset <='0'; shift_value <= '0'; timer_next <= 0; counter_next <= 0; case state is when IDLE => if (txd = '0') then state_next <= BUSY; shift_reset <= '1'; end if; when BUSY => if (counter = counter_max) then --FIXME: is this true? state_next <= DONE; end if; if (timer = timer_max) then timer_next <= 0; counter_next <= counter + 1; if (sample_counter < samples/2) then shift_value <= '1'; else shift_value <= '0'; end if; shift <= '1'; else timer_next <= timer + 1; end if; if timer = timer_max/samples and txd_next = '1' then sample_counter_next <= sample_counter + 1; end if; when DONE => state_next <= IDLE; end case; end process; end architecture beh;