Testbench возвращает неопределенные значения в Modelsim - PullRequest
0 голосов
/ 08 мая 2020

Я кодирую генератор паттернов на VHDL. Я закончил его недавно, но теперь у меня проблема с тестовым стендом.

Мой код:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;

entity pattern_gen is
    Port ( 
    clk_i : in STD_LOGIC;-- 100Mhz clock on Basys 3 FPGA board

    x : in INTEGER;
    y: in INTEGER;
    modus : in STD_LOGIC;
    enable : in STD_LOGIC;

    red : out STD_LOGIC_VECTOR(3 downto 0);
    green : out STD_LOGIC_VECTOR(3 downto 0);
    blue : out STD_LOGIC_VECTOR(3 downto 0)
    );
end pattern_gen;

architecture Behavioral of pattern_gen is
    signal segment_x : integer := 0;
    signal segment_y : integer := 0;

begin
    stripes : PROCESS(modus, segment_x, x, clk_i)
    BEGIN
        IF( clk_i'EVENT and clk_i = '1') then
            IF(modus = '0' AND enable = '1' ) THEN        --Mod 0 -> Stripes enabled
                    IF(x < (40+ (160*(segment_x-1)))) THEN
                        red <= (OTHERS => '1');
                        green  <= (OTHERS => '0');
                        blue <= (OTHERS => '0');
                    ELSE IF(x < (80+ (160*(segment_x-1)))) THEN
                        red <= (OTHERS => '0');
                        green  <= (OTHERS => '1');
                        blue <= (OTHERS => '0');
                        ELSE IF(x < (120+ (160*(segment_x-1)))) THEN
                            red <= (OTHERS => '0');
                            green  <= (OTHERS => '0');
                            blue <= (OTHERS => '1');
                            ELSE IF(x < (160+ (160*(segment_x-1)))) THEN
                                red <= (OTHERS => '0');
                                green  <= (OTHERS => '0');
                                blue <= (OTHERS => '0');
                            END IF;
                        END IF;
                    END IF;
                END IF;
            END IF;
        end if;
    END PROCESS;

    panels: PROCESS(modus, segment_x, segment_y, clk_i)
    variable i: integer range -10 to 100;
    BEGIN
        IF(clk_i'EVENT and clk_i = '1') then 
            IF(modus = '1' AND enable = '1' ) THEN        --Mod 1 -> Panels enabled
                    i := segment_x*segment_y;

                    while (i>0) loop
                        IF (i = 1) then
                            red <= (OTHERS => '1');
                            green  <= (OTHERS => '0');
                            blue <= (OTHERS => '0');
                        else if(i = 2) then
                            red <= (OTHERS => '0');
                            green  <= (OTHERS => '1');
                            blue <= (OTHERS => '0');
                            else if(i=3) then
                                red <= (OTHERS => '0');
                                green  <= (OTHERS => '0');
                                blue <= (OTHERS => '1');
                                end if;
                            end if;
                        end if;

                        i := i - 3;

                    end loop;
            END IF;
        END IF;
    END PROCESS;

    segment: PROCESS(x, y, modus, clk_i)
    variable i: integer range 0 to 10;
    BEGIN
        if(clk_i'EVENT and clk_i = '1') then
            IF(modus = '0' AND enable = '1') THEN
                i := 1;
                while i<=4 loop
                    IF(x < (i * 160))then
                        segment_x <= i;
                        exit;
                    END IF;
                    i := i +1;
                END loop;
            ELSIF (modus = '1' AND enable = '1') THEN --Mod 1 -> Panels enabled
                i:=1; --reset i for horizintal segment 
                while i<=10 loop
                    IF(x < (i * 64))then
                        segment_x <= i;
                        exit;
                    END IF;
                    i := i +1;
                end loop;
                i:=1; --reset i for vertical segment
                while i<=10 loop
                    IF(y < (i * 48)) then
                        segment_y <= i;
                        exit;
                    end if;
                    i := i +1;
                end loop;   
            END IF;
        end if; 
     END PROCESS;
end Behavioral;

Тестовая среда очень короткая, я просто хочу протестировать несколько случаев.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
entity pattern_gen_tb is

end entity;

architecture sim of pattern_gen_tb is
component pattern_gen
   Port ( 
    clk_i : in STD_LOGIC;

    x : in INTEGER;
    y: in INTEGER;
    modus : in STD_LOGIC;
    enable : in STD_LOGIC;

    red : out STD_LOGIC_VECTOR(3 downto 0);
    green : out STD_LOGIC_VECTOR(3 downto 0);
    blue : out STD_LOGIC_VECTOR(3 downto 0)
    );
end component;

signal clk_s : STD_LOGIC := '0';

signal x_s : INTEGER;
signal y_s : INTEGER;
signal modus_s : std_logic;
signal enable_s : std_logic;

signal red_s : STD_LOGIC_VECTOR(3 downto 0);
signal green_s :STD_LOGIC_VECTOR(3 downto 0);
signal blue_s : STD_LOGIC_VECTOR(3 downto 0);

begin
    uut : pattern_gen
    port map(
        clk_i => clk_s,

        x => x_s,
        y => y_s,
        modus => modus_s,
        enable => enable_s,

        red => red_s,
        green => green_s,
        blue => blue_s
        );
    clk_s  <= not clk_s after 10 ns;

 p_test : process
 begin
    x_s <= 44; 
    y_s<= 300;
    modus_s <= '0';
    enable_s <= '1'; -- result should be green(1,1,1,1)

    wait; 

end process;

end sim;

Результат моделирования не определен даже хотя сегмент вычисляется правильно, и второй оператор If должен сработать, потому что 44 <(80 + 160 * (1-1)), поэтому выход должен быть </p>

сегмент 1 и полоса 2 -> зеленый (1,1, 1,1) красный и синий (0,0,0,0)

Results of Simulation

Что мне не хватает? Я уже несколько часов пытаюсь заставить его работать.

1 Ответ

1 голос
/ 09 мая 2020

Вы управляете красным, зеленым и синим цветом от нескольких процессов.

После поиска по текущим 152 сообщениям по нескольким драйверам не было ни одного опубликованного вопроса с ответом, который бы адекватно объяснял, почему и как вы возвращаетесь ' U (или в некоторых случаях X).

IEEE Std 1076-2008
14.7 Выполнение модели
14.7.2 Драйверы

Каждый оператор назначения сигнала в оператор процесса определяет набор драйверов для определенных скалярных сигналов. Существует единственный драйвер для данного скалярного сигнала S в операторе процесса при условии, что в этом операторе процесса есть хотя бы один оператор назначения сигнала и что самый длинный префикс stati c целевого сигнала этого оператора назначения сигнала обозначает S или обозначает составной сигнал, подэлементом которого является S. Каждый такой оператор присвоения сигнала называется связанным с этим драйвером. Выполнение оператора назначения сигнала влияет только на соответствующий драйвер (ы).

14.7.3.2 Управляющие значения

> Управляющее значение любого сигнала S определяется следующими шагами:

...
e) Если S является базовым c сигналом:

...
- Если S является разрешенный сигнал и имеет один или несколько источников, затем исследуются управляющие значения источников S. ... управляющее значение S получается путем выполнения функции разрешения, связанной с S, где эта функция вызывается с входным параметром, состоящим из конкатенации управляющих значений источников S, за исключением значения любого источник S, текущее значение которого определяется нулевой транзакцией.

Как работает эта функция разрешения, описано в 14.7.3.2 Привод значений.

тип или подтип std_logic_vector (-2008) - это разрешенный составной тип или sutype с разрешенным типом элемента (-2008), который использует функцию разрешения для его элементов, предоставленных в пакете IEEE std_logic_1164, тело пакета:

  -------------------------------------------------------------------
  -- resolution function
  -------------------------------------------------------------------
  constant resolution_table : stdlogic_table := (
    --      ---------------------------------------------------------
    --      |  U    X    0    1    Z    W    L    H    -        |   |
    --      ---------------------------------------------------------
             ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'),  -- | U |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'),  -- | X |
             ('U', 'X', '0', 'X', '0', '0', '0', '0', 'X'),  -- | 0 |
             ('U', 'X', 'X', '1', '1', '1', '1', '1', 'X'),  -- | 1 |
             ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X'),  -- | Z |
             ('U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X'),  -- | W |
             ('U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X'),  -- | L |
             ('U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X'),  -- | H |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X')   -- | - |
             );

  function resolved (s : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    variable result : STD_ULOGIC := 'Z';  -- weakest state default
  begin
    -- the test for a single driver is essential otherwise the
    -- loop would return 'X' for a single driver of '-' and that
    -- would conflict with the value of a single driver unresolved
    -- signal.
    if (s'length = 1) then return s(s'low);
    else
      for i in s'range loop
        result := resolution_table(result, s(i));
      end loop;
    end if;
    return result;
  end function resolved;

Одно за другим каждое значение драйвера сравнивается с разрешенным значением предыдущих драйверов, чтобы определить разрешенное значение, включая каждый новый драйвер.

Обновление сигнала выполняется элементом из-за характеристики c, известной как самая длинная статистика c префикс (8. Имена), где используются индексированные имена (8.4) или имена срезов ( 8.5) привязывают детализацию драйверов для составных массивов к элементам (что также соответствует определению подэлементов). (Присваивания элементам записей содержат драйверы для всех элементов композиции записи и любых подэлементов. См. Раздел 8.3. Выбранные имена. У записей нет подмножеств элементов.)

Разрешение нескольких драйверов имитирует то, что происходит, когда два выхода связаны вместе. Связывание нескольких выходов вместе может быть нарушением проектных ограничений в инструментах синтеза FPGA, например, для внутренних цепей.

В вашем проекте у вас есть назначения для драйверов в нескольких процессах (и параллельные операторы также предоставляют операторы процесса).

Два процесса не влияют ни на какое назначение красного, зеленого или синего в зависимости от значения режима, которое не обновляется. Разрешение «U» с любым другим значением std_ulogi c приводит к «U».

Если ваша тестовая среда вызвала присвоение красного, зеленого или синего цвета более чем в одном процессе, то «0» для один драйвер скалярных элементов в одном процессе будет преобразован с «1» от другого драйвера к «X».

Многие целевые семейства устройств не позволяют внутренним сигналам иметь несколько источников (драйверов) . Это довольно часто встречается, например, в ПЛИС (в то время как Xilinx поддерживает автоматическое c преобразование нескольких взаимно исключающих друг друга источников для преобразования в источники, выбранные мультиплексором, с помощью процесса, запатентованного программным обеспечением для некоторых семейств устройств).

Одним из решений ограничения синтеза для нескольких драйверов может быть объединение первых двух процессов в один, при этом назначения разделяются условным выбором значений режима.

Другим решением может быть присвоение уникальных сигналов в каждом процессе и присвоение этим значениям красного, зеленого и синего цветов в другом процессе, управляемом значением модуса (эмуляция патента на программное обеспечение вручную, что также должно вызывать сомнения это действительность).

Хотя циклы исторически не приемлемы для синтеза, в то время как для циклов с фиксированным диапазоном l oop параметры всегда поддерживались. Сегодня некоторые инструменты синтеза поддерживают циклы while, в которых условие выхода может быть определено с помощью относительно небольшого числа l oop итераций. (Циклы разворачиваются в синтезе.) По крайней мере, один из ваших циклов while, вероятно, потребует переписывания реализуемого алгоритма.

...