2. Configuring constraint files and interfacing modules with Zynq Processing System
Post date: Oct 05, 2013 6:47:55 PM
This post corresponds to the subproject "Bare Metal: Interacting with ZC702 Evaluation Kit's Pins" for the Zynq Project. The main objectives of this post are to demonstrate how to connect the port of a top module with the package pins of the ZC702 Evaluation Board and interface the Zynq EPP's Processing System (PS) with other modules, all in the Vivado IDE. The hardware description language (HDL) used in this and all other projects I do is Verilog, although the same methods, of course, can be done with VHDL. Unlike the first post, I am not as thorough in this post because the first post already covers how to create and build a project, starting from Vivado IDE and ending in the SDK. Since this post is not intended to teach Verilog or C++, the computer programming language in which the PS's source is developed, any detailed descriptions of the source files are only found as comments within the source code itself. This post does, however, cover information relevant to the post's main objectives and how to avoid many of the issues I came across. Note my primary reference manual is UG850, the ZC702's user guide. The user guide contains important information such as which components on the ZC702 map to which pins on the Z-7020. Finally, the project presented in this post can be downloaded for reference.
Figure 1. The pushbuttons (1.) and 8 LEDs (2.) are the components in this project that allow for user interaction. The left and right pushbuttons select 1 of the 8 LEDs, whereas the up and down pushbuttons increase and decrease the brightness of the selected LED, respectively.
Subproject Goal. In order to fulfill the main objectives, the goal of the project itself is to program the ZC702's Z-7020 Zynq EPP such that the brightness of a selected LED can be controlled by pulse width modulation (PWM) implemented via Verilog modules. As with the first project, the first steps are to create the project in the Vivado IDE, create a block diagram for the "ZYNQ7 Processing System" and other related-IP blocks, and generate a top module that instantiates the block diagram and acts as the project's top module. The top module is then modified such that the block diagram's ports "clock", "led_bus", and "reset" are not included as part of the top module's ports. These three ports connect to instantiations of modules developed to multiplex the 12-bit led_bus port of the processing system to 16 x 8-bit channels, the LedMultiplexer module, and implement PWM to control the brightness of the 8 LEDs, the LedPulse module. Once the top module is completed, a constraint file is created to configure the project's I/O constraints, that is to say, associate the package pins of the Z-7020 with the ports of the top module and configure the I/O standards for each port. The block diagram and bitstream is exported to the SDK for the processing system's software development once compilation is successfully completed and the bitstream is downloaded to the ZC702. The processing system's software is what utilizes the Verilog modules and AXI Interconnect together to carry out the project's goal.
/** * main() executes the simple pwm program */ int main() { /* initialize leds and make sure led is off */ print("The program is initializing\n\r"); for (size_t i = 0; i < leds.size(); i++) { (leds[i] = Led(i)).off(); } /* initially have the first led selected */ ledPointer = leds.begin(); /* begin main loop and quit if left and right buttons are pressed */ print("Entering main loop\n\r"); while (!left.isHeld() || !right.isHeld()) { /* perform actions */ upButtonActions(); /* increase brightness */ downButtonActions(); /* decrease brightness */ leftButtonActions(); /* select the leftward led */ rightButtonActions(); /* select the rightward led */ /* set brightness */ ledPointer->setDuty(brightness); } /* exit program on completion */ print("This program is ending\n\r"); return 0; }
Listing 1. Processing system's high-level source code
Figure 2. The two "AXI GPIO" blocks are configured so that they don't use the board's predefined I/O constraints.
The 2-bit interface port "buttons" connects to one "AXI GPIO" (1.) and the 12-bit interface port "led_bus" connects to the second "AXI_GPIO" (2.). The 1-bit interface port clock (3.) is needed in order to synchronize other modules with the processing system. The 1-bit interface port reset is needed to reset other modules whenever the processing system is reprogrammed. In order to connect wire's to outside of the block diagram, ports and interface ports have to be created (5.).
Interface Ports versus Ports. Regarding the development of the block diagram, be careful when trying to connect blocks to ports that lead outside the block diagram. When building the block diagram, note that the "AXI_GPIO" blocks, and perhaps other AXI IP blocks, cannot connect to regular ports and can only connect to interface ports with the correct VLNV selected (the VLNV property is configured in the "Create Interface Port" window which appears after trying to create an interface port). For instance, the VLNV selected for the interface ports "buttons" and "led_bus" is "Xilinx.com:interface:gpio_rtl:1.0". Interfaces such as "FCLK_CLK0" and "peripheral_reset" connect outside of the block diagram through regular ports.
Figure 3. Above is the register transfer level (RTL) schematic of this project's top module. The 8 vertical blocks to the right are instances of the user-defined module LedPulse whereas the other is an instance of the LedMultiplexer module.
Constraint Files. The I/O constraints are, in essence, the assignment of the Zynq EPP's pins with the top module's ports and the configuration of the port's I/O standards. The I/O and other forms of constraints are configured in a constraints file, which has the extension XDC in Vivado. The ZC702's constraints are automatically generated during compilation, though custom constraints are also includable through the creation of constraint files. Figure 4 shows how the constraint file of this project is written. The constraint file can also be automatically generated by Vivado as shown in Figure 5. ZC702's components (e.g. the LEDs and pushbuttons) associated I/O standards and package pins are found in UG850.
Figure 4. Vivado constraint file
Figure 5. A constraint file is automatically generated if the I/O standards and package pins (i.e. pins of the Z-7020) are assigned to each port through the "I/O Ports" window (4.). The "I/O Ports" window is reached by running the design model's "RTL Analysis" (2.) and then selecting the "I/O Planning" option from the layout menu (3.) located near upper-center area of the Vivado IDE.
Processing System's Fixed User I/O. Unlike the left and right pushbuttons which UG850 classifies as "User Switches", the up and down pushbuttons are classified by UG850 as "User PS Switches". If the "ZYNQ7 Processing System" IP block is set to its default settings, there are 54 I/O constraints that cannot be altered through a user-defined constraint file. "User PS Switches" package pins fall under this category and are accessed through the processing system's software by separate libraries designed to target the fixed I/O. The list of fixed I/O and their respective package pins are found in the "I/O Ports" window (see Figure 5) under the port labeled "FIXED_IO_mio". Each bit of the "FIXED_IO_mio" port corresponds to the argument "int Pin" which is a parameter for many of the functions associated with the XGpioPs driver. The documentation and examples for accessing the fixed I/O's with the XGpioPs driver are found in the file "system.mss". "system.mss" is found within a "board support package" in the SDK.
Figure 6. (click on image to enlarge) Once the block diagram has been exported to the SDK, the documentation for accessing the fixed I/O with the XGpioPs driver (2.) is located in the file "system.mss" in the board support package (1.).