Skip to content

User Manual

IvarNilsson edited this page Aug 8, 2023 · 29 revisions

Welcome to the Acoustic-Warfare FPGA-sampling user manual!
Here is a complete guide to build and run the FPGA-sampler.

Requirements

To be able to build the project some hardware and programs are required.

Hardware

Zybo Z7-20 or Zybo Z7-10
Microphone array

Software

Required:
Vivado 2017.4 other versions of Vivado will also work but have not been tested on. If you use Vivado 2020.1 or newer Vitis will be used instead of SDK and some changes might be needed.

SDK will be included in Vivado.

Recommended:
VSCode or other IDE
WireShark for finding buggs

Drivers

Install board files
Linux Cable Drivers

Cloning the github repository

Follow this link for guide on cloning repository.

Configuring build.tcl file

To change what to launch when running the script change the following parameters. If you use a zybo z7-10 some changes have to be done to reduce the size of the fifos to reduce the number of b-rams used. There might be more changes needed and the axi-full have only been tested on the z7-20.

Configuration on the Z7-20

The only lines that have to be altered are the options parameters the recommend parameters are

set options {
   {gui.arg   "1"             "Launch in gui (1 to lanch gui | 0 not lanch gui)" }
   {board.arg "20"            "Select part (10 for Zybo z7-10|20 for Zybo z7-20)"}
   {synth.arg "1"             "Run synth (1 to run synth | 0 not run synth)"     }
   {impl.arg  "1"             "Run impl (1 to run impl | 0 not run impl)"        }
   {sdk.arg   "1"             "Launch SDK (1 to launch SDK | 0 not launch SDK)"  }
}

Configuration on the Z7-10

On the Zybo Z7-10 we have to do a bit more manual configuration, therefore the parameters need to be set to

set options {
   {gui.arg   "1"             "Launch in gui (1 to lanch gui | 0 not lanch gui)" }
   {board.arg "10"            "Select part (10 for Zybo z7-10|20 for Zybo z7-20)"}
   {synth.arg "0"             "Run synth (1 to run synth | 0 not run synth)"     }
   {impl.arg  "0"             "Run impl (1 to run impl | 0 not run impl)"        }
   {sdk.arg   "0"             "Launch SDK (1 to launch SDK | 0 not launch SDK)"  }
}

Build the project

Launching the project and generating a bitstream is slightly different depending on if you use the Zybo Z7-10 or the Z7-20.

Build on the Z7-20

If you use the Z7-20 the build.tcl script will handle all of the setup. The only thing you need to do is enter the project folder through the terminal and write in the terminal.

build

After writing this, the creation-process will start and a bit-stream will be generated. This will take about 30 minutes. When SDK is launched the build is complete.

Build on the Z7-10

Since the Zybo Z7-10 have less B-RAM than the Z7-20 we have to decrease the size of the FIFO used. Therefore the bit-stream is not automatically created. After Vivado launches open the FIFO block-diagram that can be found by expanding aw_top then fifo_bd_wrapper_gen[0] then open fifo_bd_i. In the block-design double click the FIFO-block and open the "Native Ports" tab. Change the "Write Depth" from 1024 to 512. Than validate and save the updated block-design. Now click "Generate Bitstream" and wait for the implementation to finish.

After the bitstream is complete open the "File" tab and chose "Export Hardware" under "Export". Make sure the "Include Bitstream" is checked. Lastly under the "File" tab click "Lanch SDK".

Creating the SDK project

Now it is time to program the Zynq processor. To start open the "File" tab and chose "New" then "Application Project". Enter a project name and click "Next>", chose the "lwIP Echo Server" template and click "Finish".

When the project is created start by clicking the "Modify this BSP's Settings" it is located under the system.mss tabe. Then navigate trough the side tabs "Overview" then "standalone" and finally to "lwip141". Under this tabe locate the "temac_adapter_options" droppdown and change the "phy_link_speed" from "Autodetect(CONFIG_LINKSPEED_AUTODETECT)" to "1000 Mbps (CONFIG_LINKSPEED1000). This fixes a problem where the program gets stuck in a auto negotiation for the speed which seems to have problems with some versions of linux.

