Thursday, March 28, 2024

Designing with FPGAs: An RS232 UART Controller (Part 3 of 5)

Varsha Agrawal

The first and second parts of the article discussed the implementation of I2C master controller and LCD display using FPGAs. The focus in this part is on designing an RS232 UART controller using an FPGA for both transmission and reception of data. The basics of RS232 protocol, data transmission and VHDL code along with details are presented in the following paragraphs.

Serial and parallel data transmission
Digital data can be transmitted between two devices using either serial mode or parallel mode of transmission. In parallel mode of transmission, multiple bits are sent simultaneously on different channels (wires) and are synchronised to a clock (Fig. 1). Therefore parallel transmission of data is a type of synchronous data transmission. Parallel transmission of data necessitates use of at least as many lines as there are bits in the word being transmitted.

Examples of parallel transmission protocols include industry standard architecture (ISA), small computer system interface (SCSI), peripheral component interconnect (PCI), IEEE-1284 and IEEE-488. They are used mainly for connections between test instruments or printers and computers located at close distances and within a computer system to transfer data between different units.

Serial mode of data transmission involves the sending of data one bit at a time sequentially over a single communication line (Fig. 2). Serial transmission can either be synchronous or asynchronous.

F2A_Fig_1
Fig. 1: Parallel mode of transmission
5AB_Fig_2
Fig. 2: Serial mode of transmission

In synchronous transmission, groups of bits are combined into frames and frames are sent continuously with or without the data to be transmitted.

- Advertisement -

In asynchronous transmission, groups of bits are sent as independent units with start/stop flags. Serial transmission is used for sending data between two computers or between a computer and an external device located some distance away.

Examples of serial communication include RS232, RS422, RS423, RS485, inter-integrated circuit (I2C), serial peripheral interface (SPI), universal serial bus (USB), FireWire and Ethernet.

An RS232 bus is an unbalanced bus capable of full-duplex communication between two receiver/transmitter pairs, named data terminal equipment (DTE) and data communication equipment (DCE). RS422 and RS485 are balanced, twisted-pair interfaces capable of speeds up to 10Mbps and distances up to 1220m (or 4000 feet). Being differential buses, they offer better noise immunity as compared to a single-ended, unbalanced bus such as RS232. The I2C bus was discussed in the first part of the series having two signal wires, namely, data (SDA) and clock (SCL).

- Advertisement -

The SPI is a synchronous serial bus comprising four signals, namely, the master out slave in (MOSI), master in slave out (MISO), serial clock (SCK) and active-low slave select (SS). Microwire is a three-wire synchronous master/slave bus, with serial data out of the master (SO), and serial data into the master (SI) and signal clock (SK).

FireWire is a serial bus interface standard for high-speed communications and isochronous real-time data transfer. Ethernet is a family of computer networking technologies for local area networks (LANs). Systems communicating over Ethernet divide a stream of data into shorter pieces called frames. Each frame contains source and destination addresses and error-checking data so that damaged data can be detected and re-transmitted.

The focus in this article is on transmitting and receiving data using RS232 protocol. Therefore this protocol is discussed in detail in subsequent paragraphs.

RS232 interface
RS232 interface is the Electronic Industries Association (EIA) standard for serial transmission of binary data between two devices, namely, the data terminal equipment (DTE) and the data communication equipment (DCE). The standard defines the electrical characteristics and timings of signals and physical size and pin-out of connectors.

The RS232 standard was introduced in the year 1962 by Radio Sector of EIA. Five revisions have been made to the standard since then. The most recent version of the standard is RS232 E and it is now addressed as EIA/TIA-232 E (Electronic Industry Association and Telecommunications Industry Association).

C56_Fig_3
Fig. 3: RS232 data format
888_Fig_4
Fig. 4: Data frame when character ‘A’ is sent

The RS232 standard specifies that a logic ‘1’ is sent as a voltage in the range of –15V to –5V and logic ‘0’ is sent as a voltage in the range of +5V to +15V. The standard specifies that a voltage of at least 3V amplitude will be recognised correctly at the receiver according to their polarity. It is an asynchronous standard and the transmitted bit sequence comprises a start bit, seven or eight data bits, an optional parity bit and one or more stop bits. The start bit is always low (logic ‘0’ or space) and the stop bit is always high (logic ‘1’ or mark). The parity bit used can be even parity or odd parity. The data format used for RS232 transmission is shown in Fig. 3. Fig. 4 shows the data frame used to send character ‘A’ when one stop bit and odd parity is used.

RS232 communication is implemented using a 9-pin connector (DB9) or a 25-pin connector (DB25). The DB25 connector is not used for normal communications as most of the pins are not needed. DB9 connector is used for serial communications using PCs. Figs 5 and 6 show the pin details of the DB25 and DB9 connectors, respectively.

The functionalities offered by the different pins of the DB9 connector are as follows:
TXD—This pin carries data from the computer (DTE) to the serial device (DCE)
RXD—This pin carries data from the serial device (DCE) to the computer (DTE)
DTR—It is an indicator from DTE and is used by it to signal that it is ready to communicate with DCE
DSR—It is an indicator from DCE that it is on
RTS—Requests clearance to send data to DCE
CTS—Used by the DCE to acknowledge DTE’s RTS signal
DCD—It is an indicator that DCE is connected to the telephone line

RI—It is an indicator that DCE has detected an incoming ring signal on the telephone line

RS232 was designed to be used for communication between a DTE (computer) and a DCE (modem).

In addition to communication between computer and a modem, RS232 is now widely used for direct connections between data acquisition devices and computer systems. In such cases, both the devices function as DTE. For this purpose, a null modem connection is used rather than having pin-to-pin connections of the modem cable. In a null modem connection, the transmission and the receiving lines are cross-linked. In some cases, the handshaking signals are also cross-linked, depending upon the application.

In a nutshell, null modem cables are used when two DTEs have to communicate with each other and pin-to-pin connections are used when a DTE and a DCE have to communicate with each other.

Most systems designed today do not operate using RS232 voltage levels. Therefore level conversion is necessary to implement RS232 communication. Level conversion is performed using line drivers and receivers. Some of the line drivers/receivers used for performing translation include MAX232 (which is a dual EIA-232 driver/receiver intended for EIA/TIA 232 E and V.28 communication interfaces), MAX235 (which is a +5V powered multichannel EIA-232 driver/receiver also intended for EIA/TIA 232 E and V.28 communication interfaces, particularly suited to applications where ±12V is not available) and so on.

VHDL code description
The VHDL code (rs232_fpga.vhd) of this article included in this month’s EFY DVD is used to transmit and receive data using RS232 protocol at 19.2kbps using odd parity.

The code implements the transmitter and the receiver finite state machine (FSM) to transmit and receive data using RS232 protocol. The code begins with the standard library to be included. The Entity section defines the input and the output connections including the 50MHz clock (CLK), reset (RST), data byte to be transmitted (Din), latch data (LD) and serial data in (Rx) as inputs and data byte received (Dout), serial data out (Tx), transmit busy flag (TxBusy), receive error flag (RxErr) and receive ready flag (RxRDY) as outputs.

The different constants and signals used to implement the transmitter and the receiver FSMs are defined in the Architecture section. Constant Fxtal is an integer with a value of 50,000,000 corresponding to the clock frequency of 50MHz (50,000,000). The Parity and the Even constants are set as True and False, respectively. The constant Baud is assigned a value 19200 corresponding to baud rate of 19.2 kbps. The two constants MaxFactor and Divisor2 have values 2604 (Fxtal/Baud) and 1302 (Fxtal/Baud/2), respectively. All the constants mentioned above will be used in the transmitter FSM as well as in the receiver FSM.

638_Fig_5
Fig. 5: Pin details of DB25 connector (Courtesy:www.omega.com)

Next in the VHDL code have been defined the signals used in the transmitter FSM followed by the signals used in the receiver FSM. They have been defined separately for ease of the readers. Signal TxFSM is of type TxFSM_State having five states, namely, Idle, Load_Tx, Shift_Tx, Parity_Tx and Stop_Tx. The initial state of the signal TxFSM is Idle. Other signals defined are Tx_Reg which is a 9-bit std_logic_vector signal used as a transmit register. TxDivisor and TxDiv are integers that can have values ranging from 0 to 2604 and TxBitCnt is also an integer having range from 0 to 15. TopTx and Tx_Par are std_logic signals.

The signals used in the receiver FSM are RxFSM, Rx_Reg, RxDivisor, RxDiv, TopRx, RxBitCnt, RxRDYi, Rx_Par and Rx_r. RxFSM is a signal of type RxFSM_State having eight states, namely, Idle, Start_Rx, Shift_Rx, Edge_Rx, Parity_Rx, Parity_2, Stop_Rx and RxOVF. RxFSM is in the initial state, that is, the Idle state. Rx_Reg is an 8-bit receive register used to store the received serial data. Signals RxDivisor and RxDiv are integers having values ranging from 0 to 1302. RxBitCnt is an integer having values ranging from 0 to 15. TopRx, RxRDYi, Rx_Par and Rx_r are std_logic signals.

