Introduction: How to Make Ernie

This is a tutorial on how to build Ernie, your autonomous sound following robot, using a Zybo Board. It will cover how to: create a project in Vivado, create PWM-like servo motor drivers in the the FPGA, interface with two sound sensors, create a time difference of arrival IP, use freeRTOS, and run the zybo off a battery pack. This was our final project for a Real Time Operating Systems class (CPE 439) at Cal Poly SLO.

Equipment list:

  • 1 - ZYBO Zynq 7000 Development Board
  • 2 - Parallax Continuous Rotation Servo
  • 2 - Sound Sensor (SparkFun Sound Detector)
  • 1 - 5v Lithium Ion USB battery pack (for board)
  • 4 - AA batteries (for servos)
  • 1 - AA battery pack (w/ 4 battery slots)
  • 1 - Micro USB cable
  • 1 - Breadboard
  • many - Male to Male Wires
  • 1 - Servo chassis

Software requirements:

  • Xilinx Vivado Design Suite 2016.2
  • Digilent Adept 2.16.1

Step 1: Setting Up a Project in Vivado for Ernie

  1. A wizard will pop up
  2. Click Next
  3. Next name the project
    1. Never use a project name or directory path that has spaces in it!!!!!
    2. This will be an RTL project.
  4. We do not want to specify sources
  5. Clicking Next, we get to the Part page. We are using a ZYNQ XC7Z010-1CLG400C.
    1. Vivado doesn’t have the Zybo listed as one of it’s pre-defined boards. Select: “parts” then search for xc7z010clg400-1.
    2. If you choose the wrong part by mistake you can easily switch chips: Tools -> Project Settings -> General and click the dots to the right of “Project Device”
  6. Click Create Block Design.
    1. Name it design_1 for now
  7. You will see a green bar that says Add IP, click it.
  8. Search for Zynq.
    1. Double click ZYNQ7 Processing System,
    2. This block will appear in our block design.
  9. You will see a green bar that says Run Block Automation, click it.
  10. Download zybo_zynq_def.xml below.
  11. In Vivado, click “Import XPS Settings” and select “zybo_zynq_def.xml”
    1. This pre populates the Vivado block configuration with all of Zybo board’s built-in peripherals and pin assignments.
  12. Double click on the ZYNQ block.
    1. MIO Configuration
      1. Enable Timer 0 (under Application Processor Unit - img 1)
      2. Enable Watchdog (under Application Processor Unit- img 1)
      3. Enable GPIO->GPIO MIO (under Application Processor Unit - img 2)
      4. Enable GPIO->ENET Reset (under I/O Peripherals- img 2)
    2. Clock Configuration
      1. Disable FCLK0 (under PL Fabric Clocks - img 3)
  13. Click Ok.
  14. “Run Block Automation” now.
    1. There will be some questions about signals, say OK
  15. Click “Generate HDL Wrapper”.
    1. We will want to copy the generated wrapper to allow user edits.
  16. Click OK.

Step 2: Creating Ernie's PWM in Vivado

This step will generate a PWM IP with inputs sent via the AXI library.

  1. Create AXI GPIO block by right-clicking the background, and clicking "add IP"
    1. type "AXI_GPIO" into the search bar, and select this package
  2. Re-customize IP by double-clicking the new axi_gpio_0 block
    1. under GPIO, set GPIO width to 2. These bits will be the PWM_ON signal to drive each PWM module instance.
    2. click "enable dual channel"
    3. under GPIO 2, set GPIO width to 2. These bits will be the PWM_FW signal to set the direction of each PWM module instance.
  3. Right click on the axi_gpio_0 output port labeled GPIO, and select "Make External"
    1. Click on the new output labeled GPIO, and navigate to the "properties" tab on the left toolbar, and change the name to PWM_ON
    2. Click on the new output labeled GPIO2, and navigate to the "properties" tab on the left toolbar, and change the name to PWM_FW
  4. Select Run Connection Automation in the green banner above the block diagram.
    1. If you manually connect the ports, AXI addresses may not be configured, leading to communication issues later on
  5. In the Flow Navigator Pane, select project manager -> Add Sources to create a new custom IP block
    1. choose "add or create design sources", and hit next
    2. click "create file", change file type to "SystemVerilog", and type "pwm" into the file name field, then click OK
    3. click Finish
    4. ignore the Define Module window by pressing OK (we will overwrite these later)
      1. if it asks if you're sure, click Yes
  6. In the sources tab, double-click the pwm.sv (located in "Design Sources/design_1_wrapper")
    1. Copy/paste the entire SystemVerilog code from the pwm.txt file attached below

