1

I am working on Quartus Prime, and I am having issue (on line 13) with the error:

Error (10779): VHDL error at fft_engine.vhd(154): expression is not constant

This shift to the variable k_uns is not synthesis code (as I have understood), however I have not been able to find a solution to make this work on Quartus Prime.

I have tried already doing this shift by using a 'for loop', and says the bound right should be a constant (line 25, page down):

Error (10454): VHDL syntax error at fft_engine.vhd(151): right bound of range must be a constant

I read this needs to be an integer, and its already defined as integer. I believe on Quartus II this would work, but not in Quatus Prime. Any solution for this??

1  function n2k (  
2      constant stage : integer;           -- stage number  
3      constant step  : integer;           -- butterfly block number  
4      constant nin   : integer            -- input number (0 or 1)  
5      )  
6      return integer is  
7      variable k_uns : unsigned(LOG2_FFT_LEN-1 downto 0);  
8      variable k_int : integer;  
9  
10   begin  
11     k_uns := to_unsigned(step, LOG2_FFT_LEN);  
12     if stage > 0 then  
13       k_uns(LOG2_FFT_LEN-1 downto LOG2_FFT_LEN-stage) := k_uns(LOG2_FFT_LEN-2 downto LOG2_FFT_LEN-stage-1);  
14     end if;  
15     if nin = 0 then
16      k_uns(LOG2_FFT_LEN-stage-1) := '0';
17    else
18      k_uns(LOG2_FFT_LEN-stage-1) := '1';
19    end if;
20    k_int := to_integer(k_uns);
21    return k_int;
22  end n2k;

LOG2_FFT_LEN is defined as generic at the entity:

generic (  
    LOG2_FFT_LEN : integer := 10 );  

My solution was to change the line 13 to a loop for:

25      for i in 0 to stage - 1 loop    
26          k_uns(LOG2_FFT_LEN - 1 - i) := k_uns(LOG2_FFT_LEN - 2 - i);     
27    end loop;      

When I try this, I get the following error:
Error (10454): VHDL syntax error at fft_engine.vhd(151): right bound of range must be a constant

maigipra
  • 11
  • 2
  • If this is not synthesis code, why are you trying to synthesise it? – Tricky Sep 03 '19 at 07:09
  • To only use constant bounds, you should be able to do a for loop from 0 to LOG2_FFT_LEN (-1?) and then use an IF GENERATE on i vs stage values to shift or copy. Then you cover all bits and it should work for synthesis. – B. Go Sep 04 '19 at 11:56
  • My bad, the if must be synthesized, so it must be a for generate, and a normal if ! – B. Go Sep 04 '19 at 12:04

1 Answers1

0

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:

Simulation waves under Vivado 2018.1

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”

dalex78
  • 228
  • 1
  • 8
  • Thanks for your reply. I have edited the code, since it was missing some of the function n2k, and stage_aux was something I wrote for tests. The same error is showing. Error: "expression is not constant" in the original code: `k_uns(LOG2_FFT_LEN-1 downto LOG2_FFT_LEN-stage) := k_uns(LOG2_FFT_LEN-2 downto LOG2_FFT_LEN-stage-1);` And when I change for a `loop for`, it appears the error: "right bound of range must be a constant". I did not understood what should I change to make this error go away. Can you clarify? – maigipra Sep 03 '19 at 21:43
  • Air78 thanks for your extended answer! I have tried only with the stage constant to define it as positive, and also as natural but did not work. I will try to expand this idea, andas let you know! – maigipra Sep 04 '19 at 11:44
  • No ,problem! Keep us updated, try also with `constant stage : integer range 1 to LOG2_FFT_LEN-1;` and the generic as you did. An another idea is also to not use `integer` but only `signed` or `unsigned` (except for your generics, I do not think the problem comes from the generics define as an integer). Good luck – dalex78 Sep 04 '19 at 15:09
  • Air78, good news! This has been fixed, as you suggested I tried to play with how I defined the variables, to make Quartus know that I wont be using any invalid range. I'll post the code here. – maigipra Sep 07 '19 at 15:01
  • ` variable stage_aux : unsigned(LOG2_FFT_LEN-1 downto 0); begin k_uns := to_unsigned(step, LOG2_FFT_LEN); stage_aux := to_unsigned(stage, LOG2_FFT_LEN); if stage > 0 then k_uns(LOG2_FFT_LEN-1 downto LOG2_FFT_LEN-to_integer(stage_aux)) := k_uns(LOG2_FFT_LEN -2 downto LOG2_FFT_LEN-to_integer(stage_aux) -1); end if; (......) ` – maigipra Sep 07 '19 at 15:04
  • Nice to here that ! Can you accept my solution or mark your solution by adding an other answer and accepte it ? Godd luck for the future – dalex78 Sep 09 '19 at 08:33