Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

sin cos LUT in HEX file

Hello,

I'm need to load a ROM with a cos and sin lookup table. I know Quartus have an auto fill cell function built in but does it support sin and cos? Or does I need a 3d-party program to do that? Also, how do I convert the cos answer to HEX/BIN? For example cos(25)= 0,9063 how do I translate that to HEX?

Thanks for your answer :)

16 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    first of all, remove the line "use ieee.std_logic_arith.all"

    It is non-standard and conflicts with numeric_std.

    Second, you cannot convert a real type to an unsigned type, you need to convert it to integer first:

    romvar(i):= std_logic_vector(to_unsigned( integer(x*real(ADDR_WIDTH-1)) ,DATA_WIDTH));
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you that helped. But now when I run the simulation the output only differs on the 4 MSb the rest are zero. I want an output of 12-14 bit resolution. How do I get that?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I assume you must have changed the code to run a simulation, as there are many syntax errors.

    Once I fixed them, it has populated the ROM correctly, with all bits used.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Ooo sorry yes I have change it to work and add some calculations so the value 0-4096 represent 0-90 degrees. When I run the simulation I get the max value of 00000000000110.

    Here is the code I use for simulation:

    
    -- Quartus II VHDL Template
    -- Dual-Port ROM
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    USE ieee.math_real.all;
    entity LUT_ROM is
    	generic 
    	(
    		DATA_WIDTH : natural := 14;
    		ADDR_WIDTH : natural := 12
    	);
    	port 
    	(
    		clk		: in std_logic;
    		addr_a	: in natural range 0 to 2**ADDR_WIDTH - 1;
    		q_a		: out std_logic_vector((DATA_WIDTH -1) downto 0)
    	);
    end entity;
    architecture rtl of LUT_ROM is
    	subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
    	TYPE ROM IS ARRAY((2**ADDR_WIDTH-1) downto 0) OF word_t;
    	FUNCTION INIT_ROM RETURN ROM IS
    	VARIABLE romvar: ROM;
    	VARIABLE x, i: REAL;
    	
    	begin
    	  for samp in 0 TO 2**ADDR_WIDTH-1 loop
    		 i := real(0.02197)*real(samp)*MATH_PI/real(180);
    		 x:= SIN(real(i)*MATH_PI/real(ADDR_WIDTH-1));
    		 romvar(samp):= std_logic_vector(to_unsigned(integer(x*real(ADDR_WIDTH-1)),DATA_WIDTH));
    	  end loop;
    	  return romvar;
    	end;
    	-- Declare the ROM signal and specify a default value.	Quartus II
    	-- will create a memory initialization file (.mif) based on the 
    	-- default value.
    	signal rom_val : ROM := INIT_ROM;
    begin
    	process(clk)
    	begin
    	if(rising_edge(clk)) then
    		q_a <= rom_val(addr_a);
    	end if;
    	end process;
    end rtl;
    

    Thank you for your help :)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I would recomend making rom_val a constant rather than a signal - its never going to be updated, so needs to be a constant really.

    But your error is because you put ADDR_WIDTH in the init_rom, rather than 2**ADDR_WIDTH.