User Tools


This is an old revision of the document!


UART Receiver

In this laboratory you will create an asynchronous serial receiver that will allow you to receive characters from your computer and onto the NEXYS4 board. Your design will closely follow last week's serial transmitter. That is, you will have handshaking with the receiver (but the signals are called Receive and Received). And, the receiver has similar components - a state machine, a bit counter, and a timer. A number of the details are different but it will have a similar organization.

Learning Outcomes

  • Implement an asynchronous receiver
  • Strengthen behavioral SystemVerilog skills

Preliminary

A class lecture was given discussing how the receiver should work. That and the textbook section on the receiver will form the basis for the lab. However, you will note that far less of the design is provided to you this week.

In this lab we will operate the receiver at a baud rate of 19,200.

Using a 100 MHz clock, how many clock cycles does it take to reach the middle of the bit period using this baud rate? (see Figure 28.15)

Exercises

Exercise #1 - Asynchronous Receiver Module

Begin your laboratory assignment by creating a receiver module that has the following parameters and ports:

Module Name = rx
Port Name Direction Width Function
clk Input 1 100 MHz System Clock
Reset Input 1 The system reset signal
Sin Input 1 Receiver serial input signal
Receive Output 1 Indicates that the receiver now has a byte it is asking to hand off on the Dout pins
Received Input 1 Indicates that the other circuitry has accepted the received byte on the Dout pins. Receive and Received serve as Req and Ack from Figure 28.7. However, the requestor who raises Receive is your rx module and the acknowledger who raises the Received signal is the testbench or other outside agent.
Dout Output 8 8-bit data received by the receiver which is then output on pins
parityErr Output 1 Indicates that there was a parity error on the last transaction.

Next, complete the full design of the receiver. See the textbook for more information. You will need:

  • Baud timer
  • Bit counter
  • Shift register - the purpose of this is to collect the serially received bits as they come in. It is recommended that you shift in all 8 data bits and the parity bit into the shift register. But, you will only output the 8 data bits on the Dout pins.
  • Error Checker - once you have shifted all 9 bits into the shift register, you should check that the parity bit is correct (odd parity). If this is not true, you should raise the parityErr signal. This can be a combinational logic signal which is always reflecting the contents of the shift register. It will thus transition as things are shifted into the shift register and will only be an accurate error signal once you have shifted in the last bit (the stop bit). That is OK - the circuit that checks this will only look at the parityErr signal once your receiver has raised the Receive output to say it has received a byte.
  • Finite State Machine - you get to design this yourself from scratch. However, we suggest you pattern it somewhat after the transmitter state machine. Note that you have to have your timer get you over into the middle of each bit period and so your timer may have additional output signals. And, your state machine will need to be designed to control when the shift register shifts so that you collect the 8 data bits and parity bits. Finally, your state machine will need to handshake using hte Receive and Received signals at the end of each byte reception. You may safely assume that a new byte will not start to arrive on the Sin signal before the Receive/Received handshake has completed. You can simulate that way and that will surely be the case when you hook everything up in hardware.

Exercise #2 - Simulation

After creating your rx module create a simple TCL file and simulate your module to make sure that there are no major errors. Then simulate your module with the following testbench file:

tb_rx.v

Provide a copy of the console output from the testbench simulation in your lab report

Include your 'rx' SystemVerilog module in your report

Exercise #3 - Top-Level Circuit

After simulating your receiver module and verifying it operates, begin a new top-level module with the following ports:

Module Name = uart_top
Port Name Direction Width Function
clk Input 1 100 MHz System Clock
sw Input 8 Slide switches to specify character to send
btnc Input 1 Send character control signal
rx_in Input 1 Receive signal
tx_out Output 1 Transmit signal
segment Output 8 Cathode signals for seven segment display
anode Output 8 Anode signals for each of the eight digits
rx_error Output 1 RX transfer error
tx_debug Output 1 TX Debug signal
rx_debug Output 1 RX Debug signal

