The Harmon Instruments sine and cosine core is a lightweight yet high performance sine and cosine generator. It uses a lookup table containing 1024 points over the first 90 degrees of cosine as well as the derivative at each point. Values between the points are interpolated using the derivative. Output is up to 25 bits and the angle input is 26 bits.
Source is available on GitHub in the sincos folder.
git clone firstname.lastname@example.org:HarmonInstruments/verilog.git
high precision: 23 bits sine + cosine with 26 bit angle
- 1 RAMB36E1
- 2 DSP48E1
- 55 LUT
- 96 register
Tested at 400 MHz in Kintex 7 XC7K70T-1 with 0.5 ns timing slack.
As reported by the test bench with 23 bit output and 26 bit angle using 10000 random angles. Some compromises are made for speed and mapping to the DSP block.
maximum magnitude error = 6.18296556398e-07 maximum magnitude error (LSB) = 2.59332310139 maximum angle error (radian) = 4.92378911865e-07 maximum angle error (LSB) = 5.25895510277 mean magnitude error = -1.68352097434e-07 mean magnitude error (LSB) = -0.706119707324 mean angle error (radian) = 4.24850255127e-08 mean angle error (LSB) = 0.453770127694 RMS magnitude error = 2.41033500234e-07 RMS magnitude error (LSB) = 1.01096753313 RMS angle error (radian) = 1.6067079938e-07 RMS angle error (LSB) = 1.7160778008
As a DDS, the largest spur is the zero spur of about -135 dBc and there are a few spurs that move around that have a near constant amplitude of -144 dBc. The plot below is an FFT of 131072 samples of output (on hardware).
sincos #(.NBD()) sincos_i (.c(), .a(), .o_cos(), .o_sin());
- c: clock in
- a: angle in, 26 bits, 2*pi radians = 226
- o_cos, o_sin: cos(a) and sin(a) scaled by 2(NBD-1) - 1
- NBD: parameter for the number of data output bits, 12 to 25.
- the NBA parameter was removed as reducing the number of angle bits did not save significant resources.
Latency is 6 cycles
- sincos/sincos.v: top level module
- sincos/cos_int.v: cosine interpolator core
- primitives/dsp_DSP48E1.v: DSP48E1 wrapper
- sincos/cosrom_generic.v: cosine ROM, generic (Spartan 6, etc)
- sincos/cosrom_RAMB36E1.v: cosine ROM, RAMB36E1 (7 Series)
Generating and simulating
The generated source is checked in to Git so these steps are optional.
The following files from a Xilinx Vivado or ISE installation are required to simulate with the Xilinx primitives. Harmon Instruments cannot distribute these due to the Xilinx copyright. Edit the VIVADO= in the Makefile so it can find them.
Xilinx/Vivado/2014.4/ids_lite/ISE/verilog/xeclib/unisims/RAMB36E1.v Xilinx/Vivado/2014.4/ids_lite/ISE/verilog/xeclib/unisims/DSP48A1.v Xilinx/Vivado/2014.4/ids_lite/ISE/verilog/xeclib/unisims/DSP48E1.v
The testbench uses [cocotb] 0.4-277 or later.
Older versions will report failure despite the logic being correct.
It is expected to be located in
Icarus Verilog is used as the simulator. Version 0.10.0 is known to work.
make all will generate the source and run the testbench.
This has been tested on a Xilinx Kintex 7 XC7K70T-1 FPGA at 400 MHz. It will require some porting for other parts due to the use of primitives.
The Harmon Instruments FPGA cores are licensed with the GPLv3. A commercial license may be negotiated upon request. For information, contact sales (at) harmoninstruments.com.