Experimental Manuals FPGA Tutor Risc-V

Asynchronous serial port communication, handshake mechanism, data frame, Asynchronous Serial Port Design and Experiment – FII-PRA040 Risc-V FPGA Board Experimental 10

Experiment 10 Asynchronous Serial Port Design and Experiment

10.1 Experiment Objective

Because asynchronous serial ports are very common in industrial control, communication, and software debugging, they are also vital in FPGA development.

  1. the basic principles of asynchronous serial port communication, handshake mechanism, data frame
  2. Master asynchronous sampling techniques
  3. Review the frame structure of the data packet
  4. Learning FIFO
  5. Joint debugging with common debugging software of PC (SSCOM, teraterm, etc.)

10.2 Experiment Implement

  1. Design and transmit full-duplex asynchronous communication interface Tx, Rx
  2. Baud rate of 11520 bps, 8-bit data, 1 start bit, 1 or 2 stop bits
  3. Receive buffer (Rx FIFO), transmit buffer (Tx FIFO)
  4. Forming a data packet
  5. Packet parsing

10.3 Experiment

10.3.1 Introduction to the UART Interface

A USB-B interface and a CP2102 chip are onboard for serial data communication.

The CP2102 features a high level of integration with a USB 2.0 full-speed function controller, USB transceiver, oscillator, EEPROM, and asynchronous serial data bus (UART) to support modem full-featured signals without the need for any external USB devices. See Figure 10.1 for the pyhsical picture.

Figure 10.1 USB-B Interface and CP2102 Chip Physical Picture

10.3.2 Hardware Design

Figure 10.2 Schematics of the serial port

The principle of USB serial port conversion is shown in Figure 10.2. The TTL_TX and TTL_RX of the CP2102 are connected to the FPGA to transmit and receive data. After being processed internally by the chip, the D_R_P and D_R_N are connected to the USB interface through a protection chip, and the data is transmitted with the PC to implement serial communication.

10.3.3 Introduction of the Program

The first step: the main program architecture

module uart_top


input inclk,

input rst,

input [1:0] baud_sel,

input tx_wren,

input tx_ctrl,

input [7:0] tx_data,

input tx_done,

output txbuf_rdy,

input rx_rden,

output [7:0] rx_byte,

output rx_byte_rdy,

output sys_rst,

output sys_clk,

input rx_in,

output tx_out


There are a lot of handshake signals here, with the tx prefix for the transmit part of the signal, and the rx prefix is for the receive part of the signal.

Step 2: create a new baud rate generator file

  1. Input clock 7.3728MHz (64 times 115200). The actual value is 7.377049MHz, which is because the coefficient of the PLL is an integer division, while the error caused by that is not large, and can be adjusted by the stop bit in asynchronous communication. See Figure 10.3.

Fine solution

  1. Implemented with a two-stage PLL for a finer frequency
  2. The stop bit is set to be 2 bits, which can effectively eliminate the error.

This experiment will not deal with the precision. The default input frequency is 7.3728 MHz.

Figure 10.3 PLL setting

  1. Supported baud rates are 115200,57600,38400,19200
  2. The default baud rate is 115200
  3. Source file of designing baud rate
// Send baud rate, clock frequency division selection

wire [8:0] frq_div_tx;

assign frq_div_tx = (baud_sel == 2’b00) ? 9’d63:

(baud_sel == 2’b01) ? 9’d127:

(baud_sel == 2’b10) ? 9’d255:9’d511;

reg [8:0] count_tx=9’d0;

always @ (posedge inclk)

if (rst) begin

count_tx <= 9’d0;

baud_tx <= 1’b0;


else begin

if (count_tx == frq_div_tx) begin

count_tx <= 9’d0;

baud_tx <= 1’b1;


else begin

count_tx <= count_tx + 1’b1;

baud_tx <= 1’b0;



Four different gear positions are set to select the baud rate, corresponding to the step 2, (1). The baud rate of the receiving part is similar to that of the transmitting part.

Step 3: Design the send buffer file tx_buf

  1. 8-bit FIFO, depth is 256, read/write clock separation, write full flag, read empty flag
  2. Interface and handshake
  3. rst reset signal
  4. wr_clk write clock
  5. tx_clk send clock
  6. 8-bit write data tx_data
  7. wr_en write enable
  8. ctrl writes whether the input is a data or a control word
  9. rdy buffer ready, can accept the next data frame

Transmit buffer instantiation file





.sys_rst (sys_rst),

.uart_rst (uart_rst),

.wr_clk (sys_clk),

