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; 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 state, state_next : STATE_UART_RX; signal tx_data_prev : std_logic_vector(7 downto 0); -- FIXME: this isnt named next so that the interface isn't called tx_data_next ... -- these are internal signals that are actually used as in and output signal tx_data_i : std_logic_vector(7 downto 0); signal tx_new_i : std_logic; begin --FIXME: tx_new <= tx_new_i; tx_data <= tx_data_i; process(sys_clk, sys_res) begin if (sys_res = '0') then -- Set reset state state <= IDLE; tx_data_prev <= X"00"; elsif rising_edge(sys_clk) then -- Store next state state <= state_next; tx_data_prev <= tx_data_i; end if; end process; process(state, txd, counter) begin state_next <= state; case state is when IDLE => if (txd = '0') then state_next <= BUSY; else state_next <= IDLE; end if; when BUSY => if (counter = 9) then --FIXME: is this true? state_next <= DONE; else state_next <= BUSY; end if; when DONE => state_next <= IDLE; end case; end process; process(state) begin -- Set default values -- for the outputs tx_new_i <= '0'; -- Calculate the outputs -- based on the current -- state case state is when IDLE => tx_new_i <= '0'; when BUSY => tx_new_i <= '0'; when DONE => tx_new_i <= '1'; end case; end process; -- END FIXME: do fill this out CORRECTLY process (sys_clk, sys_res) begin if sys_res = '0' then counter <= 0; timer <= 0; elsif rising_edge(sys_clk) then counter <= counter_next; timer <= timer_next; end if; end process; process (timer) begin if (timer = timer_max) then timer_next <= 0; else timer_next <= timer + 1; end if; end process; process (timer, counter, tx_new_i) begin if (tx_new_i = '1') then if (timer = timer_max) then if (counter > 10) then counter_next <= 0; else counter_next <= counter + 1; end if; else counter_next <= counter; end if; else counter_next <= 0; end if; end process; process (counter, txd) begin tx_data_i <= tx_data_prev; -- TODO: we probably want oversampling and averaging + failure! -- FIXME: this is per se not synthesisable case (counter) is when 0 => --start bit assert (txd = '0'); when 1 => tx_data_i(0) <= txd; when 2 => tx_data_i(1) <= txd; when 3 => tx_data_i(2) <= txd; when 4 => tx_data_i(3) <= txd; when 5 => tx_data_i(4) <= txd; when 6 => tx_data_i(5) <= txd; when 7 => tx_data_i(6) <= txd; when 8 => tx_data_i(7) <= txd; when 9 => -- stop bit assert (txd = '1'); when others => -- idle assert (txd = '1'); end case; end process; end architecture beh;