In this exercise you will instance both your tx and rx modules. Begin by instancing your tx module just like the previous lab and make the following connections to your tx module:

  • Connect the tx_out output of your tx module to your top-level tx_out output
  • Connect the tx_out output of your tx module to the top_level tx_debug output
  • Assign the value '0' to the “odd” parity input (for even parity)
  • Connect an unused signal to the 'busy' signal of your tx module (busy will not be used in this circuit)
  • Connect the 8 switches to the 'din' input of your tx module
  • Connect the top-level clock to the clk input of your tx module
  • Drive the tx “send” signal with the same circuit you used in the top-level of your previous lab (attach to btnc, use a synchronizer and debouncer).

After instancing your tx circuit, instance your rx circuit and make the following connections to your rx module:

  • Connect the rx_in input of your top-level rx_in to the rx_input of your receiver module
  • Connect the rx_in input to rx_debug
  • Connect the top-level clock to the clk input of your rx module
  • Assign the value of '0' to the “odd” parity input (for even parity)
  • Connect an unused signal to the 'busy' signal of the rx module (busy will not be used in this circuit)
  • Connect an unused signal to the data_strobe signal of the rx module (it was important for the testbench but will not be used in the top-level module)
  • Create a signal named “rx_data” and attach it to the dout port
  • Attach the top-level rx_error output port to the error port of your rx module. This should be attached to LED[0] on the board.

Instance your seven segment display controller and connect the inputs to your controller as follows:

  • Attach the 8 switches to the lower 8-bits of the data in of the seven-segment controller (bottom two digits)
  • Attach the 8-bit signal “rx_data” to bits 23-16 of the data going to the seven segment controller (digits 5 and 4)
  • Only display the bottom two digits and digits 5 and 4 of the seven segment display
  • Do not use any of the digit points
  • Attach the anode and segment signals of the controller to the top-level outputs of the top-level module

Include a copy of your top-level module in your laboratory report

Exercise #4 - Implementation

Before synthesizing your design, you will need to create an .xdc file that contains the pin locations of each port in your design. Most of the pins used in this design are the same as pins used in previous designs (buttons, switches, seven-segment display, etc.). However, you will be using a new FPGA pin to connect to the UART/USB transceiver and the debug port.

The following example code demonstrates how these I/O pins can be attached to your top-level FPGA pins:

set_property -dict { PACKAGE_PIN C4    IOSTANDARD LVCMOS33 } [get_ports { rx_in }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in
set_property -dict { PACKAGE_PIN D4    IOSTANDARD LVCMOS33 } [get_ports { tx_out }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out
set_property -dict { PACKAGE_PIN C17   IOSTANDARD LVCMOS33 } [get_ports { tx_debug }]; #IO_L20N_T3_A19_15 Sch=ja[1]
set_property -dict { PACKAGE_PIN D18   IOSTANDARD LVCMOS33 } [get_ports { rx_debug }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2]

Also, add an entry in your .xdc file for the led[0] which signals a receiver error. After completing your .xdc file, proceed with the synthesis of your design.

Provide a summary of your synthesis warnings.

After successfully synthesizing your design, proceed with the implementation and bitstream generation of your design. Indicate the number of Look-up Tables (LUT) and Input/Output (I/O) pins for your design.

Exercise #5 - Download and Putty

Once the bitstream has been generated, download your bitstream to the FPGA and test both your transmitter and receiver. Follow the PuTTY tutorial to set it up. Once you have Putty setup properly, type characters on the computer keyboard while in the Putty window and check to see what HEX values show up on your NEXYS 4's seven segment display.

Personal Exploration

Here are some ideas for personal exploration in this laboratory:

  • Experiment with different baud rates and see if you can communicate with the PC at a different baud rate.
  • Send a variety of interesting characters over the terminal and see how they respond.
  • Hook up the tx debug signal to the oscilliscope and view the transfer of an 8-bit character.

Describe your personal exploration activities

Pass Off

To pass off this laboratory, demonstrate to the TA the following:

  • Your testbench passing with 0 errors
  • Your working top-level uart transmitter/receiver circuit

How many hours did you work on the lab?

Please provide any suggestions for improving this lab in the future.

TA Notes and Feedback