Blue Flower

If you have some constructive remarks, please, do not hesitate to send them to me. Also it concerns a possible English language syntax mistakes. :)

 

In this article we will see how to describe UART receiver in VHDL. First of all let's

create an ISE project:

I use XC6SLX9 FPGA chip from Xilinx. You need to chose your chip. Also you can use

a different FPGA family, for example, Altera. In any case VHDL code should work for any

chip. After the project has been created we need to add VHDL source file to it. At the

beginning of the file we describe libraries will be used:

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.std_logic_unsigned.all;

use IEEE.NUMERIC_STD.ALL;

 

Then an interface should be defined by using a special entity keyword:

 

entity My_UART is
    port (
              clk:           in          std_logic;                                     -- ext. 25 MHz osc.
              rx:             in          std_logic;                                     -- UART receiver input
              rx_byte:    out        std_logic_vector (7 downto 0)    -- received byte
            );
end My_UART;

 

The entity physical signals are commented above and do not need any explanation.

After the entity follows the architecture:

 

architecture  Behavioral of  My_UART is

begin

end Behavioral;

 

Before a begin keyword all signals and constants are defined:

 

constant    clk_freq:            integer := 25_000_000;                        -- Osc. frequency

constant    uart_baud:         integer := 115200;                                -- UART baudrate

constant    uart_freq:          integer := clk_freq / (32 * uart_baud); -- UART system clock

signal        uart_divider:     integer range 0 to uart_freq;                 -- UART divider

signal        uart_clk:           std_logic;                                               -- UART divider

signal        cnt:                   integer range 0 to 15;                             -- UART clk counter

signal        sample:             std_logic;                                               -- Flag of begining

 

UART receiver should support a 115200 kbps baudrate. But receiver should read a data

on the input pin 16 times faster than actual UART transmit signal is changing. System clock

25 MHz is too high for this. That is why a simple divider is used:

 

-- sys_clk divider for generating uart_clk

process (clk)                                                         

begin

if (clk = '1' and clk'event)  then

uart_divider <= uart_divider + 1;

if (uart_divider = uart_freq)  then

uart_clk <= uart_clk xor '1';

uart_divider <= 0;

end if;

end if;

end process;

 

The main part of UART receiver is shown below. A finite state machine has been

implemented in VHDL. When it receives a byte, it outputs it to the output.

 

process (uart_clk)

variable          bitn:   integer range 0 to 9 := 0;             -- number of received bit

variable          data:  std_logic_vector (7 downto 0);    -- received byte

variable          rx_s:  std_logic_vector (2 downto 0);    -- bit sample variable

variable          rx_b:  std_logic;                                     -- received bit true value

begin

if (uart_clk = '1' and uart_clk'event) then

if (rx_b = '1' and rx = '0') then                    -- start condition checking

sample <= '1';

rx_b := rx;

else

rx_b := rx;

end if;

if (cnt = 8) then                                          -- 1st bit sample

rx_s(0) := rx;

end if;

       if (cnt = 9) then                                         -- 2nd bit sample

rx_s(1) := rx;

end if;

if (cnt = 10) then                                        -- 3rd bit sample

rx_s(2) := rx;

end if;

if (cnt = 11) then          -- if bit was sampled

-- Defining true bit value

rx_b := ((rx_s(0) and rx_s(1)) or (rx_s(1) and rx_s(2)) or ((rx_s(0) and rx_s(2))));

case (bitn) is

when 0 =>

if  (rx = '0') then

bitn := 1;

else

bitn := 0;

sample <= '0';

end if;

when 1 => data(0) := rx_b;

bitn := 2;

when 2 => data(1) := rx_b;

bitn := 3;

when 3 => data(2) := rx_b;

bitn := 4;

when 4 => data(3) := rx_b;

bitn := 5;

when 5 => data(4) := rx_b;

bitn := 6;

when 6 => data(5) := rx_b;

bitn := 7;

when 7 => data(6) := rx_b;

bitn := 8;

when 8 => data(7) := rx_b;

bitn := 9;

when 9 => bitn := 0;

sample <= '0';

if (rx = '1') then

rx_byte <= data; -- output received byte into port

end if;

end case;

end if;

end if;

end process;

 

To demonstrate that the UART receiver works, it is need to generate a bitstream for the

FPGA. To do this a constraints file *.ucf should be added to the ISE project:

 

# PlanAhead Generated physical constraints

NET "rx_byte[1]" LOC = P2;

NET "rx_byte[0]" LOC = P1;

NET "rx_byte[2]" LOC = P5;

NET "rx_byte[3]" LOC = P6;

NET "rx_byte[4]" LOC = P7;

NET "rx_byte[5]" LOC = P8;

NET "rx_byte[6]" LOC = P9;

NET "rx_byte[7]" LOC= P10;

NET "clk" LOC = P85;

NET "rx" LOC = P11;

# PlanAhead Generated IO constraints

NET "rx_byte[0]" IOSTANDARD = LVCMOS33;

NET "rx_byte[1]" IOSTANDARD = LVCMOS33;

NET "rx_byte[2]" IOSTANDARD = LVCMOS33;

NET "rx_byte[3]" IOSTANDARD = LVCMOS33;

NET "rx_byte[4]" IOSTANDARD = LVCMOS33;

NET "rx_byte[5]" IOSTANDARD = LVCMOS33;

NET "rx_byte[6]" IOSTANDARD = LVCMOS33;

NET "rx_byte[7]" IOSTANDARD = LVCMOS33;

NET "clk" IOSTANDARD = LVCMOS33;

NET "rx" IOSTANDARD = LVCMOS33;

 

After bitstream generation you will get a following picture:

 

As a UART transmitter it is posible to use any USB-UART converter like this:

In general, a setup will be like this:

 

The source code is here. :)