Attachments

Step 3: Creating Ernie's TDOA in Vivado

This step will generate a TDOA IP whose output can be read via the AXI library

  1. Create AXI GPIO block by right-clicking the background, and clicking "add IP"
    1. type "AXI_GPIO" into the search bar, and select this package
  2. Re-customize IP by double-clicking the new axi_gpio_1 block
    1. under GPIO, check the "All Inputs" box, and set GPIO width to 32. This bus will be the time difference of arrival between the two sensors.
    2. inside the axi_gpio_1 block, click the + next to the GPIO port to reveal gpio_io_i[31:0].
  3. Right click on the axi_gpio_1 output port labeled gpio_io_i[31:0], and select "Make External"
    1. Click on the new input labeled gpio_io_i[31:0], and navigate to the "properties" tab on the left toolbar, and change the name to TDOA_val
  4. Select Run Connection Automation in the green banner above the block diagram.
    1. If you manually connect the ports, AXI addresses may not be configured, leading to communication issues later on
  5. In the Flow Navigator Pane, select project manager -> Add Sources to create a new custom IP block
    1. choose "add or create design sources", and hit next
    2. click "create file", change file type to "SystemVerilog", and type "tdoa" into the file name field, then click OK
    3. click Finish
    4. ignore the Define Module window by pressing OK (we will overwrite these later)
      1. if it asks if you're sure, click Yes
  6. In the sources tab, double-click the tdoa.sv (located in "Design Sources/design_1_wrapper")
    1. Copy/paste the entire SystemVerilog code from the tdoa.txt file attached below

Attachments

Step 4: Wrapping and Exporting Ernie

  1. Verify that the block diagram looks like the screenshot attached
  2. In the sources tab, right-click design_1.bd and select "Create HDL Wrapper..."
    1. Select "Copy generated output to allow user edits", then press "OK"
    2. Copy the code from design_1_wrapper.txt attached below, and paste it in place of the generated design_1_wrapper.v code
    3. save design_1_wrapper.v
  3. In the sources tab, double-click the ZYBO_Master.xdc file under Constraints/constrs1
    1. Copy the code from ZYBO_Master.txt attached below, and paste it in place of the existing ZYBO_Master.xdc code
    2. Note the following input/output pins:
      1. L15: PWM signal for the left motor (Pmod JA2 on the Zybo)
      2. L14: PWM signal for the right motor (Pmod JA8 on the Zybo)
      3. V12: gate input from sound sensor 1 (Pmod JE1 on the Zybo)
      4. K16: gate input from sound sensor 2 (Pmod JE2 on the Zybo)
  4. In the Flow Navigator Pane, Click "Generate Bitstream" under Program and Debug
    1. if you think it's done right away, it's probably not. seriously, make some tea
  5. Click File->Export->Generate Hardware
    1. Check "Include Bitstream" and hit OK
  6. Click File-> Launch SDK

Step 5: Building Ernie

  1. Mount the servos to the servo chassis.
  2. Following the datasheet for the servos, do the following:
    1. connect the ground of the servos to ground pins on the Zybo's JA Pmod (see attached pinout image)
    2. connect the power pin of the servos to the AA battery pack
      1. We found that when the servos are connected to the Zybo's Vdd, the board draws too much current, causing the board to continuously reset.
    3. connect the input signal pins to the Zybo's appropriate output pins (left: JA2, right: JA8)
  3. mount the sound sensors to the front of the chassis, facing forward, keeping them as close together as possible
  4. use the sound sensor's hookup guide to integrate the sound sensors
    1. wire the ground and Vdd pins of each sound sensor to the ground and Vdd pins on the Zybo's JE Pmod (see attached pinout image)
    2. wire the left sound sensor's Gate pin to JE1
    3. wire the right sound sensor's Gate pin to JE2

