GHDL вешает работающий тестовый стенд
При тестировании простой реализации жизненной игры в 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 ответа
Процесс в жизни de0 не имеет ни списка чувствительности, ни оператора ожидания, поэтому этот процесс будет выполняться вечно, просто выполняя операторы в процессе в бесконечном цикле в одно и то же время моделирования, и поэтому моделирование не остановится.
Вы можете исправить это, добавив список чувствительности (matrix)
или ожидание с некоторым условием.
Это дополняет прекрасный ответ MortenZdk. Это просто слишком большой, чтобы идти в комментариях и не меняет этот ответ. Он демонстрирует, как сделать вашу модель синхронизированной, а также как остановить ее непрерывную работу.
Матрица размещения - это список чувствительности немеченого процесса в de0 (жизнь)
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 нс.
Добавляем часы в порт по жизни:
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 является свободно работающим осциллятором, нам нужно использовать время остановки:
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. Альтернативой являются операторы утверждений и / или отчетов, но при несвоевременном моделировании они будут происходить на границах цикла, и нет гарантии порядка, если они не являются последовательными утверждениями в одном и том же процессе.
И вы могли бы заметить, не изменяя свой исходный код, кроме утверждения утверждения, оценивающего Matrix'event в testbench, вы можете заставить свою модель прекратить симуляцию. Вы бы хотели изменить порог для остановки симуляции с помощью параметра времени выполнения (например, --assert-level=warning, где утверждение об отсутствии matrix'event является предупреждением. (И утверждение будет означать фактический конец испытания).
Исправление cellValue - это, как говорят, упражнение, оставленное читателю. (Как и как или почему углы матрицы были установлены в первую очередь?)
Интересная часть рассказывает, когда ваша модель находится в покое, когда рассчитано время. Вы можете использовать matrix'event для переключения сигнала (используйте его в качестве часов) и использовать часы для проверки двух последовательных вхождений одного и того же значения этого сигнала. И, конечно, сигнал может быть использован в операторе утверждения с уровнем утверждения для завершения симуляции в состоянии покоя.
Синтезируемое оборудование немного сложнее.