FONT SIZE : AAA
In this final exercise we will be creating a software application which ties together all of the IP modules which we have created, to create a DSP-oriented system. The procedure of setting up the ZedBoard audio codec via the hardware registers will also be introduced.
Once the SDK has launched from the previous exercise, we can start by creating a new application.
(a) Select File > New > Application Project from the Menu Bar.
In the New Project dialogue, enter adventures_with_ip as the Project name. By default the option to create a new Board Support Package will be selected. Click Next.
(b) In the Templates dialogue, select Empty Application, and click Finish.
You should recall that when we created the custom IP peripherals in the previous tutorial that a set of software driver files were generated for each. We must now point SDK to those driver files. This is done by adding a new repositories to the SDK project.
(c) Navigate to Xilinx Tools > Repositories in the Menu Bar. In the Repositories Preferences window, click on New, as shown in Figure 5.17.
(d) Add the LED Controller drivers by browsing to the directory:
C:\Zynq_Book\ip_repo\led_controller_1.0 and clicking OK.
(e) Click New.
Add the NCO drivers by browsing to the directory:
C:\Zynq_Book\ip_repo\xilinx_com_hls_nco_1_0 and clicking OK.
Upon closing the preferences window, SDK will automatically scan the repository and rebuild the project to include the driver files.
We must now assign the newly imported drivers to their corresponding peripherals.
(f) The system.mss tab should be open in the Workspace. If it is not, open it by expanding adventures_with_ip_bsp in Project Explorer and double-clicking on system.mss.
(g) At the top left of the system.mss tab, click Modify this BSP’s Settings.
The Board Support Package Settings window will open.
(h) Select drivers from the left-hand menu and assign the led_controller driver to the led_controller_0 component and the nco_top driver to the nco_0 component, as highlighted in Figure 5.18.
Click OK.
The project will now rebuild.
The LMS IP core that we created with Mathworks HDL Coder and the audio codec IP also have software drivers, but due to their directory structure, we must import their drivers to the workspace rather than use a repository.
(i) In the Project Explorer panel, expand adventures_with_ip, right-click on src and select Import.
In the Import window, expand General and double-click on File System.
Click Browse in the top right corner, and navigate to
C:\Zynq_Book\hdl_coder_lms\hdl_prj\ipcore\lms_pcore_v1_00_a\include.
Click OK, to import the LMS IP driver.
In the right-hand panel, select lms_pcore_addr.h and click Finish.
Note: This directory will only be available if you have completed Exercise 4B of Tutorial 4.
If you have not completed this exercise, you can obtain lms_pcore_addr.h from the source directory C:\Zynq_Book\sources\adventures_with_ip_integrator\drivers.
(j) Similarly, import the audio controller IP driver, audio.h, from the directory C:\Zynq_Book\sources\adventures_with_ip_integrator\drivers.
With all the driver files for the IP imported, we can import the source files for our application.
(k) Follow the same procedure as in Step (i) to import the following files from the C:\Zynq_Book\sources\adventures_with_ip_integrator\software directory:
• adventures_with_ip.h
• adventures_with_ip.c
• audio.c
• ip_functions.c
The source files will be imported and the application should build.
(l) Open the header file adventures_with_ip.h by double-clicking on it in Project Explorer.
This is the main header file for the software application. At the top of the file you should see a list of included header files, which define a variety of functions which are used in the software application.
Further down the file you should see the inclusion of the custom IP header files which we imported earlier:
As an example of one of the header files that was created during the IP creation process, we will open the header for the LMS IP core.
(m) In the Outline tab on the right hand side of the SDK window, double click on lms_pcore_addr.h.
In the LMS header file, you should see the following definitions:
These define the memory-mapped address offsets of the various signals of the LMS peripheral. Data can be transferred between the peripheral in the PL and the software in the PS by writing to, or reading from the these offset addresses. The actual address that would be used to access these signals would be BASE ADDRESS + OFFSET.
Each IP peripheral that we added to our block design in IP Integrator is automatically assigned a base address in memory. These addresses can be determined from a Xilinx parameters C header file which is automatically created when exporting an IP Integrator design which contains a Zynq Processing System. The header file is called xparameters.h.
We shall now explore the Xilinx parameters header file.
(n) Switch back to the adventures_with_ip.h tab in the Editor window.
xparameters.h is included in this main header file, and is therefore accessible from the Outline tab.
(o) Open xparameters.h by double-clicking on it in the Outline tab.
Here you should see a list of memory base address definitions, along with a number of other parameters.
As we were previously looking at the LMS header file, we will look at the definition of the base address for the LMS peripheral.
(p) Scroll down the file until you see the following lines:
Here we see the definitions of both the base and high addresses in memory for the LMS peripheral. As the difference between the high address and the base address is 0xFFFF, the LMS peripheral has an addressable range of 65536 bits, or 64 Bytes.
Referring back to the memory address offsets for the LMS block in Step (m), if we, for example, wanted to write data to the input port x(k), we would do this by writing the desired value to the BASE ADDRESS + OFFSET, which in this case would be:
XPAR_LMS_PCORE_0_BASEADDR + x_k__Data_lms_pcore = 0x43C10000 + 0x100
Giving a unique address of 0x43C10100.
We will now take a look at the main software application file.
(q) Open the source file adventures_with_ip.c by double-clicking on it in Project Explorer.
This file contains the main function, and another function which implements an interactive menu that allows the user to control the system using keyboard commands via the terminal.
Take a moment to look over the file and note the function calls which are made.
In the main() function, the first set of functions are called to setup and configure the audio coded. These functions are defined in audio.c, which we will look at next.
(r) Open audio.c.
Here we have the functions which are called to initialise the audio codec and the required I2C interface in the Zynq PS.
We don’t want to go into great detail about the functionality contained here, but in basic terms the purpose of these functions is to configure the audio codec by writing to the codec’s control registers.
Each control register has a unique address which can be accessed via the I2C serial interface. The control register addresses are defined in the audio.h header file.
(s) Open audio.h.
This file contains a number of definitions relating to the audio codec and the I2C interface, as well as some prototype function definitions.
You should see an enumerated type which lists all of the audio codec’s control register addresses, which were mentioned in the previous step.
More information on the audio codec can be found in the data sheet:
http:/www.analog.com/static/imported-files/data_sheets/ADAU1761.pdf
Next we will have a look at the functions which control the custom IP peripherals in the PL.
(t) Open ip_functions.c.
This file contains the functions which control the IP peripherals, as well as some functions to initialise drivers for the GPIO and NCO.
The three functions of interest are:
• audio_stream() — Implements stereo audio loopback between the input and output ports of the audio codec. Left and right audio samples are read in from the audio controller peripheral’s I2S receive register and are then written back out to the controller’s I2S transmit register.
• tonal_noise() — This function builds upon the audio loopback in audio_stream(). A step size value is input via the slide switches on the board. The corresponding value is then output to the LEDs on the board by writing to the memory-mapped register of the LED controller peripheral. The step size value is also output to the NCO peripheral using the XNco_SetStep_size_v() function defined by the NCO driver file. A sinusoidal sample created by the NCO peripheral is the read in by the XNco_GetSine_sample_v() NCO driver function and, as in the previous audio streaming function, left and right audio samples are received from the audio codec. The sinusoidal noise component is then added to the left and right audio samples before being written to the audio controller for output to the codec.
• lms_filter() — This function combines the functionality of the NCO and the LMS peripherals to create system which add tonal noise to an audio signal, before using an LMS adaptive filter for noise cancellation to remove the added noise. As in the tonal_noise() function, sinusoidal samples are generated from the NCO peripheral and added to the left and right audio samples from the audio controller. The sinusoidal sample is then input to the LMS as the input sample x(k) and the sample with added tonal noise is input as the desired signal d(k). The resulting output of the LMS peripheral is only read if the user presses any of the push buttons on the board, otherwise the corrupted audio sample is retained. This allows the user to verify that the LMS filter peripheral is removing the noise.
Now that we have had a look at the functions and definitions contained in the various source and header files, we can move on to actually implementing the system on the ZedBoard.
To begin, we will program the Zynq PL with the bitstream that we generated in the previous exercise.
Note: At this stage ensure that the ZedBoard is powered on and both the PROG and UART USB ports are connected to your host computer.
You should also ensure that the board is configured to boot from JTAG.
(u) Select Xilinx Tools > Program FPGA from the Menu Bar. The Program FPGA window should be configured as in Figure 5.19.
Click Program.
The Zynq PL on the board will be configured with the bitstream and the DONE LED should turn blue.
At this stage we must invoke PuTTY — the terminal program which you should have downloaded at the beginning of this tutorial.
(v) At the location which you downloaded PuTTY, double-click PuTTY.exe. As you downloaded the executable file, Windows may present a security warning. Accept the warning by clicking Run.
(w) PuTTY Configuration should open, as shown in Figure 5.20.
(x) Select Serial as Connection type (highlighted in Figure 5.20) and configure the settings as specified in Figure 5.21.
NOTE: The value of the Serial line entry will vary depending on which the USB UART cable is connected to.
In order to determine this value on a Windows system, open the Device Manager and identify the COM port.
(y) Click Open, to open the terminal connection. The PuTTY terminal window will open.
With the terminal connection open, the final step is the run the software on the Zynq PS.
(z) Right-click on adventures_with_ip in Project explorer and select Run As > Launch on Hardware (GDB).
In the PuTTY terminal you should see the following output:
Note: At this point you should attach an audio patch cable between the PC speaker output and the board’s Line IN input. Also, connect headphones to the board’s Line OUT input. These connections are highlighted in Figure 5.22.
(aa) Open the audio file
C:\Zynq_Book\sources\adventures_with_ip_integrator\original_speech.wav
in an audio player, and begin playback.
Note: It may be useful to turn on the repeat setting in the audio player for continuous playback.
(ab)In the PuTTY terminal window, press the ‘s’ key on your keyboard.
This will prompt the software application to enter the audio_stream() function which we looked at earlier.
You should be able to hear audio of speech via the headphone connection.
(ac) Press the ‘q’ key on the keyboard to return to the menu.
(ad)Press the ‘n’ key on the keyboard. This will prompt the application to enter the tonal_noise() function.
Initially you should hear the same audio signal.
You should note that currently there is no step size being input to the NCO.
Push slide switch SW0 into the on position. You should now be able to hear a sinusoidal tone which has been added to the audio signal. LED 0 should also be lit.
Experiment with different step size values by varying the on/off values of slide switches SW1 and SW2. This will vary the frequency of the tonal noise.
(ae) Press the ‘q’ key on the keyboard to return to the menu. (af) Press the ‘f’ key on the keyboard. This will prompt the application to enter the lms_filter() function. The basic functionality here is the same as in the previous NCO function, and you can add tonal noise to the audio signal using the slide switches. With tonal noise being added to the audio signal, press any of the push buttons on the board. The sinusoidal tone will be adaptively filtered by the LMS, and the tonal noise removed.
This concludes this exercise on the creation of an audio application in the SDK. You should now be familiar with:
• The automatically generated xparameters.h header file, and its contents.
• Identifying memory-mapped base addresses and offsets for communication between software running on the Zynq PS and peripherals in the PL.
• The procedure of configuring the ZedBoard’s ADAU1761 audio codec via the control register addresses.
• Receiving and sending audio samples to/from the audio codec via an audio controller block in the PL.
• The process of communicating with custom peripherals in the PL via generated software drivers.
Manufacturer:Xilinx
Product Categories:
Lifecycle:Obsolete -
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: CPLDs
Lifecycle:Active Active
RoHS:
Manufacturer:Xilinx
Product Categories: Voltage regulator tube
Lifecycle:Any -
RoHS:
Manufacturer:Xilinx
Product Categories:
Lifecycle:Obsolete -
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: FPGAs
Lifecycle:Obsolete -
RoHS: No RoHS
Support