library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity async_8n1_tx is port ( clk : in std_logic; rst : in std_logic; en : in std_logic; wr : in std_logic; data_in : in unsigned (7 downto 0); data_out : out std_logic ); end entity; architecture beh of async_8n1_tx is component generic_counter is generic ( counter_bits : integer := 4 ); port( clk : in std_logic; rst : in std_logic; en : in std_logic; cnt : out unsigned (counter_bits -1 downto 0) ); end component; type t_output_state is (mark, space, data); type t_tx_state is (idle, send_start, send_data, send_stop); signal i_data_out : std_logic; signal i_data_reg : unsigned(7 downto 0); signal i_next_data : std_logic; signal i_output_mux : t_output_state; signal i_current_state : t_tx_state; signal i_next_state : t_tx_state; signal i_cnt : unsigned(3 downto 0); signal i_clear_counter : std_logic; signal tmp_current_state : integer; signal tmp_next_state : integer; signal tmp_output_mux : integer; begin tmp_current_state <= t_tx_state'pos(i_current_state); tmp_next_state <= t_tx_state'pos(i_next_state); tmp_output_mux <= t_output_state'pos(i_output_mux); data_out <= i_data_out; with i_output_mux select i_data_out <= '1' when mark, '0' when space, i_next_data when data; i_next_data <= i_data_reg(0); i_clear_counter <= '1' when i_current_state = idle or rst = '1' else '0'; i_counter : generic_counter port map( clk => clk, rst => i_clear_counter, en => en, cnt => i_cnt); with i_current_state select i_output_mux <= mark when idle, space when send_start, data when send_data, mark when send_stop; -- Concurrent process process(i_current_state, wr, i_cnt) is begin if i_current_state = idle then if wr = '1' then i_next_state <= send_start; else i_next_state <= i_current_state; end if; elsif i_current_state = send_start then i_next_state <= send_data; elsif i_current_state = send_data then if i_cnt = to_unsigned(7, 4) then i_next_state <= send_stop; else i_next_state <= i_current_state; end if; elsif i_current_state = send_stop then i_next_state <= idle; else i_next_state <= i_current_state; end if; end process; -- Shift register process(clk) is begin if rising_edge(clk) then if rst = '1' then i_data_reg <= (others => '0'); elsif en = '1' and i_current_state = send_data then i_data_reg <= '1' & i_data_reg(7 downto 1); elsif en = '1' and i_current_state = idle and wr = '1' then i_data_reg <= data_in; else i_data_reg <= i_data_reg; end if; end if; end process; -- State machine process(clk) is begin if rising_edge(clk) then if rst = '1' then i_current_state <= idle; elsif en = '1' then i_current_state <= i_next_state; end if; end if; end process; end architecture;