Неожиданный вывод функции при отрицании параметра функции - PullRequest
2 голосов
/ 14 марта 2019

У меня есть функция кодирования приоритета, которая возвращает вектор, содержащий 1 в позиции, где первый 1 найден во входном векторе. Функция работает, как и ожидалось, если я не пытаюсь свести на нет входной вектор. Вот пример, который демонстрирует неожиданное поведение:


LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

entity tb IS
end tb;

architecture run of tb is
    constant N : natural := 5;

    function get_first_one_in_vec (vec_in: std_logic_vector) return std_logic_vector is
        variable ret: std_logic_vector(vec_in'high downto vec_in'low);
    begin
        ret := (others => '0');
        for i in vec_in'low to vec_in'high loop
            if vec_in(i)='1' then
                ret(i) := '1';
                exit;
            end if;
        end loop;

        return ret;
    end get_first_one_in_vec;

    signal a            : std_logic_vector(N-1 downto 0);
    signal abar         : std_logic_vector(N-1 downto 0);

    signal first_a      : std_logic_vector(N-1 downto 0);
    signal first_nota   : std_logic_vector(N-1 downto 0);
    signal first_abar   : std_logic_vector(N-1 downto 0);
begin
    process
    begin
        a <= "10100";
        wait for 10 ns;
        a <= "01011";
        wait for 10 ns;
        wait;
    end process;

    abar        <= not(a);
    first_a     <= get_first_one_in_vec(a);
    first_nota  <= get_first_one_in_vec(not(a));
    first_abar  <= get_first_one_in_vec(abar);

end run;

Насколько я понимаю, first_nota должно совпадать с first_abar. Однако мой симулятор (ModelSim - Intel FPGA Starter Edition 10.5b, версия 2016.10) считает иначе, как вы можете видеть здесь:

enter image description here


Что мне здесь не хватает?

1 Ответ

3 голосов
/ 14 марта 2019

Это работает нормально:

function get_first_one_in_vec (vec_in: std_logic_vector) return std_logic_vector is
    variable ret: std_logic_vector(vec_in'length downto 1);
    variable inp: std_logic_vector(vec_in'length downto 1) := vec_in;
begin
    ret := (others => '0');
    for i in inp'right to inp'left loop
        if inp(i)='1' then
            ret(i) := '1';
            exit;
        end if;
    end loop;

    return ret;
end get_first_one_in_vec;

https://www.edaplayground.com/x/3zP_

Почему у вас не работает?Хорошо, когда вы вызываете вашу функцию с оператором not как часть выражения:

first_nota  <= get_first_one_in_vec(not a);

нумерация входа функции изменяется на 1 to с помощью оператора not.Зачем?Вот код оператора not, и вы можете понять, почему:

-------------------------------------------------------------------    
-- not
-------------------------------------------------------------------    
FUNCTION "not"  ( l : std_logic_vector ) RETURN std_logic_vector IS
    -- pragma built_in SYN_NOT
-- pragma subpgm_id 204
    --synopsys synthesis_off
    ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
    VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X');
    --synopsys synthesis_on
BEGIN
    --synopsys synthesis_off
    FOR i IN result'RANGE LOOP
        result(i) := not_table( lv(i) );
    END LOOP;
    RETURN result;
    --synopsys synthesis_on
END;
---------------------------------------------------------------------

В любом случае, это нарушает ваш код (который начинает сканирование с другого конца слова).

Один из способов сделать функцию независимой от порядка нумерации ее входов - это нормализовать входы следующим образом:

variable inp: std_logic_vector(vec_in'length downto 1) := vec_in;

Как только вы это сделаете, вы все контролируете.Таким образом, вместо циклов из 'high downto 'low, мы можем быть более явными и циклически из 'right to 'left:

for i in inp'right to inp'left loop

  • not является оператором , а не функцией .Вам не нужны скобки.
...