uart_loopback

<!DOCTYPE html> <html>

<head> <meta charset="utf-8">

<script async src="https://www.googletagmanager.com/gtag/js?id=G-NG21EXTML9"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());

gtag('config', 'G-NG21EXTML9'); </script> <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> <title>SpeakHDL</title> <meta name="keywords" content="FPGA, FPGA Prototyping, FPGA Tool, Voice Coding, procedural programming, FPGA Easy, VHDL, FPGA for beginners"> <meta name="description" content="A practical FPGA design tool that combines procedural programming using native VHDL with command-based programming"> <link rel="icon" type="image/png" sizes="16x16" href="../assets/img/logo/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="32x32" href="../assets/img/logo/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="192x192" href="../assets/img/logo/android-chrome-192x192.png"> <link rel="icon" type="image/png" sizes="512x512" href="../assets/img/logo/android-chrome-512x512.png"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css"> <link rel="stylesheet" href="https://unpkg.com/@bootstrapstudio/bootstrap-better-nav/dist/bootstrap-better-nav.min.css"> <link rel="stylesheet" href="../assets/css/doxy-override.css"> <link rel="stylesheet" href="../assets/css/Footer-Basic.css"> <link rel="stylesheet" href="../assets/css/Login-Form-Clean.css"> <link rel="stylesheet" href="../assets/css/banner.css"> <link rel="stylesheet" href="../assets/css/examples.css"> <link rel="stylesheet" href="../assets/css/speakhdl-styles.css"> </head>

<body> <section> <header class="justify-content-center banner-header theme-outline" dx-block="block">

UART Loopback

</header>

Design Objective(s):

  • Design both a UART receiver and transmitter capable of looping back 8 bits of data to a PC at a 9600 baud rate by using a state machine.
  • Use a shared register to pass a byte of data and a control signal between the receiver and transmitter.
Uart Receiver Command Sequence
Show Hotkey Command Sequence
Uart Transmitter Command Sequence
Show Hotkey Command Sequence

Top Level Design Structure

Design Discussion

Although there are no prescribed rules on how to create a finite state machine with a data path, one systematic approach is to first create the states along with the conditional transitions and timed transitions that reveal the control path, then go back through the state machine to add the procedure calls that implement the data path.
For the control path, the CONDITIONAL_TRANSITION procedure call is used to suspend the state machine in a state until a boolean condition becomes true and the TRANSITION procedure call is used to create timed transitions that occur after a specified period of time. In the case of the UART receiver, the state machine is suspended in st_init until the input signal, rxd, becomes logic '0' then transitions to st_start and waits for a time period of 52us which is equal to half of a baud interval. From there, the state machine enters st_shift for enough time to allow 8 bits to be shifted, then transitions to the st_done for one baud interval before returning to st_init. The UART transmitter follows the same state logic except the transmitter state machine is initially suspended in st_init until the byte_ready signal is asserted to logic '1', then transitions to st_start for a time interval of 104us which is equal to a whole baud interval. The final two states of the UART transmitter is identical to the final two states of the UART receiver.
For the data path,  the UART receiver inputs serial data on pin C4 and utilizes a left shifter to assemble 8 bits of data. Once assembled, the receive module places the byte of data onto a shared register and asserts a an additional bit on the shared register to notify the transmitter module that a byte of data is available.  The UART transmitter takes that byte of data, reverses the bits, then uses a right shifter to shift the 8 bits of data out of pin D4, thus completing the loopback.
<section>

Entry Into Editor

Open the IO_CONFIG.cfg file in the editor and update the following parameters to match the user specific the development board. Then return to the .vhd file and give the 'ok' command.
  • [global]
  • clk_pin = E3
  • reset_pin = U9
  • sys_clk_freq = 100E6
  • reset_polarity = '1'
  • ...

</section> <section>

Hotkey Commands (UART RX)

Select a local directory location for output files *
  1. restart
  2. rename uart_rx.vhd
declare known inputs
  1. input rxd = C4
declare timing constants
  1. half_baud_rate is 52us
create a state machine and name the states
  1. sm
  2. name = init, start, shift, done
complete first pass at state machine and complete control logic
  1. ct
  2. when rxd = 0
  3. n
  4. tr
  5. divide half_baud_rate
  6. n
  7. tr
  8. divide baud_rate
  9. count 8
  10. n
  11. tr
  12. divide baud_rate
  13. goto 0
cleanup unused states and return to state 0
  1. cleanup
second pass at state machine should reveal data flow logic
  1. sr
  2. index uart_tx
  3. data shift_left7:
  4. st shift
  5. sdl
  6. data rxd
  7. shift 1
  8. enable divide_done
  9. ok
drive output signals
use a counter with boolean enable to create strobe signal
  1. cc
  2. count 1
  3. enable last_state = st_done
  1. sr
  2. index uart_tx
  3. data counter0.done
  4. offset 8 
run parser
  1. ok

</section> <section>

Hotkey Commands (UART TX)

create a new application module named 'uart_tx'
  1. new uart_tx.vhd
declare timing constants 
  1. baud_rate is 104us
declare known aliases
  1. byte_ready is shared_register(8)
create read only shared register
  1. sr
create state machine and name states
  1. sm0
  2. name = init, start, shift, stop
complete first pass at state machine and complete control logic
  1. ct
  2. when byte_ready = 1
  3. n
  4. tr
  5. divide baud_rate
  6. n
  7. tr
  8. divide baud_rate
  9. count 8
  10. n
  11. tr
  12. divide baud_rate
  13. goto 0
cleanup unused states and return to state 0
  1. cleanup
second pass at state machine should reveal data flow logic
  1. sdr
  2. data shared_register7:
  3. reverse_bits
  4. st shift
  5. sdr
  6. data shared_register7:
  7. shift 1
  8. enable divide_done
drive output signals
  1. txd;
assign pinout with pin command
  1. pin = D4
  2. 0 when st_start
  3. shift_right(0) when st_shift
  4. else 1
run parser
  1. ok
Pin locations must be changed for user specific development board
  Writing to a local directory is supported with Chrome and Microsoft Edge browsers

</section>

</section> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script> <script src="../assets/js/bss_custom_js.js"></script> <script src="https://unpkg.com/@bootstrapstudio/bootstrap-better-nav/dist/bootstrap-better-nav.min.js"></script> </body>

</html>