User Tools


UART Receiver

Here is the link to the lab intro video: https://expl.ai/UUUZMXZ.

In this laboratory you will create and simulate the receiver part of a UART. Your design will closely follow last week's serial transmitter. That is, you will have handshaking with a host (but the signals are called Receive and Received). And, the receiver has similar components - a state machine, a bit counter, and a timer.

Learning Outcomes

  • Implement an asynchronous receiver
  • Strengthen behavioral SystemVerilog skills

Preliminary

What was discussed in class lecture, along with the textbook section on UART receivers 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 and will use odd parity.

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 byte reception.

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

  • Baud timer
  • Bit counter
  • Shift register
  • Parity checker

Baud Timer

This is very similar to your timer from last time except it needs to be able to tell you when a whole bit time has passed as well as when a half bit time has passed. Both are needed at some point in your state machine's operation. One way to implement this is to simply add a second output to the timer to signify when it has reached its half-count. It need not roll over when it reaches its half-count - it can simply raise this second output and keep counting until it reaches the full termination count.

Shift Register

The purpose of this is to collect the serially received bits as they come in. It is recommended that you shift all 8 data bits plus the parity bit into the shift register. But, you will only output the 8 data bits on the Dout pins.

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

The parityErr signal can be a combinational logic signal which is constantly 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 9th bit (the parity bit). That is OK - the circuit that checks this will only look at the parityErr signal when Receive == 1.

You need to think carefully - given the order that bits arrive - do you want the register to shift right or shift left? The textbook explicitly states which bit is transmitted first. Given that, should you feed the bits in from the left of the shift register and right shift each time or the other way around? All you care about is that when you are done that you can assign the bits to Dout for output.

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 the Receive and Received signals at the end of each byte reception. You may assume that a new byte will not start to arrive on the Sin signal before the Receive/Received handshake has completed.

What about the timing of the parityErr signal? When a parity error occurs, raise the parityErr signal while the Receive signal is being raised and lower it when the Receive signal is lowered.

Exercise 1 Pass-off: Using Zoom, discuss with a TA the state graph of your state machine.

Exercise #2 - Simulation

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

tb_rx.sv

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

Include the SystemVerilog code for your receiver module in your report

Exercise 2 Pass-off: Show a TA your tcl script and your testbench output. Attach a copy of your Tcl file and a screenshot of your working simulation to Learning Suite.

Exercise #3 - Loop-Back Simulation Test

In this exercise you are going to simulate a transmitter/receiver pair as shown in the figure below.

Here, there is a transmitter (with its host) located in Boston that is going to transmit bytes to a receiver (with its host) located in San Francisco. But, to mimic that you are going to put your transmitter from Lab 10 and your receiver from Lab 11 into the same top module.

Your Tcl file will act as both the Boston host and the San Francisco host. That is, it will handshake with the transmitter to send a byte like in Lab 10. But, that byte will be transmitted to your receiver which will then receive it like in this lab and so your Tcl file will also have do handhshaking with the receiver to acknowledge that.

The actual serial data transmission, rather than actually traveling from Boston to San Franciso will travel a few nanometers on a wire inside the FPGA from the transmitter's output to the receiver's input.

Make 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
reset Input 1 Reset signal
txData Input 8 Data to be transmitted
Send Input 1 Transmit handshake: send character command signal
Sent Output 1 Transmit handshake: acknowledge character has been sent
Receive Output 1 Receive handshake: character has been received by UART
rxData Output 8 Data that was received by receiver
Received Input 1 Receive handshake: host acknowledge receipt of character
parityErr Output 1 Parity error signal
serData Output 1 The serial signal between xmit and rcv blocks. You are bringing it out as an output so you can easily see it in simulation.

Note that you are NOT going to map these I/O signals to board-level switches and led's. You are simply going to simulate this top level module.

Inside this module, instance both your tx and rx modules. Then, connect the serial out data signal of the transmitter to the serial in data signal of the receiver. This is called a “loop back” and allows you to test your transmitter and receiver together - whatever the transmitter sends serially will be received by the receiver and presented back to the host as an 8-bit received data word.

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

Now, write a Tcl file and do the simulation of your complete circuit. A complete transmission consists of applying txData and the Send signal and waiting for a Sent signal to be returned and then lowering the Send signal. That handles the transmit handshaking.

But, there will also be receive handshaking once the byte has been received by the receiver. That is, once a byte has been received your receiver will raise the Receive signal. Your Tcl file can then respond by raising the Received signal, waiting until the Receive signal has been lowered, and then lowering the Received signal.

Your simulation should show that whatever byte was requested to be transmitted by your transmitter is what was received by your receiver.

Exercise 3 Pass-off: Show a TA your top level module and explain how we will know when the rx module has received a byte.

Attach your Tcl file to Learning Suite.

Attach a screenshot showing the complete handshaking and transmission of the character 'Y'.

Attach a screenshot showing the complete handshaking and transmission of the character 'Y' but with bad parity. For this you will need to purposely break your transmitter to send the wrong parity so you can demonstrate how your receiver raises the parityErr as a part of the handshaking.