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.

VHDL SINE LUT using type "real"

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
Hello,

I'm trying to design a generic synthesizable SINE LUT in VHDL.
I'm using the "real" type to compute the LUT's values during compile time.

This is my code:

Code:
library ieee ;
	use ieee.std_logic_1164.all ;
	use ieee.numeric_std.all ;
	use ieee.math_real.all ;
 
entity sine_lut is

generic
(
    WIDTH_FRACTION_ANGLE    : natural := 4  ; -- 4 gives us a resolution of 1/16
    WIDTH_FRACTION_RESULT   : natural := 10 
) ;

port 
(
	IN_CLOCK    :   in  std_logic                                                   ;																		    
	IN_ANGLE    :   in  std_logic_vector ( 7 + WIDTH_FRACTION_ANGLE - 1 downto 0 )  ;   -- 90 is 1011010 ( 7 bits ). A sign bit isn't needed ( the user shall exploit the sine symmetry ).	     
            
	OUT_RESULT  :   out std_logic_vector ( WIDTH_FRACTION_RESULT downto 0 )             -- One integer bit + WIDTH_FRACTION_RESULT
) ; 
    
end entity sine_lut ;

architecture rtl_sine_lut of sine_lut is 

type type_lut_sine_real     is array ( 0 to 2 ** ( IN_ANGLE ' length ) - 1 ) of real ;
type type_lut_sine_slv      is array ( 0 to 2 ** ( IN_ANGLE ' length ) - 1 ) of std_logic_vector ( OUT_RESULT ' range ) ;

[COLOR="#FF0000"]signal lut_sine_real    : type_lut_sine_real ;
signal lut_sine_slv     : type_lut_sine_slv ;[/COLOR]

begin 

    generate_sine_lut : for index in 0 to 2 ** ( IN_ANGLE ' length ) - 1
    generate 
                
        lut_sine_real ( index ) <= sin ( real ( index ) * ( MATH_PI / 180.0 ) / ( real ( 2 ** WIDTH_FRACTION_ANGLE ) ) ) ;  -- Multiplying by ( MATH_PI / 180.0 ) converts from degrees to radians. 
        lut_sine_slv ( index )  <= std_logic_vector ( to_unsigned ( integer ( lut_sine_real ( index ) * ( real ( 2 ** WIDTH_FRACTION_RESULT ) ) ) , OUT_RESULT ' length ) ) ;  
    
    end generate ;

    reading_from_memory : process ( IN_CLOCK ) is
    begin 
        if rising_edge ( IN_CLOCK ) then 
            OUT_RESULT <= lut_sine_slv ( to_integer ( unsigned ( IN_ANGLE ) ) ) ;
        end if ;
    end process reading_from_memory ;
 
end architecture rtl_sine_lut ;

Unfortunately,
Quartus can't synthesize type "real" for arguments that are defined as signals. The following error is shown:
Error (10414): VHDL Unsupported Feature error at sine_lut.vhd(29): cannot synthesize non-constant real objects or values
But if I define the arrays as constants I can't use the neat "for loop" method to instantiate their values.

How can I work around this problem ?
 

Yes you can - define it all in an initialisation function:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
constant sin_rom : type_lut
 
function define_rom return type_lut_sine_slv is
  variable ret_rl : type_lut_sine_real;
  variable ret : type_lut_sine_slv;
begin
  for index in ret'range loop
    ret_rl( index ) := sin ( real ( index ) * ( MATH_PI / 180.0 ) / ( real ( 2 ** WIDTH_FRACTION_ANGLE ) ) ) ;  -- Multiplying by ( MATH_PI / 180.0 ) converts from degrees to radians. 
    ret ( index )  := std_logic_vector ( to_unsigned ( integer ( lut_sine_real ( index ) * ( real ( 2 ** WIDTH_FRACTION_RESULT ) ) ) , OUT_RESULT ' length ) ) ;  
  end loop;
end function;
 
constant rom : type_lut_sine_slv := define_rom;



Please put cheque in the post!
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top