在VHDL中测试简单的生命游戏实现时,在打印出“测试结束”消息后,空测试平台的GHDL模拟会以100%的CPU使用率挂起。
以下是代码:
----- 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;
答案 0 :(得分:4)
这补充了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 ns,第一个上升沿为模拟中的10 ns。
我们将时钟添加到生活端口:
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的断言语句之外,您可以在不修改原始代码的情况下注意,您可以让模型停止模拟。您希望使用运行时选项更改停止模拟的阈值(例如--assert-level = warning,其中缺少matrix'event的断言是警告。(并且断言将表示实际结束)测试)。
修复cellValue正如他们所说的那样,练习留给了读者。 (至于如何或为什么首先设置矩阵角?)
有趣的部分是告诉您的模型何时定时静止。您可以使用matrix'event切换信号(将其用作时钟)并使用时钟测试该信号的相同值的两次连续出现。当然,信号可以在断言语句中使用,断言级别在静止时结束模拟。
可合成的硬件涉及更多。
答案 1 :(得分:3)
de0的生命过程既没有敏感列表也没有wait语句,所以这个过程将永远运行,只是在相同的模拟时间以无限循环执行过程中的语句,因此模拟不会停止。
您可以通过添加敏感度列表(matrix)
或等待一些条件来解决此问题。