Lab 7 Assignment
ECE 525.642 FPGA Design using VHDL
Sine Wave Generator using Xilinx IP
The goal of this lab is to understand how intellectual property (IP) from various vendors can be used and incorporated into your own projects. This lab will utilize the Sine look-up table that will be generated from the Xilinx Vivado IP catalog’s DDS compiler.
This project involves designing a sine wave tone generator. The design will use the slider switches to set the tone frequency whereas a different set of switches will be used to set the volume of the sine waveform. One way to implement the tone generator is shown in the following block diagram, however, you can use different approaches. Either way, make sure to document your block diagram!
The switches are used to set the sample rate generator. This signal is an enable pulse with a specific period which is used to increment an 8-bit phase counter. The phase counter is then used as the input to a sine LUT DDS component that is generated using the Xilinx Vivado IP catalog’s DDS compiler. The output of the Sine LUT is a 16-bit value that is then passed into a volume level shifter which is controlled using another set of slider switches. The shifted sine wave is then bound to the input of a PWM generator, from which the output is used to drive the mono audio-output.
Figure 1 - Lab 7 Block Diagram
All of the white blocks will be process blocks or entity/architecture pairs created by the designer, while the orange block is a piece of IP that will be generated by Xilinx Vivado and used in the design.
This lab has the following requirements:
• BTNC is the overall reset for all sequential logic
• SW(5:3) will be used to set the volume level of the output
o ‘111’ will be maximum volume
o ‘000’ will be minimum volume
o All the values in between will be shifted based on switch positions. (see below)
• SW(2:0) will be used to set the output frequency of the sine wave
o ‘000’ will be 0Hz or DC **special case for counter!
o ‘001’ will be 500Hz
o ‘010’ will be 1000Hz
o ‘011’ will be 1500Hz
o ‘100’ will be 2000Hz
o ‘101’ will be 2500Hz
o ‘110’ will be 3000Hz
o ‘111’ will be 3500Hz
• SW(15) will be used to turn on and off the amplifier network for the audio output, setting SW(15) to ‘1’ will cause the audio output to turn-on. (Use the FPGA output AUD_SD to turn on and off the audio output amplifiers)
• The frequency value of the sine output will be displayed on the lower four 7-segment displays. Make sure to display the frequency value in decimal format as 500, 1000, 1500, etc.
• The volume level of the sine output will be displayed on the upper four 7-segment displays. We will display as percentage value based on value of SW(5:3) over the max value of 7.
A switch value of ‘111’ would be 7/7 or 100%. Switch value ‘110’ would be 6/7 or 86%, then ‘101’ would be 5/7 or 71%, then 57%, 43%, 29%, 14%, and finally 0% for ‘000’ switch values.
Note: You do not need to display percent sign, so display should show 100 for 100% or 86 for 86%.
The output for this lab can be heard by plugging in a set of stereo headphones to the mono-audio output jack. Be careful when you first turn it on if the volume is set to 100% as the output can be very loud! You should be able to hear the different frequencies, but a more scientific method would be to use an oscilloscope to verify the proper frequencies and amplitude levels. This can be done by probing the output signal with an oscilloscope. Since both the USB connected Nexys-4 board and oscilloscope should share a common ground, I recommend not attaching the ground lead of the scope for this diagnostics measurement to avoid any potential damage to the development board.
The volume level from SW(5:3) will be done by shifting the output sine value to the right by the inverse of the value. So a switch value of ‘111’ will not shift the sine LUT output at all as that’s 100% volume. A switch value of ‘010’ will shift the sine LUT output by a value of 5 bits. A switch value of ‘000’ will shift the sine LUT output by 7 bits to create the lowest volume level (called 0% but still audible!)
Operation of Sine LUT
The Sine look-up table will be generated by the Xilinx Vivado IP Catalog. Select the IP catalog category under the Project Manager and find the DDS Compiler as shown below.
Figure 2 - DDS Compiler
Selecting that option brings up the DDS Compiler form. This is where the IP can be configured to provide the inputs, outputs, and desired functions for use in this lab. In the case of this lab, we want the following properties:
• SIN COS LUT only configuration, with SINE Selected as output
• System Clock: 100MHz
• Mode of Operation: Standard
• Phase Width: 8-bits
• Output Width: 16-bits
This will provide the inputs and outputs that we expect. Note that the 8-bit input and 16-bit output of the sine LUT could be tailored depending on PWM generator and sample rate generator. For this lab, I’d recommend sticking with those values but be sure to think about how those values were determined. For more information on each option, be sure to select the Documentation tab and view the guide.
Figure 3 - DDS Compiler Documentation
Once the Sine LUT is generated, you will see the IP shown in your design sources. Now, add the component to your top level lab7 design and instantiate the entity to use. See below for the component that was included in my project:
This shows the following input/output ports:
• aclk which is the 100MHz input
• s_axis_phase_tdata phase input which is just the output of the 8-bit phase accumulator block
• m_axis_data_tdata output which is the 16-bit sine value at the current position in the sine look- up table
• The m_axis_data_tvalid signal, in this case, can be ignored
• The s_axis_phase_tvalid input can be set to ‘1’
The operation of the sine DDS component is fairly simple. Given a phase, which I also call theta, the sine_lut_dds component outputs the STD_LOGIC_VECTOR value at that phase on a sine waveform. Note the m_axis_data_tdata output needs to be level shifted prior to adjusting the volume. This can be done by inverting the MSB of the m_axis_data_tdata signal.
To use this DDS to generate an output sine wave at any desired frequency we have to note that:
1/[Output Frequency of Sine Wave] = (Maximum Phase Counts) * (Phase Increment Delay)
And since the Maximum Phase Counts is well defined in our component at 8-bits, that means:
1/[Output Frequency of Sine Wave] = (2^8)*(Phase Increment Delay) = (256 * Phase Increment Delay)
The Phase Increment Delay is the time it takes to increment the s_axis_phase_tdata or theta input on the sine_lut_dds by 1 count. For the case of our board we have a 100MHz local clock, so the theta input will need to increment at a rate slower than 100 MHz. This can be controlled by defining a maximum sample rate count to generate an enable signal that increments the phase at a specific rate. To determine the count rate needed to reach the desired frequency, the equation would be:
1/[Output Frequency] = (256 * 10ns * Max Sample Rate Count), where the output frequency is 500Hz, 1kHz, … , 3.5kHz.
For example, to generate a 1kHz signal, that means we would want: 1/1000Hz = (256 * Max Sample Rate Count * 10ns)
Which means we need to set the Max Sample Rate Count to 391. Therefore, the phase counter will increment by one value every 391 periods of the 100MHz clock in order to generate a tone at 1kHz.
**NOTE: The output of this DDS is 16-bits but the PWM Generator is sized for 10-bits, so only use the top 10-bits of the m_axis_data_tdata output for the next step! (including the inverted MSB)
Mono-audio Output PWM Signal
This lab requires creating a PWM generator to properly output the sine wave onto the mono audio output jack. The mono-audio output jack uses a PWM signal to set the value of the output signal on the headphones. The idea is to take the sine output value and generate the appropriate PWM value based on the intensity of the sine value. In other words, higher sine values should create a PWM signal with a higher duty cycle.
Figure 4 - PWM Signal Generator
A good reference for how the mono-audio output works is in the Nexys-4 DDR reference manual.
Please review section 16. For an idea on how I implemented the PWM generator, let’s take a look at my entity declaration:
This has one generic, which is not required for this lab but could help make this entity more useful in different designs by allowing the resolution to be defined as a parameter. The resolution is the number of bits that define the PWM count, which sets the overall PWM frequency and number of counts prior to resetting back to zero (2^resolution counts).
In the case of this lab, I used a resolution of 10-bits. The pwm_gen component would then have a counter which would count from 0 to 1023 and set pwm_out to ‘1’ when the counter is less than the duty_cycle value and set it to ‘0’ when greater than or equal to the duty_cycle. One extra condition is to make sure the pwm_out gets set to ‘0’ at least for one clock cycle during each period; otherwise it could create a constant DC output. To do this, I make sure that when the counter is at the maximum value of 1023, the output is set to ‘0’ .
This general overview, along with the material in the Nexys 4 reference manual in section 16.1 should provide a good grasp on coding this component. I would recommend writing this component and simulating it separately prior to integrating it and trying to use the component in the lab 7 overall design. Good test cases would be to provide the value 0, 256, 512, and 1023. Verify that the PWM holds the appropriate pulse width for each of the values by looking at the time the signal is ‘ 1’ and dividing that over the entire period length.
Design Verification and Testing
This lab can be tricky to verify if just using the headphone jack. That is one method for debugging, but it will be tough to determine the frequencies and accuracy of the output signal. I will STRONGLY recommend that each student use an oscilloscope to monitor the output of the signal by probing the output jack (or one of the pads between R172 and R271) to verify the signal frequency is correct.
An example output for the 1kHz case is as follows:
Figure 5 - 1kHz Output Waveform (500mV/div and 500uS/div)
Task 1 (Work on in 1st week)
For the first week of this assignment, work on simulating the design to visualize the sine output in the Vivado simulator. This will confirm the correct frequencies and sinusoidal outputs are generated prior to generating the bitfile and implementing the design in hardware.
Task 2 (Due in the 2nd week)
This task is to complete the requirements of the design and submit a final copy of the design files and bit file that shows a working tone generator that meets the requirements above. The design should use the Sine LUT DDS IP to generate the appropriate sine values.
Extra Tools for Testing
This lab can also be tested by using audio applications on iOS or Android smart phones. One tool for Android is called AudioTool and can be used to verify the output frequency. A free option on Android would be the Sound Spectrum Analyzer. A free tool for iOS is called Decibel 10. Any of these tools can be used to verify the output frequency without the need of a scope but of course at the cost of accuracy.