6.111 Lab #5 - IMU


Goal: Design a digital bubble level using data from an inertial measurement unit (IMU) and display the results on a monitor. When the IMU is lying flat on a surface parallel to the ground, the bubble will be centered in the circle. (This lab was inspired by the Virtual Softball project by Katie Shade and Melinda Szabo F2017.) This lab provides you with a design methodology that will be useful in your final project.

Figure 1

Useful links

Checkoff List

Please have the following available during checkoff:

Be able to respond to any of the following questions (and possibly others).

[Checkoff: 4 points, 5 points with added features - see end]

  • After checkoff, please upload your Verilog file using the "Submit Verilog" page on the course website. Your Verilog should include readable code with comments and consistent indenting, correct use of blocking and non-blocking assignments, use of "default" in case statements, use of parameter statements for symbolic name and constants. There should be no long nested if statements.

    Digital Bubble Level

    In this lab you will implement a digital bubble level using serial data from an MPU-9250 IMU. The MPU-9250 is a multi-chip module consisting of a 3-Axis gyroscope, the 3-Axis accelerometer and 3-Axis magnetometer. For this lab we will use only the accelerometer data for x,y axis. [Note: the Nexys4 includes Analog Device ADXL362 accelerometer with a SPI interface. However, the experience of attaching and using peripherals devices may come in handy during the project phase.] The accelerometer measures acceleration forces in three axes. These forces may be static such as gravity or dynamic such as motion or vibration. A common application is display rotation when smart phone display is rotated.

    IMU data for all three axes is sent via I 2 C bus with clock (SCL) and data (SDA) lines to a Teensy, then packetized and transmitted by an universal asynchronous receiver-transmitter (UART) to an I/O pin at 9600 baud. (See Lab 2 for a refresher on serial data. In Lab 2, a transmitter was implemented. For this lab the goal is to a design receiver.)

    The data is 6 bytes (16 bits for each axis) for x,y,z data respectively with the least significant bit of the least significant byte first. The data for each axis is in 2's complement format.

    The x,y coordiates are then used as inputs to move a circle with 0,0 the center of screen.

    [The more than you want to know section ...] Endianness refers to the ordering of the bytes.With big endian, the most significant byte is sent first. Endianness can also refers to the bit level. RS-232 (lab2), USB and Ethernet uses little endian at the bit level, least significant bit first. (Think of a shift register where the bits are shifting in left to right.) Other protocols such as I2C and SPI(sometimes) is little endian at the bit level. For this lab, the data sent on the I2 bus is big endian (msb first) but bit banged [converted] to little endian to comply with the RS-232 protocol. To be safe, always check the datasheet for bit and byte ordering.


    1. Get a set of parts from a staff member. Please store the material in your locker between lab sessions.

    2. Read through the lab to understand the desired functionality, determine your approach and complete a design. Although not required, you may find it helpful to schedule a conference with a member of the course staff to review your design.

    3. Wire up a protoboard with the IMU and Teensy (programmed) as shown:

      It is general practice to use black wire for ground and red wire for Vcc. There are colored wires near the center columns of the lab.

      Make a quick check to verify everything is working correctly by attaching a spare USB cable (available at the TA station) to Teensy and any computer. The board, if wired correctly, will act as a tilt sensitive mouse.

    4. Remove the USB cable from the Teensy. Turn off the Nexys4 by sliding the power switch on the Nexys4 to the off position, move the blue jumper right two pins and attach two 50cm female to female cable as show. The modification supplies +5V to the Teensy and the Nexys4.

    5. Attached the protoboard to the FPGA as shown. There are headers for the female connector and 50cm male-to-male cables available. Nothing should be attached to the +3.3V on the PMOD-JB. +5V should be attached to the two terminals near the FPGA power switch. Turn the Nexys4 on.

    6. Attach a scope to the transmit data (TX) sent to the FGPA. Here is a sreenshot of 4 sets of 6 byte data.

      Data is sampled at 100 Hz and sent at 9600 baud (104us for each data bit) with approximately a 4ms interval betweent sets. The bits are as follows:

      start bit (1 bit)
      byte 1 (8 bits)
      stop bit (1 bit)
      start bit (1 bit)
      byte 2 (8 bits)
      stop bit (1 bit)
      start bit (1 bit)
      byte 3 (8 bits)
      stop bit (1 bit)
      start bit (1 bit)
      byte 4 (8 bits)
      stop bit (1 bit)
      start bit (1 bit)
      byte 5 (8 bits)
      stop bit (1 bit)
      start bit (1 bit)
      byte 6 (8 bits)
      stop bit (1 bit)

      From the wavefrom, you'll see 59 data bits between the first falling edge and the last rising edge of data. The 60th bit is a stop bit, the same value as idle.

    Implementation Suggestions

    Clocks and Synchronizer
    For most digital systems, only one clock domain should be used. In this design, it's clock_65mhz,. To avoid crossing clock domains, other clocks used in the system such as the sampling clock should be created by using clock_65mhz and creating enable signals. (Review the discussion on clocks in lecture 7.)

    Your clocked state machine has an asynchronous input, potentially creating a problem with metastability in the state registers if the input changes too near a rising clock edge. In general asynchronous inputs need to be synchronized to the internal clock before they can be used by the internal logic. synchronize.v (included in the labkit_lab5c.v) is a Verilog implementation of a pulse synchronizer that can convert an asynchronous signal to a synchronous one with acceptably low probability of metastability in the synchronous signal.

    The labkit template module does not have a reset signal. It may be useful to implement a reset signal using a button/switch input. Be sure to debounce the signal.

    Sampling and display
    In a previous lab, a UART transmitter was implemented. In this lab, the receiving end, a UART receiver is implemented. Receiving data is more complicated than sending data. In viewing the waveform it is tempting to use the falling edge as a clock input. This is poor design since any noise will initiate the process. A better approach is to oversample, e.g., at 16x or faster rate.

    Since the incoming signal is asynchronous, sampling at 16x is needed at receiving to ensure that the input data stream is correctly sampled with respect to the falling edge of the start bit. This was not necessary when transmitting but is crucial when receiving.

    Look for 1 → 0 transition for the beginning of start bit. If sampling at 16x, the middle of the start bit should be 8 sampling clocks from the falling edge. Each subsequenty data bit can then be sampled every 16 sampling clocks. Check format (start, data, parity, stop bits) before accepting data.

    At 9600 baud, each bit is 104us. Check and see that the data line is high for at least 2ms before looking for the first start bit. This will ensue that the FSM does not start in the middle of a data stream. When the start bit is detected, begin capturing the data bits.

    One approach, thinking as a programmer is to store each byte as the bits arrive. This requires keeping track of the number of bits arriving and storing the data appropriately. A top MIT engineer would treat the incoming data as a 60 bit data stream, shift 60 bits in, pull the x, y values from the 60 bits and store the x, y values in 16 bit registers. [When solving a problem, consider alternative designs - look for an elegant or simplier solution.]

    Display the x, y accleration using 4 digits for each axis - converting from 2's complement to plus/minus format. For each axis, use the most significant 13 bits. Since the hex display cannot display a minus sign, display a "F" insstead. The value 1 [0_0000_0000_0001] will display 0001. The value -1 [1_1111_1111_1111] display as F001.

    Use SW[15] for calibration. With board lying flat and SW[15]=0, the display shows the actual x,y accelerator values. With SW[15]=1, an offset to x,y is added so the hex display shows 0,0 and the circle is centered at the cross hairs. Using the calibrated values, SW[15]=1, offset the bubble appropriately. To demonstrate that calibration is working correctly, tilt the IMU and calibrate that orientation as "flat".

    Create a 64 pixel diameter circle (bubble). Drawing a circle is similar to drawing a rectangular blob except it uses the circle equation x 2 + y 2 ≤ r 2 to determine the color of the pixel. Depending on speed of the multipliers, pipelining may be necessary in generating a circle. Use the x,y values to move the center of the circle with 0,0 at the cross hairs. Now draw a ring surrounding the circle to create the display shown in figure 1.

    Physical vibration and electrical noise will cause the bubble to jump with no apparent motion. A simple approach is to use just the high order bits at the expense of losing resolution. Other approaches include adding some filtering by using a circular buffer and creating a running average of the most recent samples, limiting the maximum change between samples or a low pass filter. There are other approaches.

    Check off

    Display cross hairs with bubble[4 points]. Be able to demonstrate all of the following:

    1. As the IMU (level) is tilted, the bubble moves correspondingly in x,y. The cross should be visible through the circle.
    2. When the level is calibrated (SW[15]=1), regardless of the initial tilt, the bubble is centered in the cross hair and moves accordingly as the level is moved.
    3. Demonstrate and describe the noise filtering (more than just using the high order bits).

    Earn an additional point by:

    1. displaying the x,y values on the screen or
    2. displaying the x,y values on the hex display in decimal.
    3. modifying the hex display to show 16 bit twos complement number in plus/minus (3 digits) format.

    Want a challenge and earn an extra 3 points above the 5 points? Modify your design to use the onboard Analog Device ADXL362 accelerometer on the Nexys4.


    The labkit_lab5c.v template top-level file and others files can be downloaded from the links at the beginning of this document.

    Compile and load the project to the Nexys4. SW[1] will toggle between color bars and cross hairs display. The graphics are 1024x768 with a 65Mhz clock. (If white borders are not aligned, press the auto-adjust button next to the Power button on the display.) You are free to modify the display in any manner in completing the lab. Note: the Nexys4 has 12 bit VGA compared to 24 bit for the labkit. Design accordingly.

    It's good design practice to use one clock domain - so use 65Mhz as your system clock. The Verilog files allow a user to utilize some of the Nexys 4 features including buttons, switches, LEDs, user input/output pins, VGA output, etc.

    You will need to instantiate all submodules in this top level file as well as create wires to connect the submodules.

    In addition, you will need to connect the input that you use to the appropriate submodules. There are Verilog statements in labkit_lab5c.v that set default values for outputs: the LEDs, 7 segment... You'll need to replace those statements with your own logic.


    Inevitably your design won't be 100% correct the first time. Debugging by just observing the hex display may not be of any use - you'll need more info to figure out what's happening. Start by building a test-jig for each module of your design and then run simulation to verify the expected behavior of the system on several sequences of inputs. This will eliminate many of the problems. To wring the tricky problems use the integrate logic analzer (ILA). The display will give you real time debugging information.