Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17268 Discussions

sin cos LUT in HEX file

Altera_Forum
Honored Contributor II
5,555 Views

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 :)
0 Kudos
16 Replies
Altera_Forum
Honored Contributor II
3,258 Views

I suspect you'll need to write a program (probably in C) for your host to generate the hex data in the required format.

0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

Where is your source from? in VHDL, you can infer a rom from a constant, and you can populate the constant from a sin/cos function.

0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

I'm using Quartus MegaWizard to generate a ROM in VHDL. I doesn't really understand what you want me to do, could you be a little more specific and explain a bit more?

0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

Have a read of this document, page 13-13: http://www.altera.co.uk/literature/hb/qts/qts_qii51007.pdf 

 

It explains how to write your VHDL code so that quartus can infer a rom without having to use the megawizard. This way you can use a custom initialisation function to populate the rom contents.
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

If you prefer to use a RAM MegaFunction with an external initialization file, it's probably convenient to use a *.mif instead of *.hex file. It's formatted text and can be easily generated in a spreadsheet calculator.

0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

 

--- Quote Start ---  

Have a read of this document, page 13-13: http://www.altera.co.uk/literature/hb/qts/qts_qii51007.pdf 

 

It explains how to write your VHDL code so that quartus can infer a rom without having to use the megawizard. This way you can use a custom initialisation function to populate the rom contents. 

--- Quote End ---  

 

 

Ok I think i understand what you mean. But when I will initiate the ROM with some sort of funktion, i will need to use some other program to do that, right? 

 

 

 

--- Quote Start ---  

If you prefer to use a RAM MegaFunction with an external initialization file, it's probably convenient to use a *.mif instead of *.hex file. It's formatted text and can be easily generated in a spreadsheet calculator. 

--- Quote End ---  

 

 

So say I use Excel to do my calculation and convert it to a *.mif file. How about the answers in the calculation? They are real numbers, will they automatic be converted?
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

 

--- Quote Start ---  

Ok I think i understand what you mean. But when I will initiate the ROM with some sort of funktion, i will need to use some other program to do that, right? 

--- Quote End ---  

Not necessarily. There is a cos function in VHDL that can be used to directly calculate the correct values. 

--- Quote Start ---  

So say I use Excel to do my calculation and convert it to a *.mif file. How about the answers in the calculation? They are real numbers, will they automatic be converted? 

--- Quote End ---  

No, you will need to use excel functions to convert them to decimal or hexadecimal first.
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

I looked at the function and I found this: 

 

TYPE ROM IS ARRAY(0 TO 511) OF UNSIGNED(8 DOWNTO 0); FUNCTION INIT_ROM RETURN ROM IS VARIABLE romvar: ROM; VARIABLE x: REAL; begin for I in 0 TO 511 loop x:= SIN(real(i)*MATH_PI/real(511)); romvar(i):=CONV_UNSIGNED(INTEGER(x*real(511)),9); end loop; return romvar; end;  

 

I think I understand how the function works but I don't understand how to interface the ROM. 

The ROM I want have the cos/sin value for 0-90 degrees with a resolution of 4096 samples.  

So do i set the array size to 0 to 4096 and the function will create a ROM of that size.  

But how do I do when I want to read a certain address?
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

have a look at the coding guidelines, as I mentioned in post# 5

0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

I have understand how the ROM works and how to interface it. Now it is the SIN function that gives me trouble.  

I have this code: 

-- Quartus II VHDL Template -- Dual-Port ROM library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; USE ieee.std_logic_arith.all; USE ieee.math_real.all; entity dual_port_rom is generic ( DATA_WIDTH : natural := 14; ADDR_WIDTH : natural := 4096 ); port ( clk : in std_logic; addr_a : in integer range 0 to 2**ADDR_WIDTH - 1; q_a : out std_logic_vector((DATA_WIDTH -1) downto 0) ); end entity; architecture rtl of dual_port_rom is subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); TYPE ROM IS ARRAY((ADDR_WIDTH-1) downto 0) OF word_t; FUNCTION INIT_ROM RETURN ROM IS VARIABLE romvar: ROM; VARIABLE x: REAL; begin for I in 0 TO 2**ADDR_WIDTH-1 loop x:= SIN(real(i)*MATH_PI/real(ADDR_WIDTH-1)); romvar(i):= std_logic_vector(to_unsigned(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 : memory_t := romvar; begin process(clk) begin if(rising_edge(clk)) then q_a <= rom(addr_a); end if; end process; end rtl;  

 

It is the same code that i posted before except that I have change to bit vectors instead of integers. But I get an error on the line: 

romvar(i):= std_logic_vector(to_unsigned(x*real(ADDR_WIDTH-1),DATA_WIDTH)); 

It say it can't determine definition of operator ""*"". 

I have tried to do some sort of workaround but I can't get it to work:  

Does anybody knows why?
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

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));
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

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?

0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

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 :)
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
3,258 Views

Thank you, it looks like it works now.

0 Kudos
Reply