Trying to generate sine wave by using LUT. But, the LUT is calculated within the VHDL code as can be seen below. I do know that in VHDL it is not possible to use real. But couldnt figure out how to produce the LUT first and then use it to generate sin wave. Sure I will be able to generate sin wave once I know how to calculate the LUT dynamically in my vhdl code.
In addition, I am getting:
Error (10482):object “sin” is used but not declared
This what I have tried so far:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SineWave is
Port ( clk : in STD_LOGIC;
sine_out : out STD_LOGIC_VECTOR(7 downto 0));
end SineWave;
architecture Behavioral of SineWave is
constant TABLE_SIZE : integer := 360; -- Number of entries in the lookup table
type sine_table_type is array (0 to TABLE_SIZE-1) of integer;
signal sine_table : sine_table_type;
begin
process(clk)
variable angle : integer := 0;
constant fs : integer := 1024;
variable counter : integer := 0;
variable frequency : integer := 1; --for now setting frequency manually
begin
for i in 0 to TABLE_SIZE-1 loop
-- Calculate sine value using the formula
angle := 2 * 180* frequency * (i) * fs; -- formula = sin(2*pie*frequency* n/sampling frequency(fs))
sine_table(i) <= sin(angle); -- Convert to fixed-point format
-- report "Index: " & integer'image(i) & " Sine Value: " & integer'image(sine_table(i));
end loop;
if rising_edge(clk) then
sine_out <= sine_table[counter];
counter := counter + 1;
end if;
end process;
end Behavioral;`
There is no sin
function available for the integer data type in standard libraries, for sin
, you need to use the ieee.math_real
library.
While it is true real
type cannot be used for synthesisable logic, it can generally be used to set up elaboration time constant values. For example, a SIN LUT.
Your example is incorrect as a LUT as it is generating logic for each element of the table. Your code indicates you are trying to re-initialise the table on every clock edge (rising and falling). You simply need to assign the table to a constant and initialise it from an initialisation function, something like the following:
use ieee.numeric_std.all;
use ieee.math_real.all;
...
type sin_table_t type is array(TABLE_SIZE-1 downto 0) of signed(bitwidth-1 downto 0);
function sin_lut_init return sin_table_t is
variable angle : real;
variable sin_angle : real;
variable table : sin_table_t;
begin
for i in table'range loop
angle := MATH_PI * real(i) / real(TABLE_SIZE);
sin_angle := sin(angle);
table(i) := to_signed( integer( real( 2**bit_width ) * angle ) ), bitwidth );
end loop;
return table;
end function;
constant SIN_LUT : sin_table_t := sin_lut_init;
It seems, that you later on want to change the frequency dynamically. So you cannot store the look-up-table in a constant, but must store it in a signal. This signal will cause a very big number of flipflops, if you try to synthesize your design. To avoid this you could use another concept for calculating the sin values, for example the cordic algorithm, which does not need any lookup table.
@Tom As your
angle
is always a multiple of 360, and as you apparently represent angles in degrees, you could get rid of your table becausesin(angle)
is constant and equal to zero. Note also that floating point (real
) and fixed point (that you mention in your comments) are completely different things.