3

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;
4

2 に答える 2

5

これは、MortenZdk の優れた回答を補足します。コメントに入れるには大きすぎるだけで、その答えは変わりません。モデルをクロックする方法と、モデルが継続的に実行されないようにする方法を示しています。

配置行列は、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

アサーション テストは 1 回だけ実行され、すぐに実行され、テストの終了を通知しません。

モデルが実行を終了したことに注意してください。ただし、シミュレーション サイクルが何回かかったかはわかりません。シミュレーション時間の背後にある考え方は、波形を保存し、相対時間を量子化できるようにすることです。

シミュレーションへのクロックの追加:

アーキテクチャ宣言領域で、クロック信号を宣言します。

    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;

clk を使用するように de0 エンティティを更新します。

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 要素をスクロールすると、マトリックスの 4 つのコーナーが最初のクロック イベントで「1」に設定されていることがわかります。残りの要素はすべて「0」に設定されます。

カーソル位置に表示される 2 番目の clk イベントは、どの行列要素にも新しい値を割り当てません (行列の 4 つのコーナーにはそれぞれ 3 つの隣接要素があり、安定しています)。

マトリックスがプロセス感度リストに含まれていた場合、シミュレーションは 2 回目以降に停止します (アンクロック)。

時間シミュレーションのポイントは、この場合は gtkwave を使用して、波形を調べることでシミュレーションを覗き込めることです。代替手段はアサーションおよび/またはレポート ステートメントですが、タイミングのないシミュレーションでは、これらはサイクル境界で発生し、同じプロセス内のシーケンシャル ステートメントでない場合、順序の保証はありません。

また、テストベンチでマトリックスのイベントを評価するアサーション ステートメント以外の元のコードを変更しなくても、モデルのシミュレーションを停止できることに注意してください。実行時オプションを使用してシミュレーションを停止するためのしきい値を変更することをお勧めします (たとえば、--assert-level=warning の場合、matrix'event の欠如に対するアサーションは警告です。(そして、アサーションは実際の終了を意味します)。テストの)。

cellValue を修正することは、彼らが言うように、読者に任された演習です。(そもそもマトリックスのコーナーがどのように、またはなぜ設定されたのか?)

興味深いのは、タイミングを計ったときにモデルがいつ静止しているかを伝えることです。matrix'event を使用して信号を切り替え (クロックとして使用)、そのクロックを使用してその信号の同じ値が 2 回連続して発生するかどうかをテストできます。もちろん、assert-level のアサーション ステートメントで信号を使用して、静止時にシミュレーションを終了することもできます。

合成可能なハードウェアはもう少し複雑です。

于 2013-07-26T01:57:38.523 に答える
5

de0 の有効期間中のプロセスには、センシティビティ リストも wait ステートメントもありません。そのため、このプロセスは無限に実行され、同じシミュレーション時間にプロセス内のステートメントを無限ループで実行するだけなので、シミュレーションは停止しません。

これは、機密性リストを追加する(matrix)か、何らかの条件で待機することで修正できます。

于 2013-07-25T10:34:02.990 に答える