Your function does not use the variable k_int
and the constants stage_aux
and nin
(which might output a warning during simulation or synthesis) and does not return an integer (this gives an error under Vivado 2018.1).
If you add the return
clause, the code simulates as expected and the synthesis also work under vivado 2018.1. (the code is synthetisable)
If you still have your problem, precise to which line in the code correspond the 2 errors you wrote above.
Note that in my code, I have tested with LOG2_FFT_LEN
being a generic or an integer and it made no difference.
EDIT
Ok, so I have updated my code, for simulation purpose, I have this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fft_engine_tb is
generic(
LOG2_FFT_LEN : integer := 10
);
end entity;
architecture Behavioral of fft_engine_tb is
signal clk : std_logic := '1'; --the clock (not used, only to see it in the simulation waves)
constant period : time := 8us; --the clock period
constant half_period : time := 4us; --the half period of the clock
signal int_return : integer := 0;
signal int_return_loop : integer := 0;
begin
--the generation of the clock
clk <= not clk after half_period;
--process that call your function
process
--definition of your second function (the pure keyword is optionnal)
function n2k (
constant stage : integer; -- stage number
constant step : integer; -- butterfly block number
constant nin : integer -- input number (0 or 1)
)
return integer is
variable k_uns : unsigned(LOG2_FFT_LEN-1 downto 0);
variable k_int : integer;
begin
k_uns := to_unsigned(step, LOG2_FFT_LEN);
if stage > 0 then
k_uns(LOG2_FFT_LEN-1 downto LOG2_FFT_LEN-stage) := k_uns(LOG2_FFT_LEN-2 downto LOG2_FFT_LEN-stage-1);
end if;
if nin = 0 then
k_uns(LOG2_FFT_LEN-stage-1) := '0';
else
k_uns(LOG2_FFT_LEN-stage-1) := '1';
end if;
k_int := to_integer(k_uns);
return k_int;
end function;
--definition of your second function with the loop (the pure keyword is optionnal)
function n2k_with_loop (
constant stage : integer; -- stage number
constant step : integer; -- butterfly block number
constant nin : integer -- input number (0 or 1)
)
return integer is
variable k_uns : unsigned(LOG2_FFT_LEN-1 downto 0);
variable k_int : integer;
begin
k_uns := to_unsigned(step, LOG2_FFT_LEN);
if stage > 0 then
for i in 0 to stage - 1 loop
k_uns(LOG2_FFT_LEN - 1 - i) := k_uns(LOG2_FFT_LEN - 2 - i);
end loop;
end if;
if nin = 0 then
k_uns(LOG2_FFT_LEN-stage-1) := '0';
else
k_uns(LOG2_FFT_LEN-stage-1) := '1';
end if;
k_int := to_integer(k_uns);
return k_int;
end function;
begin
wait for period;
int_return <= n2k( 2, 2, 0); --We expect 2
int_return_loop <= n2k_with_loop( 2, 2, 0); --We expect 2
wait for period;
int_return <= n2k( 2, 2, 1); --We expect 130
int_return_loop <= n2k_with_loop( 2, 2, 1); --We expect 130
wait for period;
int_return <= n2k( 5, 1023, 0); --We expect 1007
int_return_loop <= n2k_with_loop( 5, 1023, 0); --We expect 1007
wait for period;
int_return <= n2k( 5, 1023, 1); --We expect 1023
int_return_loop <= n2k_with_loop( 5, 1023, 1); --We expect 1023
wait for period;
int_return <= n2k( 5, 682, 0); --We expect 330
int_return_loop <= n2k_with_loop( 5, 682, 0); --We expect 330
wait for period;
int_return <= n2k( 5, 682, 1); --We expect 346
int_return_loop <= n2k_with_loop( 5, 682, 1); --We expect 346
wait for period;
int_return <= n2k( 1, 682, 0); --We expect 170
int_return_loop <= n2k_with_loop( 1, 682, 0); --We expect 170
wait for period;
int_return <= n2k( 1, 682, 1); --We expect 426
int_return_loop <= n2k_with_loop( 1, 682, 1); --We expect 426
wait;
end process;
end architecture;
Under Vivado 2018.1, it simulates perfectly and everything is as expected:

Furthermore, your function is entirely synthetizable, it works on vivado 2018.1. I have also done it.
Consequently, I believe your problem is not a VHDL syntax problem but a tool problem (a Quartus problem).
I cannot confirm you this as I do not have quartus and never used it, but I have done some research: it seems that your issue comes from a synthesis restriction. You have to show to the compiler that the constant stage
and the generic LOG2_FFT_LEN
can not take values that would result in an invalid range.
For example, if stage
takes the value -20
(it can take this value as it is an integer) then the rest of your code won't work as expected.
So, if that is the problem, change the way you declare your constant/generics:
LOG2_FFT_LEN : POSITIVE := 10 --generic
The POSITIVE
keyword is a subtype of the integer
:
type Positive is Integer range 1 to Integer'high;
For you constant:
constant stage : integer range 1 to LOG2_FFT_LEN-1; -- stage number
If it still does not work, try to expand this idea to your other constants/signals/variables. If nothing changes, then, can you precise, what have you done exactly ? Does the simulation work as you expect ? Does it fail ? Is it only the synthezis part that fail ?
Note that both of your function works fine (to me) but the first one (without the loop) is better/more beautiful than the second one. You should stick with it.
Here are some links of people that had a similar error:
VHDL expression is not constant
vhdl “expression is not constant”