はじめに
いつの間にか知っていたけれど、
あまり説明されない記述をまとめています。
ビット列に区切り文字
VHDLでは進数を明示すれば区切り文字として_
が使えます。
constant a : std_logic_vector(9 downto 0) := "11_0010_0001"; -- illegal
constant b : std_logic_vector(9 downto 0) := B"11_0010_0001";
aggregate
全てのビットの値を指定する時にothers
をよく使いますが、
一部のビットだけを別の値に指定することができます。
constant data_bits : natural := 8;
constant unsigned_max : unsigned(data_bits - 1 downto 0) := (others => '1');
constant signed_max : signed(data_bits - 1 downto 0) := (data_bits - 1 => '0', others => '1');
オーバーロード
VHDLのsubprogramではオーバーロードを使うことができます
例えば、自作のrecord_type
型の値をチェックする
Vunitのcheck_equal
にオーバーロードしたprocedure
を作ることで
テストコードの見通しがよくなります。
library vunit_lib;
context vunit_lib.vunit_context;
library ieee;
use ieee.std_logic_1164.all;
entity tb_sample is
generic (
runner_cfg : string := runner_cfg_default
);
end tb_sample;
architecture behavior of tb_sample is
type record_type is record
address : std_logic_vector(7 downto 0);
data : std_logic_vector(15 downto 0);
end record;
constant A : record_type := {
address => (others => '0'),
data => (others => '0')
};
constant B : record_type := {
address => (others => '0'),
data => (others => '1')
};
-- overload
procedure check_equal(
constant got : in record_type;
constant expected : in record_type;
constant msg : in string
) is
begin
check_equal(got.address, expected.address, "address : " & msg);
check_equal(got.data, expected.data, "data : " & msg);
end;
begin
test_bench : process
begin
test_runner_setup(runner, runner_cfg);
while test_suite loop
if run("test") then
check_equal('1', '0', "std_logic error");
check_equal(A, B, "record_type error"); -- overload
end if;
end loop;
test_runner_cleanup(runner);
end process;
end;
wait until
wait until
はイベント発生時(値が変化した時)にチェックされるので、
以下のように最初から条件を満たしている場合は待ち続けることになります。
a <= '0';
wait until a ='0';
b <= '0';
対策としては以下の2パターンがあります。
- 逆条件をチェックしてから待つ
- 適当なクロックと合わせて待つ
1
if a /= '0' then
wait until a ='0';
end if;
2
wait until rising_edge(clk) and a ='0';