我正在尝试实现我们的PoC.Simulation
帮助程序包的 VHDL-08 版本。
原始包使用共享变量来跟踪模拟状态:
- pass : 所有断言都通过
- stop : 停止所有进程
有几个函数和过程使用该内部状态。例如,一个tbGenerateClock()
过程用于创建一个时钟信号。
在我的 VHDL-08 版本中,我使用受保护类型作为共享变量。我实现了几个“方法”(正确的终点是什么?),它们正在使用或修改内部状态变量。
GHDL 编译我所有的源代码并在运行时抛出错误:
C:\Tools\GHDL\0.33dev\bin\ghdl.exe:internal error: protected_enter(2)
C:\Tools\GHDL\0.33dev\bin\ghdl.exe:error: simulation failed
这是 GHDL 内部错误还是我以错误的方式使用受保护类型?
我创建了一个(希望如此)最小的示例(从 Gist 下载),它只有 2 个过程:generateClock
, stopSimulation
.
还有一些tb*
包装程序来确保与我的 VHDL-93 实现兼容的接口。
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package simulation is
type tSimStatus is protected
procedure stopSimulation;
procedure generateClock(signal Clock : out STD_LOGIC; constant ClockPeriod : TIME; Enable : BOOLEAN := TRUE);
end protected;
-- stop all simulation processes
procedure tbStopSimulation;
-- Generate clock waveform for simulation
procedure tbGenerateClock(signal Clock : out STD_LOGIC; constant ClockPeriod : TIME; Enable : BOOLEAN := TRUE);
end;
package body simulation is
type tSimStatus is protected body
variable stop : BOOLEAN := FALSE;
procedure stopSimulation is
begin
stop := TRUE;
end procedure;
procedure generateClock(signal Clock : out STD_LOGIC; constant ClockPeriod : TIME; Enable : BOOLEAN := TRUE) is
constant HIGH_TIME : TIME := ClockPeriod / 2;
constant LOW_TIME : TIME := ClockPeriod / 2;
begin
Clock <= '1';
while not stop loop
while Enable and not stop loop
Clock <= '1';
wait for HIGH_TIME;
Clock <= '0';
wait for LOW_TIME;
end loop;
wait until (Enable = TRUE) or (stop = TRUE);
end loop;
end procedure;
end protected body;
shared variable status : tSimStatus;
procedure tbStopSimulation is
begin
status.stopSimulation;
end procedure;
procedure tbGenerateClock(signal Clock : out STD_LOGIC; constant ClockPeriod : TIME; Enable : BOOLEAN := TRUE) is
begin
status.generateClock(Clock, ClockPeriod, Enable);
end procedure;
end package body;
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use work.simulation.all;
entity tb is
end entity;
architecture test of tb is
constant CLOCK_PERIOD : TIME := 10 ns;
signal Clock : STD_LOGIC;
signal Reset : STD_LOGIC := '0';
begin
-- clock process
process
begin
tbGenerateClock(Clock, CLOCK_PERIOD, TRUE);
end process;
-- stimuli process
process
begin
wait until rising_edge(Clock);
Reset <= '1';
wait until rising_edge(Clock);
Reset <= '0';
wait until rising_edge(Clock);
tbStopSimulation;
wait;
end process;
end;
解决方案:
- 将时钟生成代码移动到
tbGenerateClock
程序中 - 向受保护类型添加一个函数以获取内部停止状态
- 将此功能标记为
impure
这是修改后的模拟包:
package simulation is
type tSimStatus is protected
procedure stopSimulation;
impure function getState return BOOLEAN;
end protected;
-- stop all simulation processes
procedure tbStopSimulation;
-- Generate clock waveform for simulation
procedure tbGenerateClock(signal Clock : out STD_LOGIC; constant ClockPeriod : TIME; Enable : BOOLEAN := TRUE);
end;
package body simulation is
type tSimStatus is protected body
variable stop : BOOLEAN := FALSE;
procedure stopSimulation is
begin
stop := TRUE;
end procedure;
impure function getState return BOOLEAN is
begin
return stop;
end function;
end protected body;
shared variable status : tSimStatus;
procedure tbStopSimulation is
begin
status.stopSimulation;
end procedure;
procedure tbGenerateClock(signal Clock : out STD_LOGIC; constant ClockPeriod : TIME; Enable : BOOLEAN := TRUE) is
constant HIGH_TIME : TIME := ClockPeriod / 2;
constant LOW_TIME : TIME := ClockPeriod / 2;
begin
Clock <= '1';
while not status.getState loop
while Enable and not status.getState loop
Clock <= '1';
wait for HIGH_TIME;
Clock <= '0';
wait for LOW_TIME;
end loop;
wait until (Enable = TRUE) or (status.getState = TRUE);
end loop;
end procedure;
end package body;