2007年07月30日
VHDL TIPS 「パッシブプロセスの使用法」
VHDLにはパッシブプロセスという物がある。
パッシブプロセスとはエンティティ内にあるプロセスの事で、主にシミュレーションでインターフェースのチェック等を行う事が出来る。
同様のことがアーキテクチャ内でも可能だがエンティティ内で行うことにより複数のアーキテクチャをコンフィギュレーションで選択する場合などに共有できるメリットがある。
以下の例では、パッシブプロセスでデータのセットアップ/ホールドをチェックしている。
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity PASSIVE_TEST is
generic
(
SETUP : in time := 10 ns;
HOLD : in time := 5 ns
);
port
(
CLK : in std_logic;
DIN : in std_logic;
DOUT : out std_logic
);
begin
-- XSTはパッシブプロセスをサポートしていない
-- pragma translate_off
process
variable PREV_DIN : std_logic := 'U';
variable PREV_DIN_TIME : time := 0 ns;
variable PREV_CLK_TIME : time := 0 ns;
begin
-- CLKかDINに変化があれば次に進む
wait on CLK, DIN;
-- DINに変化があった場合
if ( DIN /= PREV_DIN ) then
PREV_DIN_TIME := now;
PREV_DIN := DIN;
if ( now - PREV_CLK_TIME < HOLD ) then
assert false
report "Hold Time was not suitable."
severity WARNING;
end if;
end if;
-- CLKに変化があった場合
if ( CLK'event and CLK = '1' ) then
PREV_CLK_TIME := now;
if ( now - PREV_DIN_TIME < SETUP ) then
assert false
report "Setup Time was not suitable."
severity WARNING;
end if;
end if;
end process;
-- pragma translate_on
end PASSIVE_TEST;
-- ビヘイビア1
architecture BEHAVIOR1 of PASSIVE_TEST is
begin
process ( CLK ) begin
if ( CLK'event and CLK = '1' ) then
DOUT <= DIN;
end if;
end process;
end BEHAVIOR1;
-- ビヘイビア2
architecture BEHAVIOR2 of PASSIVE_TEST is
begin
process ( CLK ) begin
if ( CLK'event and CLK = '1' ) then
DOUT <= DIN after 2 ns;
end if;
end process;
end BEHAVIOR2;
この様にパッシブプロセスとしてセットアップ/ホールドをチェックする事で、アーキテクチャ「BEHAVIOR1 」と「BEHAVIOR2 」で共有する事ができる。
ただし注意点として、パッシブプロセス内では信号(signal)定義や代入を行うことが出来ないのでprocess内でvariableを使用するかコンカレント文で直接ポートをチェックするしか無い。また、XilinxのXSTではサポートされていないのでtranslate_offする必要もある。
以下に上記例のコンフィギュレーションを含めたテストベンチを紹介する。
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity PASSIVE_TEST_TB is
end PASSIVE_TEST_TB;
architecture behavior of PASSIVE_TEST_TB is
component PASSIVE_TEST
generic
(
SETUP : in time := 10 ns;
HOLD : in time := 5 ns
);
port
(
CLK : in std_logic;
DIN : in std_logic;
DOUT : out std_logic
);
end component;
signal CLK : std_logic := '1';
signal DIN : std_logic := '0';
signal DOUT : std_logic := '0';
begin
U_PASSIVE_TEST : PASSIVE_TEST
generic map
(
SETUP => 10 ns,
HOLD => 5 ns
)
port map
(
CLK => CLK,
DIN => DIN,
DOUT => DOUT
);
process begin
CLK <= '1';
wait for 50 ns;
CLK <= '0';
wait for 50 ns;
end process;
process begin
DIN <= '0' after 3 ns; -- Hold Error;
wait for 200 ns;
DIN <= '1' after 91 ns; -- Setup Error;
wait for 200 ns;
end process;
end behavior;
-- ビヘイビア1を選択
configuration PASSIVE_TEST_CONFIG1 of PASSIVE_TEST_TB is
for behavior
for U_PASSIVE_TEST : PASSIVE_TEST use entity work.passive_test(BEHAVIOR1);
end for;
end for;
end PASSIVE_TEST_CONFIG1;
-- ビヘイビア2を選択
configuration PASSIVE_TEST_CONFIG2 of PASSIVE_TEST_TB is
for behavior
for U_PASSIVE_TEST : PASSIVE_TEST use entity work.passive_test(BEHAVIOR2);
end for;
end for;
end PASSIVE_TEST_CONFIG2;
これをModelsimでシミュレーションすると、両方のコンフィギュレーションでアサーションが有効であることが分かる。