GHDL挂起正在运行的测试台

ale*_*vey 3 fpga vhdl ghdl

在VHDL中测试简单的生活游戏实现时,在打印出“测试结束”消息后,空测试台的GHDL模拟会挂起,CPU使用率达到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;
Run Code Online (Sandbox Code Playgroud)

和测试台:

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;
Run Code Online (Sandbox Code Playgroud)

Mor*_*mer 5

de0生命周期中的进程既没有敏感列表,也没有wait语句,所以这个进程将永远运行,只是在同一模拟时间无限循环执行进程中的语句,因此模拟不会停止。

您可以通过添加敏感列表(matrix)或在某些条件下等待来解决此问题。


use*_*120 5

这补充了MortenZdk的很好的答案。它太大了,无法发表评论,并且不会更改答案。它确实演示了如何使您的模型计时,以及如何使其停止连续运行。

放置矩阵是未标记过程在de0(life)中的敏感度列表

            process (matrix)
Run Code Online (Sandbox Code Playgroud)

给出:

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
Run Code Online (Sandbox Code Playgroud)

断言测试仅执行一次并立即执行,并不表示测试结束。

请注意,该模型已退出执行,但我们不知道模拟周期是如何进行的。仿真时间背后的想法是允许存储波形以及量化相对时间。

在仿真中添加时钟:

在体系结构声明区域中,我们声明时钟信号:

    signal clk: std_logic;
Run Code Online (Sandbox Code Playgroud)

您可以添加一个新进程以在您的测试平台(life_tb.vhdl)中生成时钟:

CLOCK:
    process 
    begin
        wait for 10 ns;
        clk <= '0';
        wait for 10 ns;
        clk <= '1';
    end process;
Run Code Online (Sandbox Code Playgroud)

它具有20 ns的周期,并且模拟的第一个上升沿为10 ns。

我们为生活添加时钟:

    component life
        port (
            matrix :    inout   array2D;
            clk:        in      std_logic
    );
    end component;
Run Code Online (Sandbox Code Playgroud)

我们更新de0实体以使用clk:

entity de0 is
port (
    matrix : inout array2D;
    clk:      in   std_logic
);
Run Code Online (Sandbox Code Playgroud)

我们更新过程以使其对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;
Run Code Online (Sandbox Code Playgroud)

现在,由于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
Run Code Online (Sandbox Code Playgroud)

时钟生活模拟

如果滚动浏览maxtrix元素,我们会发现在第一个时钟事件时,矩阵的四个角都设置为“ 1”。其余所有元素均设置为“ 0”。

光标处显示的第二个clk事件不会为任何矩阵元素分配新值(四个矩阵角每个看到三个邻居,它们是稳定的)。

如果矩阵在过程敏感度列表中,则模拟将在第二次(不计时)之后停止。

定时仿真的要点是,它允许您通过检查波形(在本例中为gtkwave)来窥视仿真。替代方法是断言和/或报告语句,但是在非定时模拟中,它们将在循环边界上发生,并且如果它们不是同一过程中的顺序语句,则不能保证顺序。

您可能会注意到,除了声明语句在测试台中评估矩阵事件之外,无需修改原始代码,就可以使模型停止仿真。您需要使用运行时选项更改停止仿真的阈值(例如--assert-level = warning,其中断言缺少矩阵事件的事件是警告。(断言将表示实际结束)测试)。

修复cellValue就像他们说的一样留给读者。(就像如何或为什么首先设置矩阵角?)

有趣的部分是告诉您模型何时定时处于静止状态。您可以使用矩阵事件来切换信号(将其用作时钟),并使用时钟测试该信号的相同值的两次连续出现。当然,该信号可以在具有断言级别的断言语句中使用,以在静态时结束仿真。

可综合的硬件涉及更多。