FPGA for Beginners FPGA Tutor Pocket Boards

FPGA Tutorial – Asynchronous Serial Port Design and Experiment – FPGA for Beginner – Experiment 10

Experiment 10 Asynchronous Serial Port Design and Experiment

10.1 Experiment Objective

  1. Because asynchronous serial ports are very common in industrial control, communication, and software debugging, they are also vital in FPGA development.
  2. Learning the basic principles of asynchronous serial port communication, handshake mechanism, data frame
  3. Master asynchronous sampling techniques
  4. Review the frame structure of the data packet
  5. Learning FIFO
  6. Joint debugging with common debugging software of PC (SSCOM, teraterm, etc.)

10.2 Experiment Requirement

  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

  1. Build new project named uart_frame, select 10Cl010YF144C8G for device.
  2. Add new file named uart_top, add a PLL (can be copied from the previous experiment)

module uart_top

(

input inclk,

input rst,

Input baud_sel,

input rx,

output intx

);

wire sys_clk;

wire uart_clk;

wire sys_rst;

wire uart_rst;

pll_sys_rst pll_sys_rst_inst

(

.inclk (inclk),

.sys_clk (sys_clk),

.uart_clk (uart_clk),

.sys_rst (sys_rst),

.uart_rst(uart_rst)

);

endmodule

  1. New baud rate generator file
  2. 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 Fig 10. 1.

Fine solution

Implemented with a two-stage PLL for a finer frequency

      1. 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.

Fig 10. 1 PLL setting

  1. Supported baud rates are 115200,57600,38400,19200
  2. The default baud rate is 115200
  3. Design of baud rate (Refer to the project files UART_FRAME)
  4. Instantiate and set it as top level

wire tx_band;

Wire tx_band;

baud_rate

#(.div(64))

baud_rate_inst

(

.rst (uart_rst),

.inclk (uart_clk),

.baud_sel (baud_sel),

.baud_tx (baud_tx),

);

  1. Baud rate design source file

module baud_rate

#(parameter div=64)

(

input rst,

input inclk,

input [1:0] baud_sel,

output reg baud_tx,

output reg baud_rx

);

wire [8:0] frq_div_tx; //Send baud rate, clock frequency division selection

assign frq_div_tx=(baud_sel==2’b0)?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;

end

else begin

if(count_tx==frq_div_tx) begin

count_tx <=9’d0;

baud_tx<=1’b1;

end

else begin

count_tx<=count_tx+1’b1;

baud_tx<=1’b0;

end

end

wire [6:0] frq_div_rx; //Accept partial baud rate design

assign frq_div_rx=(baud_sel==2’b0)?7’d7:

(baud_sel==2’b01)?7’d15:

(baud_sel==2’b10)?7’d31:7’d63;

 

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

always@(posedge inclk)

if(rst) begin

count_rx <=9’d0;

baud_rx <=1’b0;

end

else begin

if(count_rx==frq_div_rx) begin

count_rx <=9’d0;

baud_rx<=1’b1;

end

else begin

count_rx<=count_rx+1’b1;

baud_rx<=1’b0;

end

end

endmodule

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

tx_buf

#(.TX_BIT_LEN(8),.STOP_BIT(2))

tx_buf_inst

(

.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. Send buffer source file (Refer to the project file)
  2. Serial transmission, interface and handshake file design
  3. Interface design
      1. tx_rdy, send vacancy, can accept new 8-bit data
      2. tx_en, send data enable, pass to the sending module 8-bit data enable signal
      3. tx_data, 8-bit data to be sent
      4. tx_clk, send clock
      5. tx_baud, send baud rate
  4. Instantiation

tx_transmit

#(.DATA_LEN(TX_BIT_LEN),

.STOP_BIT(STOP_BIT)

)

tx_transmit_inst

(

.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. Source file (Refer to the project files)
  2. Send file testbench.v (Refer to the project file tb_uart)
  3. Send ModelSim simulation. See Fig 10. 2 (Already saved as wave.do file)

Fig 10. 2 ModelSim simulation waves sent by serial

  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)

UART accept file design

  1. Design of rx_phy.v

Design strategies and steps

Use 8 times sampling: so rx_baud is different from tx_baud, here sampling is rx_band = 8*tx_band

Adopting multiple judgments to realize the judgment of receiving data. Determine whether the data counter is greater than 4 after the sampling value is counted.

      1. Steps to receive data:
  1. Synchronization: refers to how to find the start bit from the received 0101… sync_dtc
  2. Receive start bit (start)
  3. Cyclically receive 8-bit data
  4. Receive stop bit (determine whether it is one stop bit or two stop bits)

Determine if the stop bit is correct

Correct, jump to step ii

Error, jump to step i, resynchronize

Do not judge, jump directly ii, this design adopts the scheme of no judgment

  1. rx_phy source file (Refer to the project file)
  2. The design of rx_buf

Design strategies and steps

Add 256 depth, 8-bit fifo

  1. Read and write clock separation
  2. Asynchronous clear (internal synchronization)
  3. Data appears before the rdreq in the read port

