GHDL зависает запущенный тестовый стенд


При тестировании простой реализации game of life в VHDL, имитация GHDL пустого тестового стенда зависает со 100% использованием процессора, после распечатки сообщения "конец теста".

Вот код:

----- Package ------------------------------
library ieee;
use ieee.std_logic_1164.all;

package data_types is
    type array2D is array (0 to 10, 0 to 10) of std_logic;
end data_types;


----- Main Code ----------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.data_types.all;

entity de0 is
    port (matrix : inout array2D);
end de0;


architecture life of de0 is

    -- Return the integer value of a cell, treating all out of bounds as 0
    function cellValue (matrix : array2D; x, y : integer) return integer is 
    begin
        if (y < 0 or y > matrix'high(1) or x < 0 or x > matrix'high(2) or matrix(y, x) = '0') then
            return 0;
        else
            return 1;
        end if;
    end cellValue;

begin

    -- Iterate over all cells
    row: for y in matrix'range(1) generate
        column: for x in matrix'range(2) generate

            process

                variable neighbours : integer := cellValue(matrix, x - 1, y - 1) +
                                                cellValue(matrix, x - 1, y) +
                                                cellValue(matrix, x - 1, y + 1) +
                                                cellValue(matrix, x, y - 1) +
                                                cellValue(matrix, x, y + 1) +
                                                cellValue(matrix, x + 1, y - 1) +
                                                cellValue(matrix, x + 1, y) +
                                                cellValue(matrix, x + 1, y + 1);

            begin

                -- Update the cell value according to the game of life rules
                if (neighbours = 2 or neighbours = 3) then
                    matrix(y, x) <= '1';
                else
                    matrix(y, x) <= '0';
                end if;

            end process;

        end generate;
    end generate;

end life;

И тестовый стенд:

library ieee;
use ieee.std_logic_1164.all;
use work.data_types.all;

entity life_tb is
end life_tb;

architecture behaviour of life_tb is
    component life
        port (matrix : inout array2D);
    end component;

    for test: life use entity work.de0;
    signal matrix : array2D;

begin

    test: life port map (matrix => matrix);

    process
    begin
            assert false
                report "End of test" severity note;

            wait;

    end process;
end behaviour;
2 2

2 ответа:

Процесс в жизни de0 не имеет ни списка чувствительности, ни оператора ожидания, поэтому этот процесс будет выполняться вечно, просто выполняя операторы в процессе в бесконечном цикле в то же время моделирования, и моделирование, следовательно, не остановится.

Это можно исправить, добавив список чувствительности (matrix) или ожидание с некоторым условием.

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

Матрица размещения-это список чувствительности немеченого процесса в de0 (life)

            process (matrix)

Дает:

ghdl -a de0.vhdl
ghdl -a life_tb.vhdl
ghdl -e life_tb
ghdl -r life_tb
life_tb.vhdl:22:13:@0ms:(assertion note): End of test

Тест утверждения выполняется только один раз и немедленно, он не сигнализирует о завершении теста.

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

Добавление часов к моделированию:

В декларативной области архитектуры мы объявляем тактовый сигнал:

    signal clk: std_logic;

Вы можете добавить новый процесс для создания часов в вашем тестовом стенде (life_tb.vhdl):

CLOCK:
    process 
    begin
        wait for 10 ns;
        clk <= '0';
        wait for 10 ns;
        clk <= '1';
    end process;
Он имеет период 20 НС, и первое положительное ребро составляет 10 НС в моделировании.

Добавим часы к порту на life:

    component life
        port (
            matrix :    inout   array2D;
            clk:        in      std_logic
    );
    end component;

Мы обновляем сущность de0, чтобы использовать clk:

entity de0 is
port (
    matrix : inout array2D;
    clk:      in   std_logic
);

Мы обновляем процесс, чтобы он был чувствителен к clk и был синхронизирован:

            process (clk)

            variable neighbours : integer := cellValue(matrix, x - 1, y - 1) +
                                            cellValue(matrix, x - 1, y) +
                                            cellValue(matrix, x - 1, y + 1) +
                                            cellValue(matrix, x, y - 1) +
                                            cellValue(matrix, x, y + 1) +
                                            cellValue(matrix, x + 1, y - 1) +
                                            cellValue(matrix, x + 1, y) +
                                            cellValue(matrix, x + 1, y + 1);

        begin
            if clk'event and clk = '1' then
            -- Update the cell value according to the game of life rules
                if (neighbours = 2 or neighbours = 3) then
                    matrix(y, x) <= '1';
                else
                    matrix(y, x) <= '0';
                end if;
            end if;

Теперь, поскольку clk является свободно работающим осциллятором, нам нужно использовать stop-time:

ghdl -a de0.vhdl
ghdl -a life_tb.vhdl
ghdl -e life_tb
ghdl -r life_tb --stop-time=100ns --wave=life_tb.ghw
life_tb.vhdl:35:13:@0ms:(assertion note): End of test
ghdl:info: simulation stopped by --stop-time

тактовая симуляция жизни

Если прокрутить элементы maxtrix, мы обнаружим, что четыре угла матрицы имеют значение '1' при первом событии синхронизации. Все остальные элементы имеют значение '0'.

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

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

И смысл временной симуляции заключается в том, что она позволяет заглянуть в симуляцию, исследуя формы волн, в данном случае с gtkwave. Альтернативой являются утверждения и / или отчеты, но в несвоевременное моделирование они будут происходить на границах цикла, и нет никакой гарантии порядка, если они не являются последовательными утверждениями в одном и том же процессе.

И вы могли бы отметить, что без изменения исходного кода, кроме оператора assertion, оценивающего для matrix ' Event в testbench, вы могли бы заставить вашу модель прекратить имитацию. Вы хотите изменить порог для остановки моделирования с помощью опции времени выполнения (например, --assert-level=warning, где утверждение для отсутствия matrix'Event-это предупреждение. (И утверждение означало бы фактический конец теста).

Фиксация cellValue, как говорится, упражнение, оставленное читателю. (Например, как и почему были установлены углы матрицы в первую очередь?)

Интересная часть заключается в том, чтобы сказать, когда ваша модель находится в состоянии покоя, когда она синхронизирована. Вы можете использовать matrix ' Event для переключения сигнала (использовать его как часы) и использовать часы для проверки двух последовательных вхождений одного и того же значения этого сигнала. И конечно сигнал может используется в операторе утверждения с assert-level для завершения моделирования в состоянии покоя.

Синтезируемое оборудование немного сложнее.