Step 6: Ernie's First BSP

  1. Create a BSP to wrap up the platform we just created.
    1. You can get this through File -> New -> Board Support Package.
  2. A wizard will pop up to help you create the BSP.
    1. We want to tie this BSP with our Platform that we just created, so
    2. Hardware Platform should line up with the one we just created (see img 1)
    3. Our CPU will be the _0 CPU.
    4. Click Finish
    5. Be sure to check off lwip141 for inclusion with your bsp in the window that pops up (see img 2)

Step 7: FreeRTOS'ing Ernie

  1. Download the latest FreeRTOS release from Sourceforge.
    1. If the download is an executable, run it to extract the FreeRTOS files into your project directory.
  2. Keep that SDK open, and click File -> Import.
  3. We want to click General->From an Existing Workspace, and then we will want to navigate to where we downloaded FreeRTOS.
  4. Our demo will be located in FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702. Upon selecting this folder, we should see three projects pop up (our code (OS), it’s BSP, and the HW Platform).
    1. ONLY Import RTOSDemo into your current workspace.
  5. On all “blue” folder projects change the referenced BSP
    1. Right clicking and selecting “Change Referenced BSP.”
    2. Select the BSP you just created for your Zybo
    3. Code Editing in Xilinx’s SDK Blue folders are the actual code projects.

Step 8: Importing Ernie's C Code

  1. In the RTOSDemo/src directory, overwrite the existing main.c with the main.c file attached here.
  2. Copy the main_sound.c fiile into the RTOSDemo/src directory.

Step 9: Debugging Ernie

  1. Select Run -> Debug Configurations
  2. On the left pane create a new System Debugger run
  3. In the Target Setup tab,
    1. select “Reset Entire System” so that the both that and ps7_init are selected
  4. Now select the Application tab.
    1. Select “download application”
    2. Set the cortexa9_0 core to “stop at program entry”
    3. Click Apply and Debug.
  5. Verify that there are no errors in the debugging process
  6. Keeping a close watch on the robot, press the Resume button until program runs without hitting any breakpoints
  7. The robot should now turn and move towards loud noises. Yay!

Step 10: Making Ernie Autonomous

  1. Once your project is all ready to go (you can run with no problems through the debugger) you are ready to load it to the flash memory on your board.
  2. Create what is called the “first stage boot loader” (FSBL) project and contains all the instruction that your board will need in order to load your project files (the bit stream and OS) on startup.
    1. Select: File->New->Application Project and the following window should appear.
    2. Name it what you want (i.e. “FSBL”)
    3. Ensure the hardware platform is the one you are working with
    4. Press next (Do not press Finish)
    5. Select the Zynq FSBL template
    6. Click finish.
  3. Once the creation process is complete you will know if everything worked if you see the following two new folders in the Project Explorer window.
  4. Create a Boot Image Now you will need to create the Boot image.
    1. Right click on your project folder (in this case mine is called “RTOSDemo”)
    2. Click “Create Boot image” from the drop down
    3. If everything is linked correctly, the project will know what files it needs and the following window will look as you see below (key being that you have 3 partitions under Boot image section, the bootloader, your bit file, and your projects .elf file).
      1. If this is not the case there is possibly something wrong with your project linking. Insure that the project folders are linked to their respective BSPs
    4. Click the “Create Image” button
  5. The last step to perform in software is to now flash your previously created image to the board’s memory
    1. Select from the SDK’s main tool bar select Xilinx Tools->Program Flash Memory
    2. Insure that the correct hardware platform is selected and that the image file path is correctly pointing to the .BIN file created in the previous step.
    3. Select “qspi single“ from the Flash type
    4. Tick the “Verify after flash” to insure the integrity but it is not needed
  6. Configure Your Board Lastly you need to insure that the boards programming mode jumper (JP5) is correctly set to select to boot from the qspi (which contains what you just flashed) when the BootROM is run.
  7. Now simply power cycle the device and insure the “Logic Configuration Done LED” (LED 10) is lit green.

Step 11: Making Ernie Cute

  1. Fur
  2. Lots of Fur
  3. BIG eyes!
  4. ... top hat