- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 :)Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I suspect you'll need to write a program (probably in C) for your host to generate the hex data in the required format.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
have a look at the coding guidelines, as I mentioned in post# 5
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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));- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 :)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you, it looks like it works now.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page