Reputation: 23
I'm struggling to write a test bench for this:
---------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
---------------------------------------
ENTITY mux IS
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
END mux;
---------------------------------------
ARCHITECTURE pure_logic OF mux IS
BEGIN
y <= (a AND NOT s1 AND NOT s0) OR
(b AND NOT s1 AND s0) OR
(c AND s1 AND NOT s0) OR
(d AND s1 AND s0);
END pure_logic;
---------------------------------------
This is my progress so far. I am not quite sure how to write the stimulus part. I tried running it through a behavioral simulation, but I am getting Undefined Errors in the results.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux_tb is
-- Port ( );
end mux_tb;
architecture Behavioral of mux_tb is
component mux
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
end component;
signal a : std_logic;
signal b : std_logic;
signal c : std_logic;
signal d : std_logic;
signal s0 : std_logic;
signal s1 : std_logic;
signal y : std_logic;
begin
uut: mux port map (
a => a,
b => b,
c => c,
d => d,
s0 => s0,
s1 => s1,
y => y
);
process
begin
s0 <= '0'; s1 <= '0';
wait for 100 ns;
s1 <= '0'; s0 <= '1';
wait for 100ns;
s1 <= '1'; s0 <= '0';
wait for 100ns;
s1 <= '1'; s0 <= '1';
end process;
end Behavioral;
Could anyone explain what I am doing wrong?
Upvotes: 2
Views: 1082
Reputation: 124
I am not quite sure how to write the stimulus part
You appear to be asking for a design technique that can be used to stimulate the inputs.
A simple method for testing a purely combinatorial circuit like your component is to drive the inputs from a test counter. In this case, it can be a 7-bit std_logic_vector counter
.
Then write a loop with 128 passes. On each pass, it will perform the component's logic function on the counter
value to produce an expected result. The pass will wait for the component outputs to settle then use an assert
to compare the actual result with the expected result and display an error if they don't match. Then increment counter
and do the next pass.
Upvotes: -2
Reputation:
You might want separate loops for the ABCD inputs and the select inputs. This makes it easier to see that the output reacts to B but not A,C,D inputs when the select is set to B, and so on. Clearer than trying to interpret a 6 bit number.
In addition to the stimulus part covered in other answers, a good TB will compute (or read from an array or file or something) the expected outputs, and compare these with the actual outputs, reporting any differences ... you can use Assert/Report for this.
If you then log Pass/Fail and number of errors (possibly to a file) at end of test, you can use this in regression tests and never have to stare at waveforms again. That's when it gets to be a time saver.
See also osvvm.org and Vunit (on github) for tools to help.
Upvotes: 1
Reputation: 755
Your testbench does not supply stimuli for a, b, c and d. You need to assign them as well as s0 and s1.
architecture full_behavior of mux_tb is
component mux
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
end component;
signal a : std_logic;
signal b : std_logic;
signal c : std_logic;
signal d : std_logic;
signal s0 : std_logic;
signal s1 : std_logic;
signal y : std_logic;
use ieee.numeric_std.all; -- CHANGED Added use clause
begin
uut:
mux port map (
a => a,
b => b,
c => c,
d => d,
s0 => s0,
s1 => s1,
y => y
);
STIMULI_ASSERT:
process
variable inputs: std_logic_vector (3 downto 0); -- data inputs
variable s1s0: integer range 0 to 3; -- selects as integer
begin
for i in 0 to 63 loop
(d, c, b, a, s1, s0) <= to_unsigned(i, 6);
wait for 100 ns;
inputs := (d, c, b, a);
s1s0 := to_integer(unsigned'(s1 & s0));
assert y = inputs(s1s0)
report "Expected " & std_ulogic'image(inputs(s1s0)) &
" got " & std_ulogic'image(y)
severity error;
end loop;
wait;
end process;
end architecture;
You can do this with a for loop which assigned values to all the mux inputs. Additionally if all the inputs are ordered you can use s0 and s1 to select which of the data inputs should appear on y.
Here the for loop range is determined by the power of two raised to the number of inputs.
This
(d, c, b, a, s1, s0) <= to_unsigned(i, 6);
is an aggregate assignment that takes it's type from context (the entire statement). 6 is the number of inputs and specifies the length of integer value i converted to unsigned. The assignment is to individual elements of the target aggregate.
this
inputs := (d, c, b, a);
has the type of the aggregate specified by the assignment target (std_logic_vector).
and this
s1s0 := to_integer(unsigned'(s1 & s0));
saves the integer value of the concatenation of s1 & s0 specified as type unsigned to s1s0.
The assertion checks the expected output as an indexed value of the data inputs against y and when not equal reports an error along with the expected and y values.
We use type unsigned declared in IEEE package numeric_std along with it's operations when we want to treat a composite value as an unsigned number.
Upvotes: 4