This website uses cookies. By using this site, you consent to the use of cookies. For more information, please take a look at our Privacy Policy.
Home > FPGA Technical Tutorials > Design Recipes for FPGAs Using Verilog and VHDL > Serial Communications > RS-232

TABLE OF CONTENTS

Xilinx FPGA FPGA Forum

RS-232

FONT SIZE : AAA

Introduction 

The basic approach of RS-232 serial transmission is that of a UART. UART stands for Universal Asynchronous Receiver/Transmitter. It is the standard method of translating a serial communication stream into the parallel form used by computers. RS-232 is a UART that has a specific standard defined for start, stop, break, data, parity, and pin names.

RS-232 Baud Rate Generator

The RS-232 is an asynchronous transmission scheme and so the correct clock rate must be defined prior to transmission to ensure that the data is transmitted and received correctly. The RS-232 baud rate can range from 1200 baud up to 115200 baud. This is based on a standard clock frequency of 14.7456 MHz, and this is then divided down by 8, 16, 28, 48, 96, 192, 384, and 768 to get the correct baud rates. We therefore need to define a clock divider circuit that can output the correct baud rate configured by a control word. We have obviously got 8 different ratios, and so we can use a 3-bit control word (baud[2:0]) plus a clock and reset to create the correct frequencies, assuming that the basic clock frequency is 14.7456 MHz (Figure 15.3).

The VHDL for this controller is given as follows and uses a single process to select the correct baud rate and another to divide down the input clock accordingly:

