0
0
VhdlHow-ToBeginner · 4 min read

VHDL Code for UART Transmitter: Syntax and Example

A UART transmitter in VHDL sends serial data by shifting bits out at a set baud rate. It typically includes a state machine to handle start, data, parity, and stop bits. The transmitter outputs a serial line signal that can be connected to a UART receiver.
📐

Syntax

The UART transmitter in VHDL usually has inputs for clock, reset, data to send, and a signal to start transmission. It outputs a serial data line and a busy flag. The main parts include:

  • clk: Clock signal.
  • reset: Resets the transmitter state.
  • tx_start: Signal to start sending data.
  • tx_data: 8-bit data to transmit.
  • tx_serial: Serial output line.
  • tx_busy: Indicates transmitter is busy.

The transmitter uses a baud rate generator to time bit transmission and a state machine to send start bit, data bits, and stop bit.

vhdl
entity uart_tx is
    Port (
        clk       : in  std_logic;
        reset     : in  std_logic;
        tx_start  : in  std_logic;
        tx_data   : in  std_logic_vector(7 downto 0);
        tx_serial : out std_logic;
        tx_busy   : out std_logic
    );
end uart_tx;

architecture Behavioral of uart_tx is
    -- Signals and states will be declared here
begin
    -- Process for UART transmission logic
end Behavioral;
💻

Example

This example shows a simple UART transmitter that sends 8-bit data with 1 start bit (low), 8 data bits (LSB first), and 1 stop bit (high). It uses a 16x baud rate clock enable signal to time bits.

vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uart_tx is
    port(
        clk       : in  std_logic;
        reset     : in  std_logic;
        tx_start  : in  std_logic;
        tx_data   : in  std_logic_vector(7 downto 0);
        tx_serial : out std_logic;
        tx_busy   : out std_logic
    );
end uart_tx;

architecture Behavioral of uart_tx is
    type state_type is (idle, start_bit, data_bits, stop_bit);
    signal state       : state_type := idle;
    signal bit_index   : integer range 0 to 7 := 0;
    signal shift_reg   : std_logic_vector(7 downto 0) := (others => '0');
    signal baud_tick   : std_logic := '0';
    signal baud_count  : integer range 0 to 15 := 0;
    signal tx_out      : std_logic := '1';
begin
    -- Baud rate generator (assuming clk is 16x baud rate)
    process(clk, reset)
    begin
        if reset = '1' then
            baud_count <= 0;
            baud_tick <= '0';
        elsif rising_edge(clk) then
            if baud_count = 15 then
                baud_count <= 0;
                baud_tick <= '1';
            else
                baud_count <= baud_count + 1;
                baud_tick <= '0';
            end if;
        end if;
    end process;

    -- UART transmitter state machine
    process(clk, reset)
    begin
        if reset = '1' then
            state <= idle;
            tx_out <= '1';
            bit_index <= 0;
            shift_reg <= (others => '0');
            tx_busy <= '0';
        elsif rising_edge(clk) then
            if baud_tick = '1' then
                case state is
                    when idle =>
                        tx_out <= '1'; -- line idle high
                        tx_busy <= '0';
                        if tx_start = '1' then
                            shift_reg <= tx_data;
                            state <= start_bit;
                            tx_busy <= '1';
                        end if;
                    when start_bit =>
                        tx_out <= '0'; -- start bit low
                        state <= data_bits;
                        bit_index <= 0;
                    when data_bits =>
                        tx_out <= shift_reg(bit_index);
                        if bit_index = 7 then
                            state <= stop_bit;
                        else
                            bit_index <= bit_index + 1;
                        end if;
                    when stop_bit =>
                        tx_out <= '1'; -- stop bit high
                        state <= idle;
                        tx_busy <= '0';
                end case;
            end if;
        end if;
    end process;

    tx_serial <= tx_out;

end Behavioral;
Output
The tx_serial line outputs a serial stream: start bit (0), 8 data bits LSB first, then stop bit (1). The tx_busy signal is high during transmission.
⚠️

Common Pitfalls

Common mistakes when writing a UART transmitter in VHDL include:

  • Not generating the correct baud rate timing, causing wrong bit durations.
  • Forgetting to send the start bit low before data bits.
  • Sending data bits in the wrong order (should be LSB first).
  • Not setting the stop bit high at the end.
  • Not managing the tx_busy signal properly, leading to data overwrite.

Always test with a known baud rate clock and verify the serial output timing with a logic analyzer or simulation.

vhdl
-- wrong approach:
-- Sending data bits MSB first (incorrect)
-- tx_out <= shift_reg(7 - bit_index);

-- correct approach:
-- Sending data bits LSB first
-- tx_out <= shift_reg(bit_index);
📊

Quick Reference

Tips for implementing a UART transmitter in VHDL:

  • Use a baud rate generator to create a tick for bit timing.
  • Implement a state machine with states: idle, start bit, data bits, stop bit.
  • Send start bit as low, data bits LSB first, stop bit as high.
  • Use a shift register to hold data bits during transmission.
  • Use a busy flag to prevent new data start until current transmission ends.

Key Takeaways

A UART transmitter sends serial data bit by bit using a state machine and baud rate timing.
Always send a low start bit, then data bits LSB first, followed by a high stop bit.
Use a baud rate generator to ensure correct timing for each bit.
Manage a busy signal to avoid starting new transmissions before the current one finishes.
Test your UART transmitter with simulation or hardware tools to verify timing and data order.