Ошибка (10454): синтаксическая ошибка VHDL в fft_engine.vhd(151): правая граница диапазона должна быть константой

Я работаю над Quartus Prime, и у меня возникла проблема (в строке 13) с ошибкой:

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

Этот переход к переменной k_uns не является кодом синтеза (как я понял), однако я не смог найти решение, чтобы заставить это работать на Quartus Prime.

Я уже пытался сделать этот сдвиг, используя цикл for, и сказал, что связанное право должно быть константой (строка 25, страница вниз):

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

Я читал, что это должно быть целое число, и оно уже определено как целое число. Я считаю, что на Quartus II это сработает, но не на Quatus Prime. Любое решение для этого ??

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 определяется как общий для объекта:

generic (  
    LOG2_FFT_LEN : integer := 10 );  

Мое решение состояло в том, чтобы изменить строку 13 на цикл для:

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;      

Когда я пытаюсь это сделать, я получаю следующую ошибку:
Ошибка (10454): синтаксическая ошибка VHDL в fft_engine.vhd(151): правая граница диапазона должна быть константой


person maigipra    schedule 03.09.2019    source источник
comment
Если это не код синтеза, почему вы пытаетесь его синтезировать?   -  person Tricky    schedule 03.09.2019
comment
Чтобы использовать только постоянные границы, вы должны иметь возможность выполнить цикл for от 0 до LOG2_FFT_LEN (-1?), а затем использовать IF GENERATE для значений i vs stage для сдвига или копирования. Затем вы покрываете все биты, и это должно работать для синтеза.   -  person B. Go    schedule 04.09.2019
comment
Плохо, что if нужно синтезировать, так что это должен быть for generate и нормальный if !   -  person B. Go    schedule 04.09.2019


Ответы (1)


Ваша функция не использует переменную k_int и константы stage_aux и nin (которые могут выводить предупреждение во время моделирования или синтеза) и не возвращает целое число (это дает ошибку в Vivado 2018.1).

Если вы добавите предложение return, код имитируется, как и ожидалось, и синтез также работает в vivado 2018.1. (код синтезируется)

Если у вас все еще есть проблема, уточните, какой строке кода соответствуют 2 ошибки, которые вы написали выше.

Обратите внимание, что в моем коде я тестировал, когда LOG2_FFT_LEN является общим или целым числом, и это не имело значения.

EDIT Итак, я обновил свой код для моделирования, у меня есть это:

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;

Под Vivado 2018.1 симулирует отлично и все как положено:

Имитация волн в Vivado 2018.1

Кроме того, ваша функция полностью синтезируема, она работает на vivado 2018.1. Я также сделал это.

Следовательно, я считаю, что ваша проблема связана не с синтаксисом VHDL, а с инструментальной проблемой (проблема Quartus).

Я не могу подтвердить вам это, так как у меня нет квартуса и я никогда его не использовал, но я провел некоторое исследование: похоже, ваша проблема связана с ограничением синтеза. Вы должны показать компилятору, что константа stage и общий LOG2_FFT_LEN не могут принимать значения, которые привели бы к недопустимому диапазону.

Например, если stage принимает значение -20 (он может принимать это значение, так как является целым числом), то остальная часть вашего кода не будет работать должным образом.

Итак, если это проблема, измените способ объявления своих констант/дженериков:

LOG2_FFT_LEN : POSITIVE := 10  --generic

Ключевое слово POSITIVE является подтипом integer:

type Positive is Integer range 1 to Integer'high;

Для вас постоянно:

constant stage : integer range 1 to LOG2_FFT_LEN-1;  -- stage number 

Если это все еще не работает, попробуйте распространить эту идею на другие ваши константы/сигналы/переменные. Если ничего не изменится, то можете ли вы уточнить, что именно вы сделали? Симуляция работает так, как вы ожидаете? Это не удается? Не получается только часть синтеза?

Обратите внимание, что обе ваши функции работают нормально (для меня), но первая (без цикла) лучше/красивее, чем вторая. Вы должны придерживаться его.

Вот несколько ссылок людей, у которых была аналогичная ошибка:

выражение VHDL не является константой

vhdl "выражение не является постоянным"

person dalex78    schedule 03.09.2019
comment
Спасибо за ответ. Я отредактировал код, так как в нем отсутствовали некоторые функции n2k, а stage_aux я написал для тестов. Та же ошибка показывает. Ошибка: выражение не является константой в исходном коде: k_uns(LOG2_FFT_LEN-1 downto LOG2_FFT_LEN-stage) := k_uns(LOG2_FFT_LEN-2 downto LOG2_FFT_LEN-stage-1); И когда я меняю на loop for, появляется ошибка: правая граница диапазона должна быть константой. Я не понял, что я должен изменить, чтобы эта ошибка исчезла. Вы можете уточнить? - person maigipra; 04.09.2019
comment
Air78 спасибо за развернутый ответ! Я пытался только с константой стадии определить ее как положительную, а также как естественную, но не получилось. Я постараюсь расширить эту мысль, и как дам вам знать! - person maigipra; 04.09.2019
comment
Без проблем! Держите нас в курсе, попробуйте также с constant stage : integer range 1 to LOG2_FFT_LEN-1; и дженериком, как вы это сделали. Другая идея также состоит в том, чтобы не использовать integer, а только signed или unsigned (за исключением ваших дженериков, я не думаю, что проблема возникает из-за того, что дженерики определяют как целое число). Удачи - person dalex78; 04.09.2019
comment
Air78, хорошие новости! Это было исправлено, как вы предложили, я попытался поиграть с тем, как я определил переменные, чтобы Quartus знал, что я не буду использовать какой-либо недопустимый диапазон. Я опубликую код здесь. - person maigipra; 07.09.2019
comment
` переменная stage_aux : без знака (LOG2_FFT_LEN-1 до 0); начать k_uns := to_unsigned (шаг, LOG2_FFT_LEN); stage_aux: = to_unsigned (этап, LOG2_FFT_LEN); если этап › 0, то k_uns(LOG2_FFT_LEN-1 до LOG2_FFT_LEN-to_integer(stage_aux)) := k_uns(LOG2_FFT_LEN -2 до LOG2_FFT_LEN-to_integer(stage_aux) -1); закончить, если; (......) ` - person maigipra; 07.09.2019
comment
Приятно вот что! Можете ли вы принять мое решение или отметить свое решение, добавив другой ответ и приняв его? Удачи богу в будущем - person dalex78; 09.09.2019