The first line after the ‘begin’ statement assigns the value of RxRDYi to RxRDY. RxRDY is the flag indicating that data is available during reception. The first process is used for receiver input resynchronisation. It has RST and CLK in the sensitivity list. If RST is at logic level ‘1,’ the resync signal Rx_r is set to logic level ‘1,’ else on the rising edge of the input clock (CLK) the value of the serial data in (Rx) is sent to Rx_r.

The next process is used for baud rate conversion. This process also has RST and CLK in the sensitivity list. When RST is at logic level ‘1,’ the values of RxDivisor and TxDivisor are set to ‘0,’ else on the rising edge of the clock, RxDivisor and TxDivisor are assigned values [(Divisor2 – 1) = 1301] and [{(2 × Divisor2) – 1} = 2603], respectively.

The next process is used for receiver clock generation. The receiver clock has a time period of bit time/2. The process has the RST and CLK signals in the sensitivity list. When RST is at logic level ‘1,’ the values of RxDiv and TopRx are set to ‘0.’

RxDiv is the receive clock generation register and TopRx is the receive master clock pulse. If the RST is at logic level ‘0,’ on the rising edge of the clock CLK, TopRx is set to ‘0.’ If the RxFSM signal is in the initial Idle state, RxDiv is also set to ‘0,’ otherwise if RxDiv is equal to RxDivisor (1301), it is set to ‘0’ and TopRx is set to ‘1,’ else value of RxDiv is incremented by one. The process generates a pulse having an on time of 1/50×106s = 20 ns and a frequency of 38.4kHz whenever the RxFSM signal is not in the Idle state.

The next process generates the transmitter clock having the same time period as the bit time. The process is similar to the one used for generating the receiver clock pulse. It generates a clock pulse having 20ns width at a frequency of 19.2kHz. The major difference between the transmitter and the receiver clocks is that the transmitter clock runs continuously and does not depend upon the state of the FSM.

The transmitter FSM is implemented next. The LSB of the transmit register Tx_Reg is transferred as serial data out to the Tx pin. The transmitter FSM is implemented in the Tx_FSM labelled process. It has RST and CLK in the sensitivity list. When RST pin is at logic level ‘1,’ the transmit register is set to ‘1FF,’ the state of TxFSM signal is set to Idle and TxBitCnt, TxBusy and Tx_Par are all set to ‘0.’ If the RST pin is at logic level ‘0,’ on the rising edge of the clock CLK, TxBusy is set to logic level ‘1,’ indicating that the system is busy.

When the FSM is in the Idle state and the latch data pin LD is at logic level ‘1,’ the data byte to be transmitted is appended with a logic bit ‘1’ and assigned to the transmit register Tx_Reg. The busy flag is set to logic level ‘1’ and the FSM goes to the Load_Tx state. In case the latch data pin LD is at logic level ‘0,’ the TxBusy flag is set to logic level ‘0,’ indicating that there is no data to be transmitted.

When the FSM is in the Load_Tx state and the transmit clock TopTx is at logic level ‘1,’ the FSM moves to the next state Shift_Tx. The start bit [Tx_Reg[0]] is set to logic level ‘0’ and the transmit bit count TxBitCnt is assigned a value of 9 (count of start, data and the parity bits to be transmitted). The transmitter FSM is designed using odd parity (Boolean constant parity = True and Boolean constant even = False). The same can be changed as per the design requirement. Since, the parity chosen is odd, value of Tx_Par is ‘1.’

When the FSM is in the Shift_Tx state and the transmit clock TopTx is at logic level ‘1,’ the value of TxBitCnt is decremented by ‘1.’ The Tx_Par bit is built over eight clock cycles and is generated by xoring the Tx_Par bit with the second LSB bit of the transmit register Tx_Reg. The Tx_Reg is then right shifted and ‘1’ is appended as the MSB. The process is repeated till TxBitCnt is ‘1.’ When the value of TxBitCnt equals ‘1,’ we get the final value of Tx_Par bit which is then transmitted later. The FSM goes to the Stop_Tx state if the system is designed without using parity, otherwise it goes to the Parity_Tx state and the parity bit is assigned to the LSB of the transmit register. Since in our case we are using odd parity, the FSM goes to the Parity_Tx state.

