* Start work on README file.
This commit is contained in:
parent
2343a70c7d
commit
e241a78fa0
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
Sine / cosine generator in VHDL
|
||||||
|
=================================
|
||||||
|
|
||||||
|
This package contains a sine / cosine generator in synthesizable VHDL code.
|
||||||
|
|
||||||
|
The core takes a phase value as input and produces the corresponding sine
|
||||||
|
and cosine as signed integer outputs. The core is fully pipelined, accepting
|
||||||
|
a new phase input on every clock cycle. The corresponding sine/cosine outputs
|
||||||
|
appear after a latency of 6 or 9 clock cycles (depending on configuration).
|
||||||
|
|
||||||
|
The VHDL code has been optimized for Xilinx FPGAs and is arranged
|
||||||
|
to make efficient use of block RAM and DSP primivites in Xilinx FPGAs.
|
||||||
|
|
||||||
|
|
||||||
|
Algorithm
|
||||||
|
---------
|
||||||
|
|
||||||
|
The core uses a small lookup table, with interpolation between table entries
|
||||||
|
based on the Taylor series.
|
||||||
|
|
||||||
|
A lookup table contains a limited number (about 1024) points in the
|
||||||
|
first quadrant of the sine function. The following steps are performed
|
||||||
|
to compute the sine and cosine of an arbitrary point in the first quadrant:
|
||||||
|
|
||||||
|
1) Lookup the closest phase point in the sine table. This is done
|
||||||
|
simultaneously for the sine and cosine, using cos(x) = sin(pi/2-x).
|
||||||
|
|
||||||
|
sin_base = table[ i ]
|
||||||
|
cos_base = table[ M-i ]
|
||||||
|
|
||||||
|
These two lookups are done simultaneously, using a table stored
|
||||||
|
in a ROM block with two read ports.
|
||||||
|
|
||||||
|
2) Compute the phase mismatch between the table point and actual
|
||||||
|
phase input in radians. This requires multiplication by Pi,
|
||||||
|
which is implemented through repeated shifting and adding.
|
||||||
|
|
||||||
|
3) Use the Taylor series to obtain a more accurate approximation
|
||||||
|
of the answer. Depending on the required accuracy, either 1st order
|
||||||
|
or 2nd order Taylor approximation is used.
|
||||||
|
|
||||||
|
sin_improved = sin_base + d_phase * cos_base
|
||||||
|
cos_improved = cos_base - d_phase * sin_base
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
sin_improved = sin_base + d_phase * ( cos_base - d_phase * sin_base / 2)
|
||||||
|
cos_improved = cos_base - d_phase * ( sin_base + d_phase * cos_base / 2)
|
||||||
|
|
||||||
|
This requres two (1st order) or four (2nd order) multiply-accumulate
|
||||||
|
steps, which are implemented in DSPs.
|
||||||
|
|
||||||
|
4) Round the improved result to the required accuracy.
|
||||||
|
|
||||||
|
Phase points not in the first quadrant are obtained by simple mirroring,
|
||||||
|
i.e. swapping of sine and cosine and/or sign flipping based on
|
||||||
|
|
||||||
|
sin(x+pi/2) = cos(x), cos(x+pi/2) = -sin(x)
|
||||||
|
sin(x+pi) = -sin(x), cos(x+pi) = -cos(x)
|
||||||
|
|
||||||
|
This automatically ensures that the full sine waveform is perfectly
|
||||||
|
balanced around zero and that the 90 degree phase shift between sine
|
||||||
|
and cosine holds exactly.
|
||||||
|
|
||||||
|
|
||||||
|
Code organization
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The generic core implementation is only one VHDL file (sincos_gen.vhdl).
|
||||||
|
It has tunable parameters to set input/output word length and to trade
|
||||||
|
accuracy vs resources. Do not mess around with those parameters!
|
||||||
|
Detailed understanding of the algorithm is required to choose good parameters.
|
||||||
|
Incorrect parameters may make the output inaccurate or plain wrong.
|
||||||
|
|
||||||
|
Two wrappers are available which set the parameters for a sensible
|
||||||
|
balance between accuracy and efficiency:
|
||||||
|
|
||||||
|
sincos_gen_d18_p20.vhdl is for 18-bit sine/cosine output.
|
||||||
|
sincos_gen_d24_p26.vhdl is for 24-bit sine/cosine output.
|
||||||
|
|
||||||
|
These two wrappers are the only tested variants of the core.
|
||||||
|
|
||||||
|
|
||||||
|
rtl/ Synthesizable VHDL code
|
||||||
|
rtl/sincos_gen.vhdl Implementation of core with tunable generics
|
||||||
|
rtl/sincos_gen_d18_p20.vhdl Wrapper for 18-bit output, 20-bit phase variant
|
||||||
|
rtl/sincos_gen_d24_p26.vhdl Wrapper for 24-bit output, 26-bit phase variant
|
||||||
|
rtl/test_sincos_serial.vhdl Synthesizable test fixture for testing in FPGA
|
||||||
|
|
||||||
|
sim/ Test benches
|
||||||
|
sim/Makefile Makefile for building test benches with GHDL
|
||||||
|
sim/sim_sincos_*_probe.vhdl Simulate core for a few phase inputs
|
||||||
|
sim/sim_sincos_*_full.vhdl Simulate core for all possible phase inputs
|
||||||
|
|
||||||
|
tools/eval_sine_quality.py Python program to determine accuracy of
|
||||||
|
output from sim_sincos_dXX_pYY_full.
|
||||||
|
|
||||||
|
synth/ Synthesis runs for Xilinx FPGAs.
|
||||||
|
|
||||||
|
|
||||||
|
Output accuracy
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Accuracy of the sine/cosine output from the cores has been determined from
|
||||||
|
a simulation of the VHDL code on all possible phase input values.
|
||||||
|
|
||||||
|
----
|
||||||
|
Core variant sincos_gen_d18_p20 sincos_gen_d24_p26
|
||||||
|
Phase input width 20 bits 26 bits
|
||||||
|
Sin/cos output width 18 bits 24 bits
|
||||||
|
|
||||||
|
Amplitude 131071.008033 lsb
|
||||||
|
Offset 0.000000 lsb
|
||||||
|
Phase mismatch 1.30e-7 rad
|
||||||
|
|
||||||
|
Peak absolute error 0.966104 lsb
|
||||||
|
Root-mean-square error 0.330982 lsb rms
|
||||||
|
SINAD 108.94 dB
|
||||||
|
Effective nr of bits 17.80 bits
|
||||||
|
Spurious-free dynamic range 129.81 dB
|
||||||
|
|
||||||
|
cos(x) == sin(x+pi/2) exact match
|
||||||
|
sin(x) == - sin(x+pi) exact match
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
FPGA resources
|
||||||
|
--------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue