This tutorial walks you through creating a digital sine and cosine wave generator on an FPGA.
You'll learn:
- How NCO components work together - from Frequency Control Word (FCW) to Phase Accumulator and CORDIC IP
- Step-by-step implementation in Vivado, including VHDL module integration
- Practical simulation and debugging techniques using ILA
- Real hardware implementation on a ZCU104 board
- Tips for extracting sine/cosine values and controlling wave frequencies
You can find the complete Video here:
Block diagram of designThis block diagram represents a Numerically Controlled Oscillator (NCO), which is used to generate a digital sine wave with a variable frequency. The main components of an NCO are: the Frequency Control Word (FCW), the Phase Accumulator, and the CORDIC IP.
- Frequency Control Word (FCW - N Bits):
- The FCW is an input value that controls the frequency of the generated sine wave.
- To increase the frequency of the sine wave, increase the FCW. For a slower sine wave, decrease the FCW.
- Phase Accumulator:
- The Phase Accumulator is the core of the NCO. It accumulates the phase by adding the FCW to its current value on every clock cycle.
- The output of the Phase Accumulator represents the current phase of the sine wave.
- This phase value continuously increases, and when it reaches π, the accumulator resets it to −π.
- The Phase Accumulator generates a phase ramp signal with values ranging from −π to π. The step increment of this phase is determined by the FCW.
CORDIC Block:
- The CORDIC block converts the input phase into the corresponding sine and cosine values.
Phase accumulator and FCW block are implemented as VHDL modules and you can easily download them from GitHub add them to your design.
https://github.com/FPGAPS/CORDIC_IP_Tutorial
The CORDIC block in Vivado generates a 32-bit output, where the upper 16 bits represent the sine values, and the lower 16 bits represent the cosine values. To access these values separately, two slices are used to extract the respective portions.
Add the VDHL codes as module to your design
Download the two VHDL files from the GitHub repository and add them as new sources to your project. Next, right-click on the block design and add the FCW and phase accumulator as modules to your design.
Add CORDIC IP in to your block design
From the IP catalog, add a CORDIC IP block to the design. Modify the CORDIC output functionality to generate sine and cosine values.
Add slices
Additionally, include two slices in the design:
- The first slice extracts bits 31 to 16 as the sine output.
- The second slice extracts bits 15 to 0 as the cosine output.
Add simulation clock to your design
To run the simulation, you can simply add a clock signal.
With all the modules and the IP block in place, connect them properly. Add some ports to the design, it makes the simulation results observing much easier.
Add top HDL wrapper and run the simulation
Finally, create a top-level wrapper and run the simulation.
Simulation resultsThe simulation results validate our methodology. When the FCW value is larger, the phase changes faster, resulting in a sine wave with a higher frequency. Conversely, a smaller FCW value produces smoother phase changes, generating a sine wave with a lower frequency.
Let’s double-check the zero-crossing points of the sine and cosine waves. We can observe a 90-degree phase difference between the two curves. also, note that the CORDIC block has an internal processing delay, which results in a phase offset between the zero-crossing point of the phase input and the generated waveforms.
The FCW and phase generator blocks are fully synthesizable, so there’s no need to modify them. However, you must provide a clock source for the design. You can use any clock source, such as the PS-PL clock from the ZYNQ IP block or an external clock generated using the Clocking Wizard.
Please follow the provided Video for this section!
Comments
Please log in or sign up to comment.