OpenCores
URL https://opencores.org/ocsvn/simple_uart_for_fpga/simple_uart_for_fpga/trunk

Subversion Repositories simple_uart_for_fpga

[/] [simple_uart_for_fpga/] [trunk/] [source/] [comp/] [uart_tx.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
-- PROJECT: SIMPLE UART FOR FPGA
--------------------------------------------------------------------------------
-- MODULE:  UART TRANSMITTER
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
-- lICENSE: The MIT License (MIT)
-- WEBSITE: https://github.com/jakubcabal/uart_for_fpga
--------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity UART_TX is
    Generic (
        PARITY_BIT  : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
    );
    Port (
        CLK         : in  std_logic; -- system clock
        RST         : in  std_logic; -- high active synchronous reset
        -- UART INTERFACE
        UART_CLK_EN : in  std_logic; -- oversampling (16x) UART clock enable
        UART_TXD    : out std_logic;
        -- USER DATA INPUT INTERFACE
        DATA_IN     : in  std_logic_vector(7 downto 0);
        DATA_SEND   : in  std_logic; -- when DATA_SEND = 1, data on DATA_IN will be transmit, DATA_SEND can set to 1 only when BUSY = 0
        BUSY        : out std_logic  -- when BUSY = 1 transiever is busy, you must not set DATA_SEND to 1
    );
end UART_TX;
 
architecture FULL of UART_TX is
 
    signal tx_clk_en         : std_logic;
    signal tx_clk_divider_en : std_logic;
    signal tx_ticks          : unsigned(3 downto 0);
    signal tx_data           : std_logic_vector(7 downto 0);
    signal tx_bit_count      : unsigned(2 downto 0);
    signal tx_bit_count_en   : std_logic;
    signal tx_busy           : std_logic;
    signal tx_parity_bit     : std_logic;
    signal tx_data_out_sel   : std_logic_vector(1 downto 0);
 
    type state is (idle, txsync, startbit, databits, paritybit, stopbit);
    signal tx_pstate : state;
    signal tx_nstate : state;
 
begin
 
    BUSY <= tx_busy;
 
    -- -------------------------------------------------------------------------
    -- UART TRANSMITTER CLOCK DIVIDER
    -- -------------------------------------------------------------------------
 
    uart_tx_clk_divider : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (tx_clk_divider_en = '1') then
                if (uart_clk_en = '1') then
                    if (tx_ticks = "1111") then
                        tx_ticks <= (others => '0');
                        tx_clk_en <= '0';
                    elsif (tx_ticks = "0001") then
                        tx_ticks <= tx_ticks + 1;
                        tx_clk_en <= '1';
                    else
                        tx_ticks <= tx_ticks + 1;
                        tx_clk_en <= '0';
                    end if;
                else
                    tx_ticks <= tx_ticks;
                    tx_clk_en <= '0';
                end if;
            else
                tx_ticks <= (others => '0');
                tx_clk_en <= '0';
            end if;
        end if;
    end process;
 
    -- -------------------------------------------------------------------------
    -- UART TRANSMITTER INPUT DATA REGISTER
    -- -------------------------------------------------------------------------
 
    uart_tx_input_data_reg : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                tx_data <= (others => '0');
            elsif (DATA_SEND = '1' AND tx_busy = '0') then
                tx_data <= DATA_IN;
            end if;
        end if;
    end process;
 
    -- -------------------------------------------------------------------------
    -- UART TRANSMITTER BIT COUNTER
    -- -------------------------------------------------------------------------
 
    uart_tx_bit_counter : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                tx_bit_count <= (others => '0');
            elsif (tx_bit_count_en = '1' AND tx_clk_en = '1') then
                if (tx_bit_count = "111") then
                    tx_bit_count <= (others => '0');
                else
                    tx_bit_count <= tx_bit_count + 1;
                end if;
            end if;
        end if;
    end process;
 
    -- -------------------------------------------------------------------------
    -- UART TRANSMITTER PARITY GENERATOR
    -- -------------------------------------------------------------------------
 
    uart_tx_parity_g : if (PARITY_BIT /= "none") generate
        uart_tx_parity_gen_i: entity work.UART_PARITY
        generic map (
            DATA_WIDTH  => 8,
            PARITY_TYPE => PARITY_BIT
        )
        port map (
            DATA_IN     => tx_data,
            PARITY_OUT  => tx_parity_bit
        );
    end generate;
 
    uart_tx_noparity_g : if (PARITY_BIT = "none") generate
        tx_parity_bit <= 'Z';
    end generate;
 
    -- -------------------------------------------------------------------------
    -- UART TRANSMITTER OUTPUT DATA REGISTER
    -- -------------------------------------------------------------------------
 
    uart_tx_output_data_reg : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                UART_TXD <= '1';
            else
                case tx_data_out_sel is
                    when "01" => -- START BIT
                        UART_TXD <= '0';
                    when "10" => -- DATA BITS
                        UART_TXD <= tx_data(to_integer(tx_bit_count));
                    when "11" => -- PARITY BIT
                        UART_TXD <= tx_parity_bit;
                    when others => -- STOP BIT OR IDLE
                        UART_TXD <= '1';
                end case;
            end if;
        end if;
    end process;
 
    -- -------------------------------------------------------------------------
    -- UART TRANSMITTER FSM
    -- -------------------------------------------------------------------------
 
    -- PRESENT STATE REGISTER
    process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                tx_pstate <= idle;
            else
                tx_pstate <= tx_nstate;
            end if;
        end if;
    end process;
 
    -- NEXT STATE AND OUTPUTS LOGIC
    process (tx_pstate, DATA_SEND, tx_clk_en, tx_bit_count)
    begin
 
        case tx_pstate is
 
            when idle =>
                tx_busy <= '0';
                tx_data_out_sel <= "00";
                tx_bit_count_en <= '0';
                tx_clk_divider_en <= '0';
 
                if (DATA_SEND = '1') then
                    tx_nstate <= txsync;
                else
                    tx_nstate <= idle;
                end if;
 
            when txsync =>
                tx_busy <= '1';
                tx_data_out_sel <= "00";
                tx_bit_count_en <= '0';
                tx_clk_divider_en <= '1';
 
                if (tx_clk_en = '1') then
                    tx_nstate <= startbit;
                else
                    tx_nstate <= txsync;
                end if;
 
            when startbit =>
                tx_busy <= '1';
                tx_data_out_sel <= "01";
                tx_bit_count_en <= '0';
                tx_clk_divider_en <= '1';
 
                if (tx_clk_en = '1') then
                    tx_nstate <= databits;
                else
                    tx_nstate <= startbit;
                end if;
 
            when databits =>
                tx_busy <= '1';
                tx_data_out_sel <= "10";
                tx_bit_count_en <= '1';
                tx_clk_divider_en <= '1';
 
                if ((tx_clk_en = '1') AND (tx_bit_count = "111")) then
                    if (PARITY_BIT = "none") then
                        tx_nstate <= stopbit;
                    else
                        tx_nstate <= paritybit;
                    end if ;
                else
                    tx_nstate <= databits;
                end if;
 
            when paritybit =>
                tx_busy <= '1';
                tx_data_out_sel <= "11";
                tx_bit_count_en <= '0';
                tx_clk_divider_en <= '1';
 
                if (tx_clk_en = '1') then
                    tx_nstate <= stopbit;
                else
                    tx_nstate <= paritybit;
                end if;
 
            when stopbit =>
                tx_busy <= '0';
                tx_data_out_sel <= "00";
                tx_bit_count_en <= '0';
                tx_clk_divider_en <= '1';
 
                if (DATA_SEND = '1') then
                    tx_nstate <= txsync;
                elsif (tx_clk_en = '1') then
                    tx_nstate <= idle;
                else
                    tx_nstate <= stopbit;
                end if;
 
            when others =>
                tx_busy <= '1';
                tx_data_out_sel <= "00";
                tx_bit_count_en <= '0';
                tx_clk_divider_en <= '0';
                tx_nstate <= idle;
 
        end case;
    end process;
 
end FULL;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.