.tx_clk (uart_clk),

.tx_baud (tx_baud),

.tx_wren (tx_wren),

.tx_ctrl (tx_ctrl),

.tx_datain (tx_data),

.tx_done (tx_done),

.txbuf_rdy (txbuf_rdy),

.tx_out (tx_out)


  1. Serial transmission, interface and handshake file design
  2. Interface design
  3. tx_rdy, send vacancy, can accept new 8-bit data
  4. tx_en, send data enable, pass to the sending module 8-bit data enable signal
  5. tx_data, 8-bit data to be sent
  6. tx_clk, send clock
  7. tx_baud, send baud rate
  8. Instantiation






.tx_rst (uart_rst),

.tx_clk (tx_clk),

.tx_baud (tx_baud),

.tx_en (tx_en),

.tx_data (tx_data),

.tx_rdy (trans_rdy),

.tx_out (tx_out)


  1. Write a testbench file to simulate the transmit module. (tb_uart)
  2. ModelSim simulation waveforms for transmit module. See Figure 10.4.

Figure 10.4 Serial port sending MoselSim simulation waveform

  1. Extended design (extended content is only reserved for users to think and practice)
  2. Design the transmitter to support 5, 6, 7, 8-bit PHY (Port physical layer)
  3. Support parity check
  4. The settings of the above steps involve FIFO, PLL, etc. (Refer to uart_top project file)

The fourth step: UART receiving module design

  1. Design of rx_phy.v
  2. Design strategies and steps
  3. Use 8 times sampling: so rx_baud is different from tx_baud, here sampling is rx_band = 8*tx_band

  4. Adopting judgments to the receiving data

Determine whether the data counter is greater than 4 after the sampling value is counted.

  1. Steps to receive data:
  2. Synchronization: refers to how to find the start bit from the received 0101 (sync_dtc)
  3. Receive start bit (start)
  4. Cyclically receive 8-bit data
  5. Receive stop bit (determine whether it is one stop bit or two stop bits)
  6. Determine if the stop bit is correct
  7. Correct, jump to step B
  8. Incorrect, jump to step A, resynchronize
  9. Do not judge, jump directly to B, this design adopts the scheme of no judgment
  10. Design of rx_buf
  11. Design strategies and steps
  12. Add 256 depth, 8-bit fifo
  13. Read and write clock separation
  14. Asynchronous clear (internal synchronization)
  15. Data appears before the rdreq in the read port
  16. Steps:
  17. Initialization: fifo, rx_phy
  18. Wait: FIFO full signal (wrfull) is 0
  19. Write: Triggered by rx_phy_byte, rx_phy_rdy of rx_phy:
  20. End of writing
  21. Back to step b and continue to wait
  22. rx_buf.v source program (Reference to project files)
  23. Receive module simulation

Content and steps

  1. tx, rx loopback test (assign rx_in = tx_out)
  2. Continue to use the testbench file in the TX section
  3. Write the testbench of rx
  4. ModelSim simulation. See Figure 10.5.
  5. Reflection and development
  6. Modify the program to complete the 5, 6, 7, 8-bit design
  7. Completing the design of the resynchronization when the start and stop have errors of the receiving end rx_phy
  8. Complete the analysis and packaging of the receiving data frame of rx_buf
  9. Using multi-sampling to design 180° alignment data sampling method, compare FPGA resources, timing and data recovery effects

Figure 10.5 rx_phy wave form

10.4 Experiment Verification

  1. Hardware interface, FII-PRA040 development board has integrated USB to serial port conversion

UART chip






  1. Write a hardware test file
  2. Test plan: connect development board CON8 to host USB interface
  3. Using test software such as teraterm, SSCOM3, etc., you can also write a serial communication program (C#, C++, JAVA, Python…)
  4. PC sends data in a certain format
  5. The test end uses a counter to generate data in a certain format.
  6. Write the test program hw_tb_uart and instantiate uart_top in it.
  7. Set hw_tb_uart to the top level, instantiate the previous program, and then verify it
  8. Pin assignmnets:

Table 10.1 Serial port experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
Inclk CLK_50M G21 Input clock
rst KEY2 Y6 Reset signal
rx_in TTL_RX E16 Serial data received
tx_out TTL_TX F15 Serial data transmiteed
  1. Observe the experiment result
  2. Observe the data received by the PC. See in Figure 10.6.
  3. Observe the data received by the FPGA with SignalTap II

Figure 10.5 Data transmitted displayed on the host computer

  1. The receiving part has been skipped here. You are encouraged to try it on your own.

Related posts