Steps:

  1. Initialization: fifo, rx_phy
  2. Wait: FIFO full signal (wrfull) is 0
  3. Write: Triggered by rx_phy: rx_phy_byte, rx_phy_rdy
  4. End of writing
  5. Back to ii and continue to wait

rx_buf.v source program (Reference to project files)

Receive simulation incentive

Content and steps

  1. tx, rx loopback test (assign rx_in = tx_out)
  2. Continue to use the incentive file in the TX section
  3. Writing the incentive part of rx

Modelsim simulation, as shown in Fig 10. 3

Fig 10. 3 ry_phy waveform

Reflection and expansion

  1. Modify the program to complete the 5, 6, 7, 8-bit design
  2. Completing the design of the resynchronization when the start and stop have errors of the receiving end rx_phy
  3. Complete the analysis and packaging of the receipt frame of rx_buf
  4. Using multi-sampling to design 180° alignment of data, compare with FPGA resources, timing and data recovery effects

Hardware test

Hardware Test
Hardware Test

Fig 10. 4 USB to serial conversion

Firstly, Use FII-PR006 to test

Secondly, FPGA and UART pin mapping table. See Table 10. 1

UART RXD TXD
Schematic Name JTAG_TXD_O JTAG_RXD_I
FPGA Pin 144 143

Table 10. 1 FPGA and UART pin mapping table

Thirdly, lock the pins, and recompile

Fourthly, write a hardware test file

  1. Development board J2 is connected to the host USB interface
  2. Using test software such as teraterm, SSCOM3, etc. You can also write a serial communication program (C#, C++, JAVA, Python…).
  3. PC sends data in a certain format
  4. The test end uses a counter to generate data in a certain format.
  5. The test procedure is as follows (hw_tb_uart)

module hw_tb_uart(

input inclk,

input rst,

input rx_in,

output tx_out

);

wire [1:0] baud_sel=2’b00; //Default baud rate is 115200

reg tx_wren=0;

reg tx_ctrl=0;

reg [7:0] tx_data=0;

reg [7:0] tx_len=0;

reg tx_done;

wire txbuf_rdy;

wire sys_clk;

wire sys_rst;

reg [7:0] count=0;

reg [3:0] trans_st;

always@(posedge sys_clk)

if(sys_rst)begin

trans_st <=0;

tx_wren <=1’b0;

tx_ctrl <=1’b0;

tx_data <=8’b0;

tx_done <=1’b0;

tx_len <=0;

tx_len <=0;

count <=8’d0;

end

else case(trans_st)

0:begin

trans_st <=1;

tx_wren <=1’b0;

tx_ctrl <=1’b0;

tx_data <=8’b0;

tx_done <=1’b0;

tx_len <=16;

end

1:begin

tx_wren <=1’b0;

tx_ctrl <=1’b0;

tx_data <=8’b0;

tx_done <=1’b0;

if(txbuf_rdy)

trans_st <=2;

end

2:begin

tx_wren <=1’b1;

tx_ctrl <=1’b1;

tx_data <=tx_len;

trans_st <=3;

end

3:begin

tx_wren <=1’b0;

tx_ctrl <=1’b0;

if(tx_len==0)

trans_st <=4;

else if(txbuf_rdy) begin

tx_data <=count;

count <=count+1;

tx_wren <=1’b1;

tx_len <=tx_len-1;

end

end

4:begin

tx_wren <=1’b0;

tx_ctrl <=1’b0;

tx_data <=0;

tx_len <=16;

tx_done <=1’b1;

trans_st <=5;

end

5:begin

tx_done <=1’b0;

trans_st <=1;

end

endcase

wire [7:0] rx_byte;

wire rx_byte_rdy;

reg [7:0] rx_byte_r;

reg rx_rden;

always@(posedge sys_clk)

if(rx_byte_rdy)begin

rx_rden <=1’b1;

rx_byte_r<=rx_byte;

end

else begin

rx_rden<=1’b0;

end

 

uart_top uart_top_dut

(

.inclk (inclk),

.rst (rst),

.baud_sel (baud_sel),

.tx_wren (tx_wren),

.tx_ctrl (tx_ctrl),

.tx_data (tx_data),

.tx_done (tx_done),

.txbuf_rdy (txbuf_rdy),

.rx_rden (rx_rden),

.rx_byte (rx_byte),

.rx_byte_rdy(rx_byte_rdy),

.sys_clk (sys_clk),

.sys_rst (sys_rst),

.rx_in (rx_in),

.tx_out (tx_out)

);

 

endmodule

Set this file to be top level entity and instantiate the previous program. Download the program to the board and verify it.

Fifthly, lock the pins and test.

Signal Name Port Description Network Label FPGA Pin
Inclk Clock input C10_50MCLK 91
rst Reset signal KEY2 10
rx_in Serial input data TAG_RXD_I 144
tx_out Serial output data TAG_TXD_O 143

Observe the data received by PC. See Fig 10. 5

Use SignalTap II to observe the data received by FPGA.

Fig 10. 5 Data sent displayed on the host computer

Sixthly, the receiving part has been eliminated here. You are encouraged to try it on your own.

 

Related posts