To the create the source files for the udp transmitter open "src" folder in the project and then deleting the "echo.c" file. Open the "main.c" file and replace the code with the code from udp_transmitter.c.

The first and most important thing to change in the main file is the ip of the receiving pc. We used 10.0.0.1 and then match it manually on the receiving computer instead to make the same program able to run on all PCs.

// ip of receiving pc
IP4_ADDR(&ip_remote, 10, 0, 0, 1);

Recommended configuration of receiving PCs IP-address

IPv4 addr: 10.0.0.1 
NET-MASK:   255.255.255.0
GATEWAY:   192.168.1.1

There are a few more parameters that can be good to know about but they do not need to be changed for the program to work.

    // set number of arrays used
    u32 nr_arrays = 4;

    // set number of 32bit slots in payload_header
    u32 payload_header_size = 2;

    // constants that will be sent in payload_header
    u32 protocol_ver = 2;
    u32 frequency = 48828;

The port is also set in the main file, later in the UDP-receiver it is important that the port number is the same.

u16_t Port = 21844;

Last step is to open "platfrom_zynq.c" and remove line 133. The line is easy to find because it creates a compiling error.

xemacpsif_resetrx_on_no_rxdata(echo_netif);

Connecting the hardware

The image highlights the important part of the Zybo that will be used to run this program. First step is to check that the blue jumper in the top left corner is set to USB. Secondly check that the other blue jumper in the top right corner is set to JTAG.

The four LEDs in the middle will indicate how full the FIFO cues are. The LD3 symbolizes empty, LD2 almost empty, LD1 almost full and LD0 full. When the program is running it is important that LD0 are off since this would mean that samples are lost.

The last part are the LEDs ACT and LINK by the Ethernet port. When the program is running and sending UDP-packets LINK will blink slowly and ACT should blink rapidly.

The connector that interfaces with the array is the JC PMOD connector. The picture indicates how the pins are configured and if the array is placed with the microphone inputs facing up it should be able to plug straight in to the connector.

Setup of UDP receiver

First you will need to disable the firewall to be able to receive UDP packets from the FPGA. Linux, Windows

Make sure the port in the receiver is the same as in transmitter.
Receiver (udp_receiver.c):

#define PORT 21844

Transmitter (main.c in SDK):

u16_t Port = 21844;

To compile the "udp_receiver.c" code open the ps folder of the project in the terminal and compile the file. The command for compiling the file will depend on whether you use Linux,Windows or Mac-os.

The udp_receiver is now ready!

Startup procedure

First turn on the FPGA and open SDK. Then to simplify debugging connect the SDK serial-monitor for the connected Zybo. On Linux we first have to allow read and write ability by entering following command in the terminal. ttyUSB1 might have to be changed to the right port of the computer.

sudo chmod 666 /dev/ttyUSB1

Then open the SDK serial-monitor and click the plus sign and chose the usb-port that the Zybo is connected to. If done correctly the SDK terminal for the serial-monitor will print "Connected to /dev/ttyUSB1 at 115200"

Open the "Xilinx" tab, click "Program FPGA" and "Program". Now the "Done", "LD0" and "LD1" LEDs should light up. The Done led means that the bit-stream successfully transferred to the FPGA. The LD1 means that the FIFOs are almost full and LD0 that they are also completely full.

Make sure the Ethernet cable is connected between the FPGA and the PC. Then right click on the project folder in SDK and chose "Run As" and "1 Launch on Hardware (System Debugger)". This will program the Zynq processor on the Zybo. In SDK terminal the following will be printed.

-----lwIP RAW Mode Demo Application ------
WARNING: Not a Marvell or TI Ethernet PHY. Please verify the initialization sequence
Start PHY autonegotiation 
Waiting for PHY to complete autonegotiation.
autonegotiation complete 
link speed for phy address 1: 1000
DHCP Timeout
Configuring default IP of 192.168.1.75 
Board IP: 192.168.1.75
Netmask : 255.255.255.0
Gateway : 192.168.1.1
Setup DoneSuccess in UDP binding 
Success in UDP connect 