1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.std_logic_unsigned.all; 45 entity baudcontroller is 6 port(

1 library ieee;

2 use ieee.std_logic_1164.all; 

3 use ieee.std_logic_unsigned.all; 

4

5 entity baudcontroller is

6 port(

Baud rate generator. (2).png

Figure 15.3 

Baud rate generator.

7 clk : in std_logic;

8 rst : in std_logic;

9 baud : in std_logic_vector(0 to 2);

10 clkout : out std_logic;

11 end baudcontroller;

12

13 architecture simple of baudcontroller is

14 signal clkdiv : integer := 0;

15 signal count : integer := 0;

16 begin

17 div: process (rst, clk)

18 begin

19 if rst=’0’ then

20 clkdiv <= 0;

21 count <= 0;

22 elsif rising_edge(clk) then

23 case baud is

24 when "000" => clkdiv <= 7; −− 115200

25 when "001" => clkdiv <= 15; −− 57600

26 when "010" => clkdiv <= 23; −− 38400

27 when "011" => clkdiv <= 47; −− 19200

28 when "100" => clkdiv <= 95; −− 9600

29 when "101" => clkdiv <= 191; −− 4800

30 when "110" => clkdiv <= 383; −− 2400

31 when "111" => clkdiv <= 767; −− 1200

32 when others => clkdiv <= 7;

33 end case;

34 end if;

35 end process;

36

37 clockdivision: process (clk, rst)

38 begin

39 if rst=’0’ then

40 clkdiv <= 0;

41 count <= 0;

42 elsif rising_edge(clk) then

43 count <= count + 1;

44 if (count > clkdiv) then

45 clkout <= not clkout;

46 count <= 0;

47 end if;

48 end if;

49 end process;

50 end simple;

The Verilog equivalent for this baud rate controller is given as follows and uses separate code to select the correct baud rate and another to divide down the input clock accordingly:


1 module baudcontroller (

2 clk, / clock

3 rst, / reset

4 clkout / baud rate output

5 );

67 input clk;

8 input rst;

9 output clkout;

10 reg clkout;

11

12 parameter baudrate = 9600;

13

14 always_init

15 case baudrate

16 115200: clkdiv = 7;

17 57600: clkdiv = 15;

18 38400: clkdiv = 23;

19 19200: clkdiv = 47;

20 9600: clkdiv = 95;

21 4800: clkdiv = 191;

22 2400: clkdiv = 383;

23 1200: clkdiv = 767;

24

25

26 when "000" => clkdiv <= 7; −− 115200

27 when "001" => clkdiv <= 15; −− 57600

28 when "010" => clkdiv <= 23; −− 38400

29 when "011" => clkdiv <= 47; −− 19200

30 when "100" => clkdiv <= 95; −− 9600

31 when "101" => clkdiv <= 191; −− 4800

32 when "110" => clkdiv <= 383; −− 2400

33 when "111" => clkdiv <= 767; −− 1200

34 when others => clkdiv <= 7;

35

36 always @(CharIn)

37 case (CharIn)

38 4’h0: HexOut = 7’b1000000;

39 4’h1: HexOut = 7’b1111001;

40 4’h2: HexOut = 7’b0100100;

41 4’h3: HexOut = 7’b0110000;

42 4’h4: HexOut = 7’b0011001;

43 4’h5: HexOut = 7’b0010010;

44 4’h6: HexOut = 7’b0000010;

45 4’h7: HexOut = 7’b1111000;

46 4’h8: HexOut = 7’b0000000;

47 4’h9: HexOut = 7’b0011000;

48 4’hA: HexOut = 7’b0001000;

49 4’hB: HexOut = 7’b0000011;

50 4’hC: HexOut = 7’b1000110;

51 4’hD: HexOut = 7’b0100001;

52 4’hE: HexOut = 7’b0000110;

53 4’hF: HexOut = 7’b0001110;

54 default: HexOut = 7’b0110110;

55 endcase

56

57 architecture simple of baudcontroller is

58 signal clkdiv : integer := 0;

59 signal count : integer := 0;

60 begin

61 div: process (rst, clk)

62 begin

63 if rst=’0’ then

64 clkdiv <= 0;

65 count <= 0;

66 elsif rising_edge(clk) then

67 case baud is

68 when "000" => clkdiv <= 7; −− 115200

69 when "001" => clkdiv <= 15; −− 57600

70 when "010" => clkdiv <= 23; −− 38400

71 when "011" => clkdiv <= 47; −− 19200

72 when "100" => clkdiv <= 95; −− 9600

73 when "101" => clkdiv <= 191; −− 4800

74 when "110" => clkdiv <= 383; −− 2400

75 when "111" => clkdiv <= 767; −− 1200

76 when others => clkdiv <= 7;

77 end case;

78 end if;

79 end process;

80

81 clockdivision: process (clk, rst)

82 begin

83 if rst=’0’ then

84 clkdiv <= 0;

85 count <= 0;

86 elsif rising_edge(clk) then

87 count <= count + 1;

88 if (count > clkdiv) then

89 clkout <= not clkout;

90 count <= 0;

91 end if;

92 end if;

93 end process;

94 end simple;

RS-232 Receiver

The RS-232 receiver must wait for data to arrive on the RX line and has a specification defined as follows: <number of bits><parity><stop bits>. So, for example an 8-bit, No parity, 1 stop bit specification would be given as 8N1. The RS-232 voltage levels are between −12V and +12V, and so we will assume that an interface chip has translated these to standard logic levels (0-5 V or 0-3.3 V, for example). A sample bit stream would be of the format shown in Figure 15.4.

The idle state for RS-232 is high, and in this figure, after the stop bit, the line is shown as going low, when in fact that only happens when another data word is coming. If the data transmission has finished, then the line will go high (idle) again. We can in fact model this as a simple state machine as shown in Figure 15.5.

Example serial data bit streampng

Figure 15.4 

Example serial data bit stream.

Figure 15.5.png

Figure 15.5 

Basic serial data receiver state machine.

We can implement this simple state machine in VHDL using the following model:

1 library ieee;

2 use ieee.std_logic_1164.all; 3 use ieee.std_logic_unsigned.all; 45 entity serialrx is

6 port( 7 clk : in std_logic;

8 rst : in std_logic;

9 rx : in std_logic;

10 dout : out std_logic_vector (7 downto 0)

11 );

12 end serialrx;

13

14 architecture simple of serialrx is

15 type state is (idle, s0, s1, s2, s3, s4, s5, s6, s7, stop);

16 signal current_state, next_state : state;

17 signal databuffer : std_logic_vector(7 downto 0);

18 begin

19 receive: process (rst, clk)

20 begin

21 if rst=’0’ then

22 current_state <= idle;

23 for i in 7 downto 0 loop

24 dout(i) <= ’0’;

25 end loop;

26 elsif rising_edge(clk) then

27

28 case current_state is

29 when idle =>

30 if rx = ’0’ then

31 next_state <= s0;

32 else

33 next_state <= idle;

34 end if;

35 when s0 =>

36 next_state <= s1;

37 databuffer(0) <= rx;

38 when s1 =>

39 next_state <= s2;

40 databuffer(1) <= rx;

41 when s2 =>

42 next_state <= s3;

43 databuffer(2) <= rx;

44 when s3 =>

45 next_state <= s4;

46 databuffer(3) <= rx;

47 when s4 =>

48 next_state <= s5;

49 databuffer(4) <= rx;

50 when s5 =>

51 next_state <= s6;

52 databuffer(5) <= rx;

53 when s6 =>

54 next_state <= s7;

55 databuffer(6) <= rx;

56 when s7 =>

57 next_state <= stop;

58 databuffer(7) <= rx;

59 when stop =>

60 if rx = ’0’ then

61 next_state <= s0;

62 else

63 next_state <= idle;

64 end if;

65 dout <= databuffer;

66 end case;

67 current_state <= next_state;

68 end if;

69 end process;

70 end;

In turn, the same approach of a state machine can be used in Verilog, with the model as shown below:

1 module serial_rx (

2 dout, / Output Value

3 clk, / Clock

4 rst, / Reset

5 rx / Input receiver value

6 );

789 output [3:0] dout;

10 input clk;

11 input rst;

12 input rx;

13

14 reg [3:0] dout;

15

16 reg [3:0] current_state, next_state; / state variable

17

224 Chapter 15

18 parameter idle=0,s0=1, s1=2, s2=3, s3=4,s4=5,s5=6,s6=7,s7=8,stop=9;

19

20 always @(state)

21 begin

22 case (state)

23 s0:

24 dout[0] = rx;

25 s1:

26 dout[1] = rx;

27 s2:

28 dout[2] = rx;

29 s3:

30 dout[3] = rx;

31 s4:

32 dout[4] = rx;

33 s5:

34 dout[5] = rx;

35 s6:

36 dout[6] = rx;

37 s7:

38 dout[7] = rx;

39 endcase

40 end

41

42 always @(posedge clk)

43 begin

44 if (rst == 0)

45 state = idle;

46 else

47 case (state)

48 idle:

49 state = s0;

50 s0:

51 state = s1;

52 s1:

53 state = s2;

54 s2:

55 state = s3;

56 s3:

57 state = s4;

58 s4:

59 state = s5;

60 s5:

61 state = s6;

62 s7:

63 state = stop;

64 stop:

65 state = idle;

66 default:

67 state=idle;

68 endcase

69 end

70

71 endmodule



  • XC2V2000-6FGG676C

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 2M Gates 24192 Cells 820MHz 0.15um Technology 1.5V 676-Pin FBGA
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Obsolete -

    RoHS:

  • XCS30XL-4TQ144Q

    Manufacturer:Xilinx

  • Xilinx TQFP144
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS: -

  • XC3090A-6PC84C

    Manufacturer:Xilinx

  • FPGA XC3000 Family 6K Gates 320 Cells 135MHz 5V 84-Pin PLCC
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS: No RoHS

  • XC2V250-4CS144I

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 250K Gates 3456 Cells 650MHz 0.15um Technology 1.5V 144-Pin CSBGA
  • Product Categories:

    Lifecycle:Obsolete -

    RoHS: No RoHS

  • XC2V250-4FG456I

    Manufacturer:Xilinx

  • FPGA Virtex-II Family 250K Gates 3456 Cells 650MHz 0.15um Technology 1.5V 456-Pin FBGA
  • Product Categories: FPGAs

    Lifecycle:Obsolete -

    RoHS:

Need Help?

Support

If you have any questions about the product and related issues, Please contact us.