Implementation of a simple TCP/IP server on the Cora Z7 board using FreeRTOS. This implementation is done with Vivado 2019.1, its associated SDK, and the example code included with this distribution. It will likely build and run fine with other distributions.
To start create the hardware system described in this element14 community blog. I followed the example closely except that I named the block design cora_design_1 and I added Cora’s two push buttons and the 2 RGB LEDs through and AXI_GPIO connection by dragging them from the Board tab of the Block Design window. When complete the block design appears as follows.
After validating the the design (F6), generate the Bitstream. Launch the SDK from within Vivado; File=>Launch SDK. Alternatively export the hardware; File=>Export=>Export_Hardware and then import the hardware description file after starting the SDK separately. If you don’t already have a Workspace create one. From within the SDK create a new application program. Give it a name and choose freertos as the OS Platform. Select the processor. Choose processor zero on a dual processor system. Create a new BSP. Click “Next>”.
Select the “lwIP TCP Perf Server” template. Click “Finish”.
Build the application. The default IP address of the application is 192.168.1.10. Configure your host IP to have a static IP on the same class-C subnet. You may change the default address of the application by editing the value of the #define DEFAULT_IP_ADDRESS in the main.c source file. Connect your host PC to the Cora board with an Ethernet cable. Also connect the Cora board micro USB port to your host PC. You will need a terminal program. You can use the terminal inside the SDK program or an external terminal program. I use TeraTermwhich is a free download. Open the terminal. Connect to the terminal through the Cora boards COM port. Configure the settings to the default application values of 115,200 baud, 8N1.
Right click the application project and select Run as=>Run configurations … . Configure as shown
Click run. If the terminal is connected to the COM port the following startup status information will be displayed.
If using a Windows host you will need to down7load the iperf utility. Download iperf version 2. iperf3 in incompatible with the server running on the Cora board. Open a cmd or terminal window on your host PC. In windows change directory where you have put the iperf executable.
from the command window run,
iperf -c 192.168.1.10 -i 5 -t 90 -w 2M
The output on the Windows 10 client and the Cora Z7 server are;
You should achieve a performance of approximately 500 Mbits/sec.
One of the components necessary for the end goal of controlling a motor is pulse width modulation (PWM). This component will be used to switch the FETs in the bridge to which the motor is connected. For a brushed DC motor two PWM components will be required; for a three phase brushless motor three.
This post covers the development of a single PWM component. Some of the features that I would like my PWM module to have include;
A single counter is used to drive multiple PWM components.
The resolution of the PWM is up to 14-bits.
Higher PWM carrier frequency (at the cost of lower resolution) can be achieved by using a least significant subset of bits from the counter. High PWM carrier frequencies are useful for driving low inductance motors.
Make the switch points of the PWM symmetric about the midpoint of the PWM carrier wave. The carrier midpoint would be the maximum value if a triangle carrier wave is used. I will be using a sawtooth carrier wave. The allows a simpler counter. I only need to count up and roll over compared to creating an up-down counter.
Generate a carrier wave midpoint signal that can be used to trigger motor current sampling. Sampling the motor currents as far as possible from the PWM switch points reduced noise in the current measurement.
Start Vivado and create a new project.
Click “Next“. Make it an “RTL Project” and check “Do not specify source at this time“. Click “Next“. Select your part. In my case the “Cora Z7-10” board from Digilent. Click “Next“. Review the summary and click “Finish” when satisfied.
Under “PROJECT MANAGER” in the “Flow Navigator” panel click “Settings“. Choose your target language. I will be using VHDL.
Click “OK”. Under “IP INTEGRATOR” in the “Flow Navigator” panel click “Create Block Design“. Give your design a name and click “OK“.
In the “Diagram” panel add IP by clicking on the “+” button. Add a binary counter. Double click the counter block and configure it to an output width of 14 bits. In the control tab check “Clock Enable (CE)” and “Synchronous Clear (SCLR)“.
Click “OK“. The counter needs to be driven by a clock. Click the “+” button and add the “Clocking Wizard” IP. Double click the “Clock Wizard” block to open it. Under the “Board” tab set “CLK_IN1” to “sys_clock“. Check out the “Clocking Options” tab. I just left the default settings. Under the “Output Clocks” tab set the frequency of the “clk_out1” output. I selected 250 MHz. This gives a particular set of possible carrier frequencies depending on the number of bits of the counter that are used. Higher frequency PWM permits lower current ripple in loads (ex. motor coils) with low inductance. A higher clock frequency could probably used. If you select a higher clock frequency, verify that all timing constraints when the hardware builds. The “Output Clocks” tab is also where the optional inputs, outputs and reset are configured. My selections are as shown in the figure below.
Counter Bits
PWM Carrier Frequency (KHz)
14
15.2588
13
30.5176
12
61.0352
11
122.070
Check out the “MMCM Settings” and “Summary” tabs. Click “OK” when satisfied.
Add ports to connect to “resetn” and “clk_in1“. Right click in the “Diagram” panel and select “Create Port …” from the menu to create each port. For the “resetn” port set the direction to “Input“, the type to “Reset” and the polarity to “Active Low“. For the port which will connect to “clk_in1“, name the port “sys_clock“. Set the direction to “Input“. Set the type to “Clock“. Specify the frequency as “125” MHz. You may need to select “Regenerate Layout“, from the right click menu, to get the diagram elements grouped.
From the “Project Manager” click “Add Sources“. Select “Add or create design sources“. Click “Next>” Click “Create File” and give it the name “PWM“. Click “OK” to add it to the local project. Click “Finish“. You could enter the port definitions in the “Define Module” dialog. Just click “OK“. We will edit the file directly. The file should appear in the hierarchy of the “Sources” tab. Open the file for editing. The source code file can be cloned from this repository.
The PWM module takes as inputs the PWM sawtooth carrier signal in the form of the count from the binary counter and the switch points to the left and right of the centre of the carrier signal. It uses the same clock as the counter. The reset is driven by the “locked” signal from the clocking wizard. The module is held is reset until the generated clock has stabilised. While in reset, the “ce” and “clr” signals are held at a level to keep the binary counter cleared and disabled. Outputs are the PWM signal itself (“pwm_out“) and a signal called “mid” which transitions from low to high at the centre of the carrier signal. This edge transition can be used to trigger current sensor acquisition and synchronise servo loops in motor control.
In the “Diagram” panel, right click and select “Add Module …“. Select the “PWM” module and click “OK“. The module with its input and output ports should appear in the diagram. Again you may need to “Regenerate Layout” to get the blocks to group. Add “mid” and “pwm_out” ports to the diagram. These are both “Output” ports of type “Other“. For now we will drive the left and right switch point signals of the PWM block with constants. Later these signals will be driven by a processor. Use the “+” button to add two “Constant” blocks. Double click to open and set the width to 13. Enter positive values for the switch points. I used 3636 for the left switch point and 4556 for the right switch point. This will give a a symmetric pulse about the centre of the carrier signal. With all signals connected, the block diagram should look something like the following figure.
Write click in the “Diagram” panel and select “Validate Design“. Everything should check out. With block diagram complete, right-click on the board file (.bd) in the sources hierarchy and click “Create HDL Wrapper …“. Let Vivado manage the wrapper and auto-update. Click “OK“.
Constraints need to be specified for the input and output ports in the diagram. Under the “PROJECT MANAGER” click “Add Sources“. Select “Add or create constraints” and click “Next>“. Select “Add Files“. Browse to where the you installed the Digilent Cora Z7 master constraint file. “Cora-Z7-10-Master.xdc” in my case. Select the file. Click “OK“. Make sure that “Copy constrains files into project” is checked. Click “Finish“. The constrains file should now appear under the “Constraints” section of the “Sources” tab hierarchy. Open the file to edit. Uncomment the two lines under the “##PL System Clock” comment. Change the name in braces to “sys_clk”.
Select IO pins for the “resetn“, “mid” and “pwm_out” signals. I used the first three IO pins of the JA Pmod header. Uncomment the lines and edit to set the IO names.
The complete constraints file is in the repository.
Under the “PROJECT MANAGER” > “PROGRAM AND DEBUG” click “Generate Bitstream“. When the build finishes, open the implementation. Check the “Design Timing Summary” and verify that the timing constraints are satisfied. The “Project Summary” will show the device utilisation.
It remains to check if the design actually works as expected. One way to check the design is to simulate it. The simulator is a very useful tool for debugging. It allows you to inspect both external ports and internal signals. Under the “PROJECT MANAGER” click “Add Sources“. Select “Add or create simulation sources“. Click “Next>“. Specify the simulation set. I used the already created set “sim_1“. This entry can be used to create multiple simulation sets. Click “Create File“. Select the file type; VHDL in my case. Give the file a name. I used “PWM_Test1“. Select the file location local to the project. Click “OK“. Make sure that “Include all design sources for simulation” is checked. Click “Finish“. You can specify the IO ports with the “Define Module” dialog. Just click “OK“. We will edit the file directly.
The “PWM_Test1” file should appear under “Simulation Sources” in the “Sources” hierarchy. Open the file to edit. This file is a wrapper around the “System_1_wrapper” in the “sim_1” set. When done the file should look like this the one in the repository.
Once you save the file it should take its place at the top of the “sim_1” hierarchy.
Under the “PROJECT MANAGER” click “Settings“. Under “Project Settings” click “Simulation“. Review the various tabs. I left the default settings.
Click “OK“.
Under the “PROJECT MANAGER” click “Run Simulation -> Run Behavioral Simulation“. The IO pins appear by default in the simulation “Wave Window“. Add the counter. Select the counter under the “Scope” tab. In the “Objects” panel, right click “Q[13:0]” and add it to the wave window. In the wave window right click on “Q[13:0]” and set “Waveform Style” to “Analog“. Run the simulation for the interval specified in the simulation toolbar by clicking the right arrow button with the “(T)” subscript. Next to the simulation time. I ran for three 100 microsecond intervals for a total of 300 microseconds. The waveforms should show up in the wave window. They didn’t initially on by Ubuntu 16.04 computer. If I toggle from “Default Layout” to ” Simulation Layout” and back, using the upper right selection box, the waveforms magically appear. I need to do this each time I run a simulation segment. I don’t have this problem on Windows. You can verify the sawtooth carrier with a 66.67 microsecond period (15 KHz). The “mid” signal transitions high at the midpoint of the carrier. The “pwm_out” signal has the expected pulse width and is centred about the carrier signal midpoint.
Finally lets program the board and view the outputs on oscilloscope. Under the “PROGRAM MANAGER -> PROGRAM AND DEBUG” click “Open Hardware Manager“. If it doesn’t immediately connect click “auto connect“. Click “Program Device“. Verify that the bit file is correct. Verify that “Enable end of startup check” is checked. Click “Program“.
Connect your scope. I am using a Digilent Analog Discovery2 to monitor the “mid” and the “pwm_out” signals. The Analog Discovery 2 is a compact, inexpensive device; perfect for the job. I highly recommend it.
Here are the output signals from the board.
In useful system the switch points will not be constants. In the next post a processor will be added to set the switch points.
Launch the Vivado SDK either from a terminal or the launcher. Select the location for your project workspace.
Click OK.
In the “Welcome” tab click on “Create Application Project“.
In the new project dialog click “New” so that you can select the target hardware to be that which you created in the previous post.
This dialog is used to create a new hardware project with hardware description file that was built in the previous post. Browse to the directory where you built the hardware description in the previous post and select the hardware description file. A default project name will appear in the “Project name:” entry. It can be edited. I left the default. The project location can also be changed if the “Use default location” box is unchecked. Again , I left the default. Click “Finish“.
Give the project a name. Select the language and note that a new board support package will be created. Click “Next”.
Select the “Hello World” template and click “Finish“.
In the “Project Explorer” tab you will see the “Hello-Cora” ‘C’ software project. The board support package (bsp) and the hardware platform project. Expand the sub-directories of these project to see there contents. Open the “helloworld.c” file by double-clicking it. Edit the printed message as you like.
Plug the Cora Z7 board into the a USB port on your computer. In Linux you can check which port is assigned to the Cora Z7 board by inspecting the contents of the /dev directory before and after the Cora board is connected. For example the following command in a terminal
ls -al /dev/ttyUSB*
before and after board is connected gives
The Cora board is connected to /dev/ttyUSB2. In the “SDK Terminal ” tab in the bottom centre panel click the “+” button to connect the serial port.
Make the settings 115200 baud, 8 data bits, 1 stop bit an d no parity.
Right click on the “Hello Cora” project in the “Project Explorer“. Select “Run As -> Launch on Hardware (System Debugger)” Progress will be updated in the “SDK Log” panel. The program will load and run. The output is displayed in the “SDK Terminal” tab.
Be patient it can take a while to load the debugger and run the application. If you prefer you can use a terminal program outside the SDK. GtkTerm works fine. Just connect to the same port and use the same port configurations.
Before you can create and run a “Hello Cora” software project, the hardware on which to run the program needs to be built. This post goes through the creation of a simple single processor bare-metal (no OS) system on which the “Hello Cora” application will be executed.
Start Vivado either from a terminal or use the launcher.
Under “Quick Start” click “Create Project >”
Click “Next >”
Enter a project name and location. Check selection box to create a project subdirectory.
Click “Next >”
Select “RTL Project” and “Do not specify sources at this time”.
Click “Next >”
Select “Boards”. Under “Vendor:” choose “digilent.com”. In “Search:” type “Cora”. Select your Cora board.
Click “Next >”
Review the “New Project Summary”.
When satisfied click “Finish”.
The project is initialised and the “Project Manager” window appears.
In the flow navigator bar to the left click “Create Block Design”.
In the “Create Block Design Dialog”, give the design a name. Leave other entries as the default.
Click “OK”.
In the “Diagram” panel, click the “+” button to add IP. You may click the button in the middle of the panel or in the tool bar along its top edge.
In the search window begin typing “zy”. “ZYNQ7 Processing System” will appear.
Make sure that it is highlighted and hit the “Enter” key. A “processing_system_7_0” block will appear in the middle of the panel. You may need to zoom in to make it readable. “Zoom Fit” in the tool bar didn’t work for me. Left click and dragging a “Zoom Area” box around the IP block did. You can also hold “Ctrl” and the mouse wheel to zoom in and out.
Click “Run Block Automation” at the top of the panel.
Accept the defaults and click “OK”.
Zoom in again if necessary.
Right click in the “Diagram” tab and select “Validate Design”.
A clock pin has not been connected. We will fix this. Click “OK”.
On the diagram make a connection between “FCLK_CLK0” and “M_AXI_GP0_ACLK”. As you hover over “FCLK_CLK0” a pencil will appear. Click and hold on “FCLK_CLK0” and drag towards “M_ZXI_GP0_ACLK”. A green check will appear on the “M_ZXI_GP0_ACLK” pin. Drag to this pin and release the mouse button. A connection is established.
Again validate the design. Right click select “Validate Design” or press F6. Two warning messages appear.
These are not a problem. Refer to Hardware errata page of the Cora Z7 Reference Manual. Click “OK”.
Save your project. Click the “Sources” tab design Hierarchy.
Right click on “System (system.bd) (1), click “Create HDL Wrapper …”.
Select “Let Vivado manage wrapper and auto-update”. Click “OK”.
After updating a wrapper file will appear. In the “Flow Navigator” bar click “Generate Bitstream”.
Click “Yes” to launch synthesis and implementation.
Accept the defaults of the “Launch Runs” Dialog and click “OK”.
A progress bar will appear for a short time and then you will see progress updating in the upper right corner of the screen.
When complete the “Bitstream Generation Completed” dialog will appear.
Select “Open Implement Design” and click “OK”.
At this point I was asked to take a survey of Vivado 2018.3 experience. I selected “Remind me Later”. I will take the survey after a bit more experience with this release and bring up the zooming issue. Explore the device and/or the “Project Summary” tab.
At this point our hardware has been generated. Export the hardware description so that is can be imported into the SDK for software development. From the file menu select “File->Export->ExportHardware …”.
Select “Include bitstream” and export “<Local to Project>. Click “OK”.
A “HelloCora.SDK” folder will be created in the project directory. The hardware description file will be imported into the SDK in the next post. If your project needs saving, save it.
If continuing immediately on the the software part of the “Hello Cora” example, you can launch the SDK from the file menu and it will automatically load the hardware description file that you saved in the project. This used to crash in version 2016.4 under Ubuntu but appears to work fine in 2018.3. Nice! Thanks Xilinx.
The Cora Z7-10 features a Xilinx Zynq 7010 System on Chip (SoC) which sports two ARM Cortex-A9 processing cores, a broad array of IO, dual abalog to digitla converters and programmable logic. Details of the board features can be found in the reference manual. Over the next several months I will work on several small projects with a end goal of creating an embedded system to control one or more brushed or brushless DC servomotors . The first step in this process is to install the necessary development tools.
Install Xilinx Vivado
Development on the Cora Z7 boards are supported by the Xilinx Vivado Design Suite. I will be using the latest Webpack version of this suite. At the time this project was started this was Vivado HLX 2018.3. I will be installing Vivado on a Ubuntu 16.04. I have installed Vivado on Windows 10 and got a “Hello Cora” project up and running but I found that the SDK would crash without an error message. Checking the Xilinx forums I found that a work around for the problem was to disable the automatic build setting in the Vivado SDK. To disable just uncheck “Automatic Build” under the “Project” menu of the SDK.
If you haven’t already registered an account with Xilinx you will need to do so before you can download Vivado. Once your account is set up, download the Vivado Design Suite suite from Xilinx.
Extract the archive into a working directory. Open up an terminal. Decide where you want Vivado installed. The default for Vivado 2018.3 /tools/Xilinx. I had previously installed Vivado 2016.4 in /opt/Xilinx so will be installing in the /opt/Xilinx directory. If your directory doesn’t already exist create it. In my case
If your permissions do not allow “other” read and execute permissions use the “chmod” command set the correct permissions.
sudo chmod 755 /opt/Xilinx
Start the installer.
cd Xilinx_Vivado_SDK_2018.3_1207_2324/ sudo ./xsetup
You will get the “Welcome” dialog box.
Note the comment circled in red. I will return to this later. Click “Next >”
Accept the license terms and conditions.
Click “Next >”
Select the edition that you have or for which you can obtain a license. I am using the free WebPACK.
Click “Next >”
These are the default WebPACK selections. I chose these.
Click “Next >” once your selection are made.
Click “Next >”
A summary of the installation choices will be displayed. You may go back and make changes if required.
Click “Install” when ready to proceed.
Installation progress will be updated.
When finished you will be notified.
Once installed, configure the settings file to run by adding the following lines to your .bashrc file in your home directory.
source /opt/Xilinx/Vivado/2018.3/settings64.sh
Make sure to use your install path. After starting up a new terminal Vivado can be run from the command line using
vivado &
The Xilinx SDK can be run from the command line using
xsdk &
I am using the “Unity” desktop environment. To launch Vivado and the SDK from the Unity Launcher create the following two files in ~/.local/share/applications
Vivado_2018.desktop SDK_2018.desktop
The contents of these file respectively is
[Desktop Entry] Name=Vivado_2018 Comment=Xilinx Design Suite for HDL design Exec=/opt/Xilinx/Vivado/2018.3/bin/vivado Icon=/opt/Xilinx/Vivado/2018.3/doc/images/vivado_logo.ico Terminal=false Type=Application
Start Vivado ether from the command line or the launcher. Start the License Manager under the Help menu.
Help->Manage License…
Click “Obtain License“.
Select the appropriate entry for your install and click “Connect Now“. Login to your Xilinx account. Click “Next” to proceed license entitlement page. Choose your license(s). Click “Generate Node-Locked License”. The “Generate Node License” dialog will come up. Add any comment that you like.
Click “Next“.
Review the license request.
Click “Next“.
The license file will be emailed to the email address set up in your Xilinx account. Close the email notification dialog.
When you receive the email, save the attached license file to a convenient location. From the Vivado License Manager click “Load License”.
Click “Copy License…“. Browse to the location that you save the license file that you received by email. Select it. Click “Open“.
Click “OK”. Select “View License Status” in the License Manager to view the updated License status.
Close the license manager. Exit Vivado.
Additional Library Installation
NOTE: None of this may be necessary.
Remember way back on the “Welcome” dialog for the installation of Vivado there was a comment about “Additional library installation required” for a Ubuntu install.
There is an answer in Xilinx support which addresses this issue.
That being said I have had no problem without following the procedure in this answer; and like they say … “If it ain’t broke don’t fix it. I did go part way through the procedure to try and discover the which libraries that my install missed. If I run into issues in the future I will need to revisit this answer.
A Perl script is provided to check for required libraries and libraries that are missing on a Linux system. Download the Perl script from
Save the script to a convenient location. Open a terminal and navigate to that directory. Check that Perl is installed on your system. Execute the command on the terminal.
which perl
If it exists and is found you should get a response something like.
/usr/bin/perl
If not found install Perl.
The Vivado environment needs to be set up by sourcing “settings64.sh”. This should already be done if you added the line
source /opt/Xilinx/Vivado/2018.3/settings64.sh
to your .bashrc file as directed above. Run (with your install path substituted)
You will get an output something like the following.
librdi_commonmain.so => not found /lib64/ld-linux-x86-64.so.2 librdi_common.so => not found libtcmalloc.so.4 => not found /lib/x86_64-linux-gnu/libc.so.6 linux-vdso.so.1 /lib/x86_64-linux-gnu/libm.so.6 /lib/x86_64-linux-gnu/libgcc_s.so.1 libboost_signals.so => not found
I found all of the libraries that the script reported missing in
/opt/Xilinx/Vivado/2018.3/lib/lnx64.o/
and
/opt/Xilinx/SDK/2018.3/lib/lnx64.o/
Install Cable Drivers
The Linux install of Vivado does not install the JTAG cable drivers. These can be installed by running a script as super-user. Change to the directory containing the script.
cd /opt/Xilinx/Vivado/2018.3/data/xicom/cable_drivers/lin64/install_script/install_drivers/
Run the “install_drivers” script as super-user.
sudo ./install_drivers
Install Digilent Boards Files
Before you can do much useful work with Cora Z7, a board definition file needs to be installed. Download the archive of Digilent Vivado boards repository from
Unpack the archive into a convenient location. Edit the “init.tcl” file in the “utility” subdirectory of the boards repository that you just unpacked. The Vivado_init.tcl file is for Vivado versions before 2016.4. Change the path in the script to the extracted location of the Digilent Vivado board files. My script looks like this. Note that environment variables will not work in this script.
Save the file and exit the editor. In a terminal, as super-user, copy the edited “init.tcl” file into “$HOME/.Xilinx/Vivado/
sudo cp init.tcl $HOME/.Xilinx/Vivado/
Vivado should now be setup and configured for the Digilent Cora Z7 board. In the next post I will create a simple “Hello Cora” application to run on one of the Cora Z7’s Zynq processors.