In the Parity_Tx state, when the transmit clock TopTx is at logic level ‘1,’ the stop bit is assigned to the LSB of the transmit register Tx_Reg and the FSM goes to the Stop_Tx state. In the Stop_Tx state, the stop bit is transmitted and the FSM goes to the Idle state.

114_Fig_6
Fig. 6: Pin details of DB9 connector

Download Source Code: click here

The process that implements the receiver FSM (Rx_FSM) also has reset (RST) and clock (CLK) inputs in the sensitivity list. If RST is at logic level ‘1,’ all the bits of the receive register (Rx_Reg) and data byte received (Dout) are made zero. The receive bit count (RxBitCnt), receive error (RxErr), receive ready (RxRdyi) and the receive parity (Rx_Par) are all cleared to zero and the FSM is made to go to the Idle state.

If the RST pin is at logic level ‘0,’ on the rising edge of the clock CLK, it is checked whether the receive ready signal (RxRdyi) is at logic level ‘1’ or ‘0.’ If it is at logic level ‘1,’ it indicates that the word has been received and the receive error flag (RxErr) and the receive ready signal (RxRdyi) are made zero.

After that the receiver FSM is implemented. If the FSM is in the Idle state, the receive count bit (RxBitCnt) is set to zero. Then the parity bit is checked. If the parity is even parity, the receive parity bit (Rx_Par) is set to zero, else it is set to one. If the receive signal (Rx_r) is zero, the FSM goes to the next state, that is, the Start_Rx state. When in the Start_Rx state, the FSM waits for the first data bit. When the receive clock (TopRx) is at logic level ‘1’ and the Rx_r signal is still at logic level ‘1’ then a warning is issued and the FSM goes to the RxOVF state, else the FSM goes to the Edge_Rx state.

RxOVF state is the error-handling state that reports the error and sends the FSM to the Idle state when Rx is at logic level ‘1.’ In the Edge_Rx state, if the receive clock (TopRx) is at logic level ‘1,’ the FSM goes to the Shift_Rx state if the RxBitCnt is not equal to eight. If the value of receive bit count (RxBitCnt) equals eight, the FSM goes to Parity_Rx state, if the parity is used in the receiver design, else it goes to the Stop_Rx state. In the Shift_Rx state, when the receiver clock (TopRx) is at logic level ‘1,’ the value of receive bit count (RxBitCnt) is incremented by one and the receive register (Rx_Reg) is shifted right by including the received bit as the MSB.

The Rx_Par bit is updated by performing the xor operation on the received bit and the initial parity bit. Next, the FSM goes to the Edge_Rx state. The FSM moves between the Edge_Rx and the Shift_Rx states till the receive bit count is equal to eight.

In the Parity_Rx state, the parity bit is sampled. When the receive clock (TopRx) is at logic level ‘1,’ it is checked whether Rx_Par and Rx_r bits are the same. In case they are the same, then the FSM goes to the Parity_2 state, else it goes to the error state RxOVF.

In the Parity_2 state, when the receive clock (TopRx) is at logic level ‘1,’ the FSM goes to the Stop_Rx state. The Parity_2 state basically generates a wait period of half the bit time. In the Stop_Rx state, when the receive clock (TopRx) is at logic level ‘1,’ if the Rx_r signal is high then the contents of the receive register (Rx_reg) are sent to the receiver output pins (Dout), the receiver ready signal (RxRdyi) is set to logic level ‘1’ and the FSM goes to the Idle state. The FSM then reports the character received in decimal after suitable conversion. If the Rx_r signal is not at logic level ‘1,’ the FSM goes to the error state RxOVF. The last statement implements the case that when the FSM is in any other state, then it should go to the Idle state.

Conclusion
This part described how to establish an RS232 communication link using an FPGA. In the next part, we will discuss how to manage clocks using clock managers in FPGA to generate a clock of the desired frequency from a given input clock.


Varsha Agrawal is a scientist at Laser Science and Technology Center (LASTEC), a premier DRDO lab working in the field of laser-based defence systems. She has more than 13 years of R&D experience in the design and development of a variety of systems for defence-related applications. She has authored two books and published more than 20 research papers and technical articles.

SHARE YOUR THOUGHTS & COMMENTS

Electronics News

Truly Innovative Tech

MOst Popular Videos

Electronics Components

Calculators