--=====================================================
-- Проект 16. Передатчик UART
-- Формирует кадр: старт-бит, восемь бит данных,
-- стоп-бит. Скорость задаётся делителем такта.
--=====================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uart_tx is
    generic (
        CLK_DIV : integer := 5208                       -- 50 МГц / 9600 бод
    );
    port (
        clk     : in  std_logic;
        rst     : in  std_logic;
        start   : in  std_logic;                        -- запрос передачи
        data    : in  std_logic_vector(7 downto 0);
        tx      : out std_logic;                        -- линия передачи
        busy    : out std_logic
    );
end entity uart_tx;

architecture rtl of uart_tx is
    type state_t is (IDLE, START_BIT, DATA_BITS, STOP_BIT);
    signal state   : state_t := IDLE;
    signal baud    : integer range 0 to CLK_DIV := 0;
    signal bit_idx : integer range 0 to 7 := 0;
    signal shreg   : std_logic_vector(7 downto 0) := (others => '0');
    signal tx_reg  : std_logic := '1';                  -- линия в покое высокая
begin
    process (clk, rst)
    begin
        if rst = '1' then
            state   <= IDLE;
            tx_reg  <= '1';
            baud    <= 0;
            bit_idx <= 0;
        elsif rising_edge(clk) then
            case state is
                when IDLE =>
                    tx_reg <= '1';
                    if start = '1' then
                        shreg <= data;                  -- защёлкиваем байт
                        baud  <= 0;
                        state <= START_BIT;
                    end if;

                when START_BIT =>
                    tx_reg <= '0';                      -- старт-бит
                    if baud = CLK_DIV - 1 then
                        baud    <= 0;
                        bit_idx <= 0;
                        state   <= DATA_BITS;
                    else
                        baud <= baud + 1;
                    end if;

                when DATA_BITS =>
                    tx_reg <= shreg(bit_idx);           -- младшим битом вперёд
                    if baud = CLK_DIV - 1 then
                        baud <= 0;
                        if bit_idx = 7 then
                            state <= STOP_BIT;
                        else
                            bit_idx <= bit_idx + 1;
                        end if;
                    else
                        baud <= baud + 1;
                    end if;

                when STOP_BIT =>
                    tx_reg <= '1';                      -- стоп-бит
                    if baud = CLK_DIV - 1 then
                        baud  <= 0;
                        state <= IDLE;
                    else
                        baud <= baud + 1;
                    end if;
            end case;
        end if;
    end process;

    tx   <= tx_reg;
    busy <= '0' when state = IDLE else '1';
end architecture rtl;
