Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Tricky generation of sin / cos LUT with passed generics?

Status
Not open for further replies.

cbeighley

Newbie level 2
Joined
Dec 23, 2010
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,303
Hello,

I am wondering if there is an elegant way to implement in VHDL a sin/cos lookup table for a complex local oscillator with generics. Specifically what I want to do with to be able to specify the width of the input phase (for instance 8 bits, 0 to 255 corresponding to 0 to 2*pi) and the width of the output sin / cos signals (for instance 3 bits => 2's complement -3 to +3) with generics and have it generate the look up tables for sin / cos upon synthesis.

Currently what I am doing is I have a script in Matlab that generates the values on which a discrete sin / cos should switch (for a given quantization and code phase size) and manually insert this into a VHDL module. I could just generate the code with Matlab, but I'd like to figure out how to do this in VHDL.

Is there a way to have all this Matlab computation done in VHDL to generate the look up table for a given passed generic quantization width and code phase width upon synthesis?

VHDL Module
Code:
--Sin/cos lookup table. Used to generate local oscillator.
--
--Input: 17 bit vector (0 to 131071) corresponding to the range
--(0 to 2 pi) on the unit circle.
--
--Output: 2 bit sign format (-1,0,1)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity sin_cos_lut is
    port(
            input_phase : in     std_logic_vector(16 downto 0);
            cos_out         : out std_logic_vector(1 downto 0);
            sin_out         : out std_logic_vector(1 downto 0)
            );
end sin_cos_lut;

architecture behavioral of sin_cos_lut is
begin

    look_up_table : process (input_phase)
        variable input_phase_usign : unsigned (16 downto 0);
        begin
            input_phase_usign := unsigned(input_phase);
            --Sin   
            if ((input_phase_usign>=0)and(input_phase_usign<=10922)) then
                sin_out <= "00";
            elsif ((input_phase_usign>=10923)and(input_phase_usign<=54613)) then
                sin_out <= "01";
            elsif ((input_phase_usign>=54614)and(input_phase_usign<=76458)) then
                sin_out <= "00";
            elsif ((input_phase_usign>=76459)and(input_phase_usign<=120149)) then
                sin_out <= "11";
            elsif ((input_phase_usign>=120150)and(input_phase_usign<=131071)) then
                sin_out <= "00";
            else   
                sin_out <= "XX";
            end if;
            --Cos
            if ((input_phase_usign>=0)and(input_phase_usign<=21845)) then
                cos_out <= "01";
            elsif ((input_phase_usign>=21846)and(input_phase_usign<=43690)) then
                cos_out <= "11";
            elsif ((input_phase_usign>=43691)and(input_phase_usign<=87381)) then
                cos_out    <= "01";
            elsif ((input_phase_usign>=87382)and(input_phase_usign<=109226)) then
                cos_out <= "11";
            elsif ((input_phase_usign>=109227)and(input_phase_usign<=131071)) then
                cos_out <= "11";
            else
                cos_out <= "XX";
            end if;
    end process look_up_table;
   
end behavioral;

Matlab Script - scales and translates so that rounding will properly discretize sin/cos. For instance in order to discretize to [-2,-1,0,1,2] we multiply by 2 and add 2 so that our wave is in closed interval [0,4], and then subtract two after rounding.
Code:
max_phase = 2^17;
q_conv = 1; %for 3 quantization levels

fprintf('\n');

fprintf('\nsin\n0: 0 to ');
for i = 0:max_phase-1
   if (round(q_conv+q_conv*sin(2*pi*(i+1)/max_phase)) ~= round(q_conv+q_conv*sin(2*pi*(i)/max_phase)))
       fprintf('%d\n%d: %d to ',i,round(q_conv+q_conv*sin(2*pi*(i+1)/max_phase))-q_conv,i+1);
   end
end
fprintf('%d\n',max_phase-1);

fprintf('\ncos\n1: 0 to ');
for i = 0:max_phase-1
   if (round(q_conv+q_conv*cos(2*pi*(i+1)/max_phase)) ~= round(q_conv+q_conv*cos(2*pi*(i)/max_phase)))
       fprintf('%d\n%d: %d to ',i,round(q_conv+q_conv*cos(2*pi*(i+1)/max_phase))-q_conv,i+1);
   end
end
fprintf('%d\n',max_phase-1);

fprintf('\n');

Matlab Output
Code:
sin
0: 0 to 10922
1: 10923 to 54613
0: 54614 to 76458
-1: 76459 to 120149
0: 120150 to 131071

cos
1: 0 to 21845
0: 21846 to 43690
-1: 43691 to 87381
0: 87382 to 109226
1: 109227 to 131071
 
Last edited:

Generally, you can calculate tables in VHDL at compile time. I previously posted some example code how to build a table with a generate statement. Alternatively, a function can supply the constants.
https://www.edaboard.com/threads/117304/
 
Thanks, that was a really helpful example.

---------- Post added at 15:35 ---------- Previous post was at 15:28 ----------

However it occurs to me that using a ROM with so many indexes will likely use a lot of resources - in my case the LUT will be 2^17 addresses long , whereas the combinatorial comparator will not - thoughts?
 

Hi,

if what you need is an oscillator, maybe your best solution is a coupled oscillator. It requires very few resources for any frequency.
Basically, it is a second-order filter with the two poles in the unit circle.
The poles may be very slightly out of the circle (use saturation arithmetic!). In that way, the aplitude is fixed for any frequency.
In addition, it gives simultaneously cos and sin outputs (very important for complex carrier).
Look for "coupled oscillator".
Regards

Z
 

The method of performing calculations with constants is not limited to generating ROMs, it's used for it in my example. If the constants are defining the output of combinational logic, it can be minimized by the synthesis tool in the regular way.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top