cbeighley
Newbie level 2
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
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.
Matlab Output
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: