如何显示自验证测试平台中发生的错误数量?
How to display the amount of errors that occured in a self-verifying testbench?
下面是我的一个简单(无时钟)4 位加法器的测试平台代码。我的模拟当前将显示出现的任何错误,并在末尾显示 "Test Completed"。如果没有错误,模拟将简单地 return "Test Completed".
我的问题是:
有没有办法以某种方式包含 "if" 语句,以便在模拟中未检测到错误时显示 "Test Completed, no errors",而在模拟中检测到错误时显示 "Test Completed, [x] errors found"(其中 x是模拟完成后可变的错误量 returned。)?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY adder_4bit_TB IS
END adder_4bit_TB;
ARCHITECTURE behavior OF adder_4bit_TB IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_4bit
PORT(
a : IN std_logic_vector(3 downto 0);
b : IN std_logic_vector(3 downto 0);
carry : OUT std_logic;
sum : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal a : std_logic_vector(3 downto 0) := (others => '0');
signal b : std_logic_vector(3 downto 0) := (others => '0');
--Outputs
signal carry : std_logic;
signal sum : std_logic_vector(3 downto 0);
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: adder_4bit PORT MAP (
a => a,
b => b,
carry => carry,
sum => sum
);
-- Stimulus process
stim_proc: process -- No CLK
begin
-- Initialize Input values
a <= "0000";
b <= "0000";
--Loop over all values of "a" and check sum
for I in 0 to 15 loop
--Loop over all values of "b" and check sum
for J in 0 to 15 loop
-- Wait for output to update (10 ns)
wait for 10ns;
-- Below is the self-verification routune being implemented for the 4 bit Adder.
-- The routine checks the sum of "a" and "b" at the end of every loop, and
-- reports any Errors that may have occured. If no errors occur, simulation
-- will return "Test Completed" (line109) in Command Window.
assert (sum = a + b) report "Expected sum of " &
integer'image(to_integer(unsigned((a + b)))) & ". For a = " &
integer'image(to_integer(unsigned((a)))) & " and b = " &
integer'image(to_integer(unsigned((b)))) & ", but returned sum was " &
integer'image(to_integer(unsigned((sum)))) severity ERROR; -- severity level can be NOTE, WARNING, ERROR, or FAILURE
-- Increment to next value of four bit vector "b"
b <= b + "0001";
end loop;
-- Increment to next value of four bit vector "a"
a <= a + "0001";
end loop;
--Echo to user that report has finished
report "Test completed";
wait; --will wait forever
end process;
END;
使用下面的答案,这里是生成的工作代码:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY adder_4bit_TB IS
END adder_4bit_TB;
ARCHITECTURE behavior OF adder_4bit_TB IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_4bit
PORT(
a : IN std_logic_vector(3 downto 0);
b : IN std_logic_vector(3 downto 0);
carry : OUT std_logic;
sum : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal a : std_logic_vector(3 downto 0) := (others => '0');
signal b : std_logic_vector(3 downto 0) := (others => '0');
--Outputs
signal carry : std_logic;
signal sum : std_logic_vector(3 downto 0);
--Outputs (Testbench only)
signal Errors : boolean; -- Boolean value. True if error detected. False if no error detected.
signal ErrorCount : integer := 0; -- Integer value to store the qty of errors. Intitialized to zero
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: adder_4bit PORT MAP (
a => a,
b => b,
carry => carry,
sum => sum
);
-- Stimulus process
stim_proc: process -- No CLK
begin
-- Initialize Input values
a <= "0000";
b <= "0000";
--Loop over all values of "a" and check sum
for I in 0 to 15 loop
--Loop over all values of "b" and check sum
for J in 0 to 15 loop
-- Wait for output to update (10 ns)
wait for 10ns;
-- Below is the self-verification routune being implemented for the 4 bit Adder.
-- The routine checks the sum of "a" and "b" at the end of every loop, and
-- reports any Errors that may have occured.
if (sum /= a + b) then ---- "/=" syntax: test for inequality, result is boolean
Errors <= true;
ErrorCount <= ErrorCount + 1;
else
Errors <= false;
end if;
assert (Errors = false) report "Expected sum of " &
integer'image(to_integer(unsigned((a + b)))) & ". For a = " &
integer'image(to_integer(unsigned((a)))) & " and b = " &
integer'image(to_integer(unsigned((b)))) & ", but returned sum was " &
integer'image(to_integer(unsigned((sum)))) severity ERROR; -- severity level can be NOTE, WARNING, ERROR, or FAILURE
-- Increment to next value of four bit vector "b"
b <= b + "0001";
end loop;
-- Increment to next value of four bit vector "a"
a <= a + "0001";
end loop;
--Echo to user that report has finished
report "Test completed with " & integer'image(ErrorCount) & " errors";
wait; --will wait forever
end process;
END;
这将非常直接地添加到您已有的内容中。不是使用断言直接测试和的结果,而是使用if
语句设置一个boolean
如果和不正确,然后assert/count错误基于此。类似于:
variable Error : boolean;
variable ErrorCount : integer := 0;
...
if (sum /= a + b) then
Error := true;
ErrorCount := ErrorCount + 1;
else
Error := false;
end if;
assert (Error = false) report "Expected sum of " &
integer'image(to_integer(unsigned((a + b)))) & ". For a = " &
integer'image(to_integer(unsigned((a)))) & " and b = " &
integer'image(to_integer(unsigned((b)))) & ", but returned sum was " &
integer'image(to_integer(unsigned((sum)))) severity ERROR;
...
report "Test completed with " & integer'image(ErrorCount) & " errors";
您可以使用简单的 report
语句代替 assert
并将其包装在 if..then..end if
块中。例如:
if (error_count = 0) then
report "Test completed." severity NOTE;
else
report "Test completed with " & INTEGER'image(error_count) & " errors." severity ERROR;
end if;
这里有一个更高级的方法:
你可以构建一个隐藏一些内部代码的模拟辅助包,这样模拟使用一个更清晰的界面。以下示例声明一个共享变量 pass
以跟踪是否发生错误。
此外,它声明了三个过程来提供断言 'statement' 和 'print simulation result' 方法:
- tbFail 将消息写入模拟器日志并将跟踪变量设置为 false。
- tbAssert 测试条件,如果失败,它会调用 tbFail 生成日志消息
- tbPrintResult 将整体结果写入标准输出。
(这也可以在模拟器日志中看到,但特别是如果模拟以批处理模式运行,它可以被其他命令行工具解析。)
这是一个例子helper package:
use std.TextIO.all;
package body simulation is
-- Test Bench Status Management
-- =============================================
-- * Internal state variable to log a failure condition for final reporting.
-- * Once de-asserted, this variable will never return to a value of true.
shared variable pass : boolean := true;
procedure tbFail(msg : in string := "") is
begin
if msg'length > 0 then
report msg severity error;
end if;
pass := false;
end;
procedure tbAssert(cond : in boolean; msg : in string := "") is
begin
if not cond then
tbFail(msg);
end if;
end;
procedure tbPrintResult is
variable l : line;
begin
write(l, string'("SIMULATION RESULT = "));
if pass then
write(l, string'("PASSED"));
else
write(l, string'("FAILED"));
end if;
writeline(output, l);
end procedure;
end package;
此代码可以在 testbench 中使用,如下所示:
architecture test of arith_prng_tb is
constant CLOCK_PERIOD_100MHZ : TIME := 10 ns;
constant COMPARE_LIST_8_BITS : T_SLVV_8(0 TO 15) := (
x"12", x"24", x"48", x"90", x"21", x"42", x"85", x"0A",
x"14", x"28", x"51", x"A2", x"45", x"8B", x"17", x"2E"
);
signal SimStop : std_logic := '0';
signal Clock : STD_LOGIC := '1';
signal Test_got : STD_LOGIC := '0';
signal PRNG_Value : T_SLV_8;
begin
Clock <= Clock xnor SimStop after CLOCK_PERIOD_100MHZ / 2.0;
process
begin
for i in 0 to 255 loop
Test_got <= '1';
wait until rising_edge(Clock);
tbAssert(
(PRNG_Value = COMPARE_LIST_8_BITS(I)),
"I=" & INTEGER'image(I) & " Value=" & raw_format_slv_hex(PRNG_Value) & " Expected=" & raw_format_slv_hex(COMPARE_LIST_8_BITS(I))
);
end loop;
Test_got <= '0';
-- Report overall simulation result
tbPrintResult;
SimStop <= '1';
wait;
end process;
-- ...
end architecture;
来源:
- PoC.simulation a helper package for simulations (VHDL-2008 version)
- PoC.arith.prng 的测试台 - 伪随机数生成器
推荐大家看看开源测试框架VUnit(https://github.com/LarsAsplund/vunit)。这样你就可以做到
check_equal(sum, a + b);
如果出现错误,将会给你这样的错误消息
ERROR: Equality check failed! Got 1111 (15). Expected 1110 (14).
要输出错误统计信息,您可以使用 get_checker_stat 函数。例如
info("Test Summary" & LF & to_string(get_checker_stat));
它给你这样的东西
INFO: Test Summary
Checks: 6
Passed: 1
Failed: 5
下面是我的一个简单(无时钟)4 位加法器的测试平台代码。我的模拟当前将显示出现的任何错误,并在末尾显示 "Test Completed"。如果没有错误,模拟将简单地 return "Test Completed".
我的问题是:
有没有办法以某种方式包含 "if" 语句,以便在模拟中未检测到错误时显示 "Test Completed, no errors",而在模拟中检测到错误时显示 "Test Completed, [x] errors found"(其中 x是模拟完成后可变的错误量 returned。)?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY adder_4bit_TB IS
END adder_4bit_TB;
ARCHITECTURE behavior OF adder_4bit_TB IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_4bit
PORT(
a : IN std_logic_vector(3 downto 0);
b : IN std_logic_vector(3 downto 0);
carry : OUT std_logic;
sum : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal a : std_logic_vector(3 downto 0) := (others => '0');
signal b : std_logic_vector(3 downto 0) := (others => '0');
--Outputs
signal carry : std_logic;
signal sum : std_logic_vector(3 downto 0);
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: adder_4bit PORT MAP (
a => a,
b => b,
carry => carry,
sum => sum
);
-- Stimulus process
stim_proc: process -- No CLK
begin
-- Initialize Input values
a <= "0000";
b <= "0000";
--Loop over all values of "a" and check sum
for I in 0 to 15 loop
--Loop over all values of "b" and check sum
for J in 0 to 15 loop
-- Wait for output to update (10 ns)
wait for 10ns;
-- Below is the self-verification routune being implemented for the 4 bit Adder.
-- The routine checks the sum of "a" and "b" at the end of every loop, and
-- reports any Errors that may have occured. If no errors occur, simulation
-- will return "Test Completed" (line109) in Command Window.
assert (sum = a + b) report "Expected sum of " &
integer'image(to_integer(unsigned((a + b)))) & ". For a = " &
integer'image(to_integer(unsigned((a)))) & " and b = " &
integer'image(to_integer(unsigned((b)))) & ", but returned sum was " &
integer'image(to_integer(unsigned((sum)))) severity ERROR; -- severity level can be NOTE, WARNING, ERROR, or FAILURE
-- Increment to next value of four bit vector "b"
b <= b + "0001";
end loop;
-- Increment to next value of four bit vector "a"
a <= a + "0001";
end loop;
--Echo to user that report has finished
report "Test completed";
wait; --will wait forever
end process;
END;
使用下面的答案,这里是生成的工作代码:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY adder_4bit_TB IS
END adder_4bit_TB;
ARCHITECTURE behavior OF adder_4bit_TB IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_4bit
PORT(
a : IN std_logic_vector(3 downto 0);
b : IN std_logic_vector(3 downto 0);
carry : OUT std_logic;
sum : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal a : std_logic_vector(3 downto 0) := (others => '0');
signal b : std_logic_vector(3 downto 0) := (others => '0');
--Outputs
signal carry : std_logic;
signal sum : std_logic_vector(3 downto 0);
--Outputs (Testbench only)
signal Errors : boolean; -- Boolean value. True if error detected. False if no error detected.
signal ErrorCount : integer := 0; -- Integer value to store the qty of errors. Intitialized to zero
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: adder_4bit PORT MAP (
a => a,
b => b,
carry => carry,
sum => sum
);
-- Stimulus process
stim_proc: process -- No CLK
begin
-- Initialize Input values
a <= "0000";
b <= "0000";
--Loop over all values of "a" and check sum
for I in 0 to 15 loop
--Loop over all values of "b" and check sum
for J in 0 to 15 loop
-- Wait for output to update (10 ns)
wait for 10ns;
-- Below is the self-verification routune being implemented for the 4 bit Adder.
-- The routine checks the sum of "a" and "b" at the end of every loop, and
-- reports any Errors that may have occured.
if (sum /= a + b) then ---- "/=" syntax: test for inequality, result is boolean
Errors <= true;
ErrorCount <= ErrorCount + 1;
else
Errors <= false;
end if;
assert (Errors = false) report "Expected sum of " &
integer'image(to_integer(unsigned((a + b)))) & ". For a = " &
integer'image(to_integer(unsigned((a)))) & " and b = " &
integer'image(to_integer(unsigned((b)))) & ", but returned sum was " &
integer'image(to_integer(unsigned((sum)))) severity ERROR; -- severity level can be NOTE, WARNING, ERROR, or FAILURE
-- Increment to next value of four bit vector "b"
b <= b + "0001";
end loop;
-- Increment to next value of four bit vector "a"
a <= a + "0001";
end loop;
--Echo to user that report has finished
report "Test completed with " & integer'image(ErrorCount) & " errors";
wait; --will wait forever
end process;
END;
这将非常直接地添加到您已有的内容中。不是使用断言直接测试和的结果,而是使用if
语句设置一个boolean
如果和不正确,然后assert/count错误基于此。类似于:
variable Error : boolean;
variable ErrorCount : integer := 0;
...
if (sum /= a + b) then
Error := true;
ErrorCount := ErrorCount + 1;
else
Error := false;
end if;
assert (Error = false) report "Expected sum of " &
integer'image(to_integer(unsigned((a + b)))) & ". For a = " &
integer'image(to_integer(unsigned((a)))) & " and b = " &
integer'image(to_integer(unsigned((b)))) & ", but returned sum was " &
integer'image(to_integer(unsigned((sum)))) severity ERROR;
...
report "Test completed with " & integer'image(ErrorCount) & " errors";
您可以使用简单的 report
语句代替 assert
并将其包装在 if..then..end if
块中。例如:
if (error_count = 0) then
report "Test completed." severity NOTE;
else
report "Test completed with " & INTEGER'image(error_count) & " errors." severity ERROR;
end if;
这里有一个更高级的方法:
你可以构建一个隐藏一些内部代码的模拟辅助包,这样模拟使用一个更清晰的界面。以下示例声明一个共享变量 pass
以跟踪是否发生错误。
此外,它声明了三个过程来提供断言 'statement' 和 'print simulation result' 方法:
- tbFail 将消息写入模拟器日志并将跟踪变量设置为 false。
- tbAssert 测试条件,如果失败,它会调用 tbFail 生成日志消息
- tbPrintResult 将整体结果写入标准输出。
(这也可以在模拟器日志中看到,但特别是如果模拟以批处理模式运行,它可以被其他命令行工具解析。)
这是一个例子helper package:
use std.TextIO.all;
package body simulation is
-- Test Bench Status Management
-- =============================================
-- * Internal state variable to log a failure condition for final reporting.
-- * Once de-asserted, this variable will never return to a value of true.
shared variable pass : boolean := true;
procedure tbFail(msg : in string := "") is
begin
if msg'length > 0 then
report msg severity error;
end if;
pass := false;
end;
procedure tbAssert(cond : in boolean; msg : in string := "") is
begin
if not cond then
tbFail(msg);
end if;
end;
procedure tbPrintResult is
variable l : line;
begin
write(l, string'("SIMULATION RESULT = "));
if pass then
write(l, string'("PASSED"));
else
write(l, string'("FAILED"));
end if;
writeline(output, l);
end procedure;
end package;
此代码可以在 testbench 中使用,如下所示:
architecture test of arith_prng_tb is
constant CLOCK_PERIOD_100MHZ : TIME := 10 ns;
constant COMPARE_LIST_8_BITS : T_SLVV_8(0 TO 15) := (
x"12", x"24", x"48", x"90", x"21", x"42", x"85", x"0A",
x"14", x"28", x"51", x"A2", x"45", x"8B", x"17", x"2E"
);
signal SimStop : std_logic := '0';
signal Clock : STD_LOGIC := '1';
signal Test_got : STD_LOGIC := '0';
signal PRNG_Value : T_SLV_8;
begin
Clock <= Clock xnor SimStop after CLOCK_PERIOD_100MHZ / 2.0;
process
begin
for i in 0 to 255 loop
Test_got <= '1';
wait until rising_edge(Clock);
tbAssert(
(PRNG_Value = COMPARE_LIST_8_BITS(I)),
"I=" & INTEGER'image(I) & " Value=" & raw_format_slv_hex(PRNG_Value) & " Expected=" & raw_format_slv_hex(COMPARE_LIST_8_BITS(I))
);
end loop;
Test_got <= '0';
-- Report overall simulation result
tbPrintResult;
SimStop <= '1';
wait;
end process;
-- ...
end architecture;
来源:
- PoC.simulation a helper package for simulations (VHDL-2008 version)
- PoC.arith.prng 的测试台 - 伪随机数生成器
推荐大家看看开源测试框架VUnit(https://github.com/LarsAsplund/vunit)。这样你就可以做到
check_equal(sum, a + b);
如果出现错误,将会给你这样的错误消息
ERROR: Equality check failed! Got 1111 (15). Expected 1110 (14).
要输出错误统计信息,您可以使用 get_checker_stat 函数。例如
info("Test Summary" & LF & to_string(get_checker_stat));
它给你这样的东西
INFO: Test Summary
Checks: 6
Passed: 1
Failed: 5