Skip to content

User Manual

tuvabjornberg edited this page Jun 18, 2024 · 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
Microphone array
12-pin PMOD cables
Ethernet cable
5V external power supply with a barrel jack connector (coaxial power connector)

Software

Required:
Vivado 2022.1 AS WELL AS 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.
In this project Vivado 2017.4 will only be used for it's SDK to generate a .elf file and Vivado 2022.1 for building the bitstream.

Zsh and Aactivator for sourcing the project's environment.

Recommended:
VSCode or other IDE
WireShark for finding bugs
GHDL, VUnit, GTKWave for testing.

Other good Set-up tips can be found here.

Drivers

Install board files
Linux Cable Drivers

Cloning the github repository

Follow this link for guide on cloning repository.

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

Build scripts will handle all of the setup.

To have a correct setup for your receiving PC main.c the IP of if may need changes. 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;

When the IP has been configured, the only thing you need to do to is enter the project folder through the terminal and write in the terminal.

build

After writing this, the creation-process will start and a bitstream will be generated. This will take about 30 minutes.

Connecting the hardware

The image highlights the important part of the Zybo that will be used to run this program. Make sure to check:
  1. The blue jumper in the top left corner is set to WALL, when using an external power source.
  2. The other blue jumper in the top right corner is set to JTAG or SD, depending on if you program the FPGA over UDB or using a SD-card.

The Zybo also has integrated LED lights, buttons and switches which for this project has their own purpose:

  • The four LEDs in the middle will indicate how many delays the sampling should have. They are controlled by button 3 (btn3) and button 2 (btn2), shown to the lower middle on the image above. Button 2 increments an index by 1, meaning adding 1 delay to each sample. Button 3 decrements the amount of delays. Maximum 15 delays can be run, at startup 8 delays will be set. The LEDs indicates the amount of delays with bits, MSB is shown on ld3 and MSB on ld0. An example: the standard 8 delay will light up ld3 while ld2-0 remains off (bits 1000).
  • The two RGB LEDs (above btn2, in a red box) will indicate how full the FIFO queues are:
    • LD6 being blue symbolizes empty
    • LD6 being green symbolizes almost empty
    • LD5 being red symbolizes almost full
    • LD5 being blue symbolizes full. Mixing of colors can occur, such as purple (almost full and full) and cyan (almost empty and empty).
  • To pad the data with a mic id (instead of 2's compliment) sw0 should be on.
  • To run with the generated simulated data instead of the array bitstream sw1 should be on.
  • Switch 3 (sw3) and switch 2 (sw2) are used to apply an ID to the FPGA, which is used when distributing the system to give them each a unique IP-address. ID's 0-3 can be applied by toggling the switches. They are set by bits, meaning sw3 indicates the MSB and sw2 LSB. An example: switch 3 on and switch 2 off will give the id 2 (bits 10)

The switches can be combined to fit the purpose and are not compulsory for the sampling.

When the program is running and sending UDP-packets the LED LINK will blink slowly and ACT should blink rapidly, they are placed by the Ethernet port.

The connectors that interfaces with the array are the PMOD connectors. 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.

To run the program with 4 arrays they need to be placed adjacent to each other with the PMOD pins facing to the left. The arrays are then connected as follows to the Zybo's PMOD ports from right to left (with view of back side of arrays) with the set amount of PMOD cables:

  • Array nr 1 (PCBA 2 DEFECTIVE) to JE, 1 cable
  • Array nr 2 (PCBA 1) to JB, 1 cable
  • Array nr 3 (PCBA 2) to JC, 2 cables
  • Array nr 4 (Version 1) to JD, 3 cables

Setup of UDP receiver

First you might 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_reciever.py):

UDP_PORT = 21844

Transmitter (main.c in SDK):

u16_t Port = 21844;

When running the receiver the user have to input the file name, whether the data should be saved as a txt or bit file and the recording length. If saved as a txt the data will be printed in rows that make it easy to debug and find errors in the sampling. However to listen to the sound the data have to be recorded to a bit file that can later be played using the sound_player.py.

The udp_receiver is now ready!

Startup procedure using JTAG

First turn on the FPGA and open SDK. Make sure the blue jumper is set to JTAG. 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.

Startup procedure using SD-card

The SD-card have to be flashed and a TFTP server have to be set up on the computer which can be found in the zybo-rt-sampler repository. Then two files have to be copied from the project to the /data/tftp/ folder the first is the bitstream using the following command:

cp /home/USER_NAME/PROJECT_LOCATION/FPGA-sampling/pl/vivado_files/acoustic_warfare.runs/impl_1/aw_top.bit bitstream

The we also have to copy over a file containing the C program (the UDP transmitter) which can be done using:

cp /home/USER_NAME/PROJECT_LOCATION/FPGA-sampling/pl/vivado_files/acoustic_warfare.sdk/SDK_PROJECT_NAME/Debug/SDK_PROJECT_NAME.elf ps.elf

It is important that the bitstream file have the name "bitstream" and the PS file "ps.elf" for this to work. After doing this simply plug in the FPGA and turn it on, after a few seconds the FPGA should program using the files in the /data/tftp/ folder and start sending data. The ACT LED will blink rapidly.

Process and analyze the data

The python script "udp_receiver.py" has two purposes.

  1. It can be used to check the bits sent from the FPGA in a txt file. This can be helpful to see if everything is timed correctly as patterns will appear if there are problems with the delay.
  2. It created an audio file to be used in other python scrips to analyze data.

The script "sound_player.py" allows you to listen to the audio of a mic from the array. 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.

Another script for audio files is "analyze_from_file.py". It will plot different graphs of the microphone data. It's recommended to record a sinus wave (500-1000 MHz). Figure 2 and 3 of the script can be helpful in finding malfunctioning microphones on the array.

Troubleshooting

Various problems can occur when trying to launch this program. Here is some help to locate and fix some of the 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

A solution for this problem has not been found. Try again and set "Number of jobs" to one in Vivado or in build.tcl.

No data received

If "new_sample_data.txt" (generated from "udp_receiver.py")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.py" is the same as in "transmitter_axi_full.c". Else 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. Be aware that if the data is to be used with the Acoustic Warfare beamforming algorithm the frequency should not be lowered.

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 "aw_top.vhd" under the sample_gen_n as "index". To see if a delay is needed and the size of the delay try to use "udp_receiver.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.

Future work

Some other known problems and future work can be found here.

Clone this wiki locally