alpha = arcsin( (Vout-Offset)/0.035 )
[Offset = 2.5v, Vout = 0 to 5v]
alpha = arcsin( (Data-Offset)/14.336 )
[Offset = 0x3FF, Vout = 0 to 0x7FF]
architecture behavioural of angle_lookup is
signal count: unsigned(10 downto 0) := 0;
my_array: ; -- I don't know how to intialise an array...
begin
while (count < 2047) loop
my_array(count) <= count*2; -- multiply by two - example function
count <= count +1
end loop;
value_out <= my_array(data_in);
end behavioural;
CONSTANT ROMSIZE : INTEGER := 2**(N_ADDR-1);
CONSTANT ROMMAX : INTEGER := 2**(N_WSIZE)-1;
TYPE SINTAB IS ARRAY(0 TO ROMSIZE-1) OF SIGNED (N_WSIZE-1 DOWNTO 0);
SIGNAL SINROM: SINTAB;
BEGIN
GENROM:
FOR idx in 0 TO ROMSIZE-1 GENERATE
CONSTANT x: REAL := SIN(real(idx)*2.0*MATH_PI/real(ROMSIZE));
CONSTANT xn: SIGNED(N_WSIZE-1 DOWNTO 0) := TO_SIGNED(INTEGER(x*real(ROMMAX)),N_WSIZE);
BEGIN
SINROM(idx) <= xn;
END GENERATE;
Error(29) Unknown identifier "to_unsigned"
Warning(33) Length of expected is 11; length of actual is 2048.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.math_real.all;
entity incl_lookup is
--port();
end entity;
architecture lookup of incl_lookup is
constant ROMSIZE: integer := 2048; -- length of the ROM
constant ROMWIDTH: integer := 11; -- Width of the data addresses
constant V_FACTOR: real := 14.113; -- scale factor based on sensitivity of 35mV/deg
type ROM is array(0 to ROMSIZE-1) of unsigned(ROMWIDTH-1 downto 0);
signal NL_correct: ROM;
begin
GENROM:
for i in 0 to ROMSIZE-1 generate
----------------- asin( data - 1023 / ~14.2 ) * pi/180
constant x: real := ARCSIN( ( ( (real(i) - real(ROMSIZE/2)-1.0) / V_FACTOR) ) * MATH_DEG_TO_RAD );
constant xn: unsigned(ROMSIZE-1 downto 0) := to_unsigned( round(x * MATH_RAD_TO_DEG * 10.0) + 90, ROMWIDTH);
begin
NL_correct(i) <= xn;
end generate;
end lookup;
And the warning comes bacause you have made xn the same with as the number of entries in the table (ROMSIZE), you need to make it the width of a single entry (ROMWIDTH).
Illegal type conversion from std.STANDARD.REAL to ieee.NUMERIC_STD.UNSIGNED (numeric to array)
constant xn: unsigned(ROMWIDTH-1 downto 0) := unsigned( round(x * MATH_RAD_TO_DEG * 10.0));
constant xn: unsigned(ROMWIDTH-1 downto 0) := to_unsigned( integer( round(x * MATH_RAD_TO_DEG * 10.0), ROMWIDTH ) );
Would I even need to do the round or is that something that the conversion to an integer would handle anyway?
# ** Error: ABS(X) > 1.0 in ARCSIN(X)
# Time: 0 ps Iteration: 0 Region: /incl_lookup/GENROM(0) File: C:/Documents and Settings/user/My Documents/Dropbox/FPGA things/Learnings/Inclinometer_LUT/inlc_lookup.vhd
# ** Error: (vsim-86) Arg Value -726 is out of NATURAL range 0 to 2147483647.
# Time: 0 ps Iteration: 0 Region: /incl_lookup/GENROM(0) File: C:/Documents and Settings/user/My Documents/Dropbox/FPGA things/Learnings/Inclinometer_LUT/inlc_lookup.vhd
# ** Error: ABS(X) > 1.0 in ARCSIN(X)
# Time: 0 ps Iteration: 0 Region: /incl_lookup/GENROM(1) File: C:/Documents and Settings/user/My Documents/Dropbox/FPGA things/Learnings/Inclinometer_LUT/inlc_lookup.vhd
# ** Error: (vsim-86) Arg Value -726 is out of NATURAL range 0 to 2147483647.
....etc
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity incl_lookup is
port(clk: in std_logic;
data_in : in unsigned(11 downto 0);
data_out: out unsigned(11 downto 0)
);
end entity;
architecture lookup of incl_lookup is
constant ROMSIZE: integer := 2048; -- length of the ROM
constant ROMWIDTH: integer := 12; -- Width of the data addresses
constant V_FACTOR: real := 14.113; -- scale factor based on sensitivity of 35mV/deg
type ROM is array(0 to ROMSIZE-1) of unsigned(ROMWIDTH-1 downto 0);
signal NL_func: ROM;
begin
GENROM:
for i in 0 to ROMSIZE-1 generate
----------------- asin( data - 1023 / ~14.2 ) * pi/180
constant x: real := ARCSIN( ( (real(i) - real(ROMSIZE/2)-1.0) / V_FACTOR) * MATH_DEG_TO_RAD );
constant xn: unsigned(ROMWIDTH-1 downto 0) := to_unsigned( integer((x * MATH_RAD_TO_DEG * 10.0) + 90.0), 12);
begin
NL_func(i) <= xn;
end generate;
process(clk)
begin
if rising_edge(clk) then
data_out <= NL_func( to_integer(data_in) );
end if;
end process;
end lookup;
What you'll need to do is write your own wrapper function to catch those out of range values so you dont call the arcsin function with an invalid value.
What you'll need to do is write your own wrapper function to catch those out of range values so you dont call the arcsin function with an invalid value.
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type ROM is array(0 to ROMSIZE-1) of unsigned(ROMWIDTH-1 downto 0); function init_rom return ROM is variable ret : ROM; begin for i in 0 to ROMSIZE-1 loop if i < 202 or i > 1800 then --catch the illegal values ret(i) := SOME_VALUE; else ret(i) := YOUR_CALCULATION; end if; end loop; return ret; end function init_rom; constant ARCSIN_ROM : ROM := init_rom;
I was initially going to just hard code in an array with values generated elsewhere, but this seems like a more convenient to go down at the time... how wrong I was!
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?