After this is printed in the SDK terminal the ACT led should start blinking rapidly. LD2 and LD3 will turn on and LD0 and LD1 will turn off. This means that the FIFO is empty which means that the Ethernet communication is keeping up with the sampling frequency.

Before starting the UDP-receiver beware that it will create a text-file and write a lot of data. Therefore make sure to not run the program for more than a couple seconds to keep the files at manageable sizes. To start the receiver open the PS folder in a terminal and run the UDP-receiver.

The UDP receiver is now recording and saving the data to "new_sample_data.txt". To stop the receiver click ctrl+c in the terminal. If everything worked correctly the data in the text-file should consist of 68 columns and the 48818 rows per second of recorded data. The first and second column should be all ones, the third one is the sample frequency and the fourth a counter. The fifth to 68 column is the data.

Process and analyze the data

The first and most important way to analyze the data is to listen to it. This is done with "sound_player.py". Make sure the variables have the right name for your file and run the program. If the sound is extremely noisy there might be a delay problem in the sampling more on that in the troubleshooting section.

The python script "udp_p.py" can be used to check the bits that are sent from the FPGA. This can be very helpful to see that everything is timed correctly. If there are problems with the delay, patterns will appear that help find the problem. More on this is also found under the troubleshooting section.

Sample_counter_check.py can be used to check if there are any missing UDP-packets. The if there are any other terminal outputs than the number of rows in the data file there are packets missing.

Signal_analyzer.py can be used to plot various data from the microphones. Figure 2 and 3 can be very helpful in finding broken microphones on the array.

If the "new_sample_data.txt" is empty a great start is to use WireShark to se all Ethernet communication to the computer. This is a great first step in troubleshooting if there is no data received.

Troubleshooting

various problems can occur when trying to launch this program. Here is some help to locate and fix some problems.

Vivado problems

If the bit-stream generation was unsuccessful here are some tips.

Vivado not able to config Zynq block

If Vivado is unable to configure the Zynq block in the block design this can be due to the Vivado version used. Vivado 2020.2 on Linux is one of the version that have this problem. However this project should still work since the Zynq block is preconfigured from a .tcl script.

Vivado crashing when trying to generate a bit-stream

This problem has not completely bean solved but something that seems to help is to set "Number of jobs" to one.

No data received

If "new_sample_data.txt" is empty a good first step is to see if the computer is receiving any UDP-packets. The recommended tool for this is WireShark which will display all the packets received by the computer. If there are no packages showing up here when running the FPGA there is a problem with the UDP-transmitter. A good first test is to do a UDP-ping test. If there is no contact with the FPGA try just a Hello World test to see that the Zynq processor is configured correctly.

If there are packets received by WireShark but no data in the "new_sample_data.txt" file then it is probably a receiver problem. Start by checking that the port in "udp_receiver.c" is the same as in "udp_transmitter_sdk.c". If they are the same but there are still no data try running "udp_p.py" and if samples are printed in the terminal. If there is data printed make sure the "udp_receiver.c" have a correct file-path for creating "new_sample_data.txt". If there is no data when running "udp_p.py" the problem is more likely caused by a firewall or something similar.

Bad data received

Only receiving zeros

There are some things that can cause the receiver to only get zeros. The first is a bad mic-array, if possible try a different array. The second one is a bad WS signal. Try extending the duration of WS in ws_pulse.vhd to three pulses long and look at it in a oscilloscope to see that it is a nice square wave with the correct interval.

Noisy and bad sound

If data is received correctly but it is noisy and sounds bad there are a couple of different things to try. The first fix is to lower the sampling frequency. This can be the cause of the problem but in our experience frequency under 16 kHz should not create noisy data. A second adjustment is to check the delay. A small delay from when WS is activated to when the FPGA start to sample might be needed for optimal result. This can be added in "sample.vhd". To see if a delay is needed and the size of the delay try to use "udp_p.py" and search for patterns that creates very big values. If the sampling is of by as little as one bit the data can be completely unusable.

Clone this wiki locally