Download as pdf or txt
Download as pdf or txt
You are on page 1of 86

Testbenches

• Design verification
• Design should achieve intended functionality and
• Should meet timing requirements
• Both of these aspects can be verified using simulation through
testbenches.
Constituents of testbench
• The three basic constituents of a simple testbench- are the UUT,
stimulus generator. and response monitor-

• UUT : A testbench is a top-level VHDL program that includes an
instantiation of the design to be verified. This instance is labeled UUT
(unit under test)
• For a functional verification, the design description is the UUT.
• For a timing verification the VHDL timing model generated by the
place-and-route tool is the UUT.
• Stimulus generator: A testbench includes code that applies a
sequence of predetermined stimulus values to the UUT's inputs. This
code comprises a stimulus generator.
• The stimulus must not contain any metalogical or high-impedance
values Logical values 'L' and 'H' are replaced by '0' and '1',
respectively.
• As a result , for combinational designs, only combinations of the
values '0' and '1', Or sequences of such combinations, are applied as
stimulus.

• Response monitor :
• In response to each stimulus, the UUT's output values must be checked
to verify that they are identical to the expected output values.
Self checking testbench
• In testbenches for very simple designs, verification can be
accomplished by visual inspection of the UUT's outputs in the
simulator's waveform editor window.
• However, a more efficient approach is to include code in the testbench
to automatically check the actual UUT output values against the
expected values.
• Such a testbench is referred to as being self-checking.
Intent model
• Thus, the block labeled response monitor in Figure could be either a
person inspecting the simulator output waveforms or code that is part
of the testbench.
• Using an intent model, the response monitor simply compares the
UUT's output with that of the intent model, for each stimulus applied.
• The intent model provides the expected values in response to a
stimulus. The intent model can be anything from a table to an
executahle specification.
• For example, design intent might be represented by a nonsynthesizable
VHDL behavioral model.
Functional verification
• It is not concerned with any timing delays that result from mapping
synthesized logic to a target PLD.
• Accordingly, functional verification should be performed immediately
after a design description is written,
• This allows us to find logical errors early in the design flow and
prevents wasting our time in performing synthesis, place and route,
and timing simulation for a description that is not functionally correct.
• functional verification allows us to detect errors that result from our
misunderstanding the semantics of VHDL statements that we have
used.
• Since a testbench is only simulated, not synthesized, the full range of
VHDL language constructs and features can be used.
• Some additional nonsynthesizable VHDL features useful in
testbenches include multidimensional arrays and text I/O.
Simple testbench
• The simplest testbenches don't include code for a response monitor or
an intent model.
• They just apply stimulus to the UUT.
• We must then visually verify UUT output values by inspecting
waveforms using the simulator's waveform editor.
testbench for halfadder
• library ieee;
• use ieee.std_logic_1164.all;
• entity testbench is -- testbench entity has no ports
• end testbench;
• -- Stimulus signals - to connect testbench to UUT input ports
• signal a_tb, b_tb : std_logic;
• -- Observed signals - to connect testbench to UUT output ports
• signal sum_tb, carry_out tb: std_logic;
• -- Unit Under Test port map
• UUT : entity half adder port map (a => a_tb, b => b_tb, sum =>
sum_tb, carry_out => carry_out_ tb );
Continued..
• Signal assignment statements generating stimulus values
• a_tb <= '0', '1' after 40 ns;
• b_tb <= '0', ‘1' after 20 ns, '0' after 40 ns, ‘1' after 60 ns;

• In this example, the testbench entity is named testbench.


• Often a convention is followed where the testbench's name is the same
as the UUT's name with the addition of the suffix _ tb.
• The entity declaration for testbench has no ports.
• After clauses are not synthesizable.
• The time expression in an after clause must evaluate to a value of type
time.
• Type time is a predefined physical type.
Single process testbench
• Library ieee;
• use ieee. std logic 1164. all;
• entity testbench is
• end tes tbench;
• -- Declare local signals to assign values to and to observe
• signal a_tb, b_tb, sum_tb, carry_out tb : std logic;
• begin
• -- Create an instance of the circuit to be tested
• uut: entity half_adder port map(a => a_tb, b => b tb,
• sum => sum_tb, carry_out => carry_out_tb) ;
• Define a process to apply input stimulus and verify outputs
• tb : process
• constant period: time := 20 ns;
• Begin --apply every possible i/p combination
• a tb <= '0'; --apply input combination 00 and check outputs
• b tb <= '0';
• wait for period;
• assert ((sum_tb = '0') and (carry_out_tb = '0'))
• report "test failed for input combination 00" severity error;

• a tb <= '0'; --apply input combination 01 and check outputs


• b tb <= '1';

• wait for period;
• assert ((sum_tb = '1') and (carry out tb = '0'))
• report "test failed for input combination 01" severity error;
• a tb <= '1'; --apply input combination 10 and check outputs
• b tb <= '0';
• wait for period;
• assert ((sum_tb = '1') and (carry out tb = '0'))
• report "test failed for input combination 10" severity error;
• a tb <= '1'; --apply input combination 11 and check outputs
• b tb <= '1';
• wait for period;
• assert ((sum_tb = '0') and (carry out tb = '1')) report "test failed for
input combination 11" severity error;
• end process;
• end;
• The need of wait statement is
• First, the signal assignments can't take effect until after the process
suspend,.
• Without the wait for statement, the response would be checked during
the current simulation cycle and would not be the response to the
newly assigned input values.
• Second, waiting for a time interval allows the new input values to
appear in the simulator waveforms for this time period. This makes it
possible to view the waveform. Otherwise, all the actions in the
process would take place in zero simulation time.
• Third, wait statements allow this same testbench to be used later,
without modification for timing simulation.
• Use of assertion statements eliminate the need to visually inspect
timing waveforms .
Wait statement
• A wait on statement has a sensitivity list. While a process is suspended
due to the execution of a wait on statement, all signals in the
statement's sensitivity list are monitored by the simulator. When an
event occurs on anyone of these signals, the process resumes execution
at the statement following the wait on statement. Note that a wait on
statement's sensitivity list is not enclosed in parentheses.
• A wait until statement causes a process to suspend until its associated
boolean expression is true. A wait until statement has an implied
sensitivity list involving all the signals in the Boolean expression.
• When an event occurs on any signal in the implied sensitivity list. the
boolean expression is evaluated. If it evaluates true, the suspended
process resumes execution at the statement following the wait until
statement.
• If its boolean expression is already true, when a wait until statcment is
cxecuted, the process will still suspend.
• There must be a subselluent event on one of the signals in the implied
sensitivity list that causes the boolean expression to again be true for
the process to resume execution.
• If a wait statement contains both a sensitivity clause and a condition
clause, the boolean expression is evaluated only whcn an event occurs
on a signal in the sensitivity clause. For example, the statement
Wait on ie until interrupt = ‘1’;
• will resume the process when signal ie changes value and signal
interrupt = '1'
• In this case, interrupt does not have to change value for the process to
resume.
• A wait for statement causes a process to suspend for a time-out interval
equal to its associated time expression. After the time-out interval
elapses, the process automatically resumes.
Assertion statements
• An assertion statement checks whether a specified condition (the
assertion) is true. if it is not true, a message is displayed. This approach
can eliminate the need to visually inspect simulator waveforms.
• An assertion statement always has the required assert clause.
• The report and severity clauses are optional.
• Note that an assertion statement is a single statement and only one
semicolon is used, and must be at the very end of the statement.
• When verifying output values in a testbench, the condition we put in
an assertion statement equates the actual output value to its expected
value.
• If the condition in the assert statement evaluates false, an assertion
violation occur!
• The severity clause allows a severity level to be assigned.
• This level indicates the degree to which an assertion violation affects
operation of the system and what actions the simulator must take.
• The levels are enumeration literals of the type ( severity_level, ) which
is predefined in package STANDARD as:
• type severity_level is ( note, warning, error, failure) ;
• If the simulation completes and no reports are displayed, it is assumed
that the UUT performed as expected.
Report statements
• In addition to the report clause in an assertion statement, there is a
separate statement called a report statement.
• A report statement displays a message every time it is executed. If its
severity clause is omitted, its severity level defaults to note (instead of
error). Whenever executed, a report statement always generates the
message associated with the report expression.
• Report statements and report clauses in assertion statements only
accept a single string.
• However, this string can be produced by concatenating substrings.
• The string is displayed as a single line, unless the special character
constants CR (carriage return) and/or LF (line feed) are used in the
concatenation of substrings.
• A simple way to specify both stimulus and expected response values is
to use a table of constants
• A convenient way to represent a row of the table is as a record.
• A record is a composite type that consists of named elements that may
be of different type,.
• Elements in a record are selected by name, not by an index number
• The identifiers of all the elements of a record type must be distinct.
The value of a record object is the composite value of its elements.
• record_declaration ::= type identifier is record
• Identifier_list : element_subtype_definition ;
• { identifier_list : element_subtype_definition ; }
• end record [ record_type_simple_name ]
• For example, to declare a record for a test vector for the half adder we
can write:
• type test vector is record a : std_logic;
• b : std_logic;
• sum: std_logic; carry_out std_logic;
• end record;
• The table of constants that comprises all of the test vectors is an array
of records of type test_vector.
• This unconstrained array is declared as follows:
• type test_vector_array is array (natural range <» of test_vector;
• constant test_vectors: test_vector_array := a, b,
sum, carry_out
• (a = > '0', b = > '0’ , sum => ‘0’,carry_out=>’0’) ,
(a => '0', b => '1', sum => '1', carry_out=> ‘0’),
• (a => '1', b => '0', sum => '1', carry_out =>’0’),
• (a = > '1', b = > '1', sum = > '0', carry_out =>' l' )) ;
Table lookup testbench
• library ieee;
• use ieee.std_logic 1164.all;
• entity testbench is
• end testbench;
• -- Stimulus signals
• signal a : std_logic; signal b : std_logic;
• -- Observed signals
• signal sum: std_logic; signal carry_out : std_logic;
• -- Declare record type
• type test_vector is record
• a : std_logic;
• b : std logic;
• sum : std_logic;
• carry out :std_logic;
• end record;
• Type test _vector _array is array (natural range<>) of test _vector;
• constant test _ vectors : test_vector _ array:=
• .--- a, b, sum, carry_out
• (‘0’ ,’0’, '0‘,’0’),
• (' 0',’1’,’1’,’0’)
• ('1' ,’0 ‘,’1’, '0')
• ('1', '1', '0', '1'));
• !JUT entity half_adder
• port map (a => a, b => b, sum => sum, carry out => carry_out);
• verify process begin
• for i in test_vectors'range loop
• a <= test_vectors (i) .a; b <= test_vectors (i) .b;
• assert (( sum = test_vectors (i) .sum )
• and (carry_out = test vectors (i) .carry out))
• report "test vector " & integer'image(i) & " failed"&
• " for input a ="& std_logic' image (a)
• & " and b = " & std logic' image (b)
• severity error;
• end loop;
• wait;
• end process;
• end table;
Testbench that compute stimulus and
expected results
• In previous testbenches, expected output values were predetermined
for each input combination and included in the testbench as literals.
• Alternatively, a testbench can be written so that the expected output
values are computed during the simulation,
• In a single process testbench, the same process is used to apply
stimulus and compute and verify expected results

• library ieee;
• use ieee.std_loglc l164.all;
• use ieee. numeric std. all;
• entity testbench is
• end testbench;
• architecture behavior of testbench is
• -- Declare signals to assign values to and to observe
• signal a tb, b_tb, sum_tb, carry_out tb std_logic;
• begin
• Create an instance of the circuit to be tested
• uut: entity half adder port map(a => a tb, b => b tb, sum => sum_tb,
carry_out => carry_out tb);
• Define a process to apply input stimulus and test outputs
• tb : process
• constant period: time := 20 ns; constant n: integer := 2;
• begin
• -- Apply every possible input combination
• for i in 0 to 2**n – 1 loop
• (a_tb, b_tb) <= to_unsigned(i,n);
• wait for period;
• assert ((sum_tb = (a_tb xor b_tb)) and (carry _out_tb =(a _tb and
b_tb))
• report "test failed" severity error;
• end loop;
• wait; -- indefinitely suspend process
• end process;
• end;
• In previous testbenches the stimulus values were applied by
aggregating all inputs into a single vector and counting this vector
through all of its possible values starting from 0.
• It is often preferable, particularly for more complex combinational
systems, to apply stimulus values in an order that is related to the
functionality of the UUT.
• That is, values are applied to certain UUT control inputs to put the
UUT in a particular mode of operation.
• Other inputs are then sequenced through all of their values.
• This verifies each different mode of operation of the UUT in a logical
fashion. While this may lead to a textually longer stimulus process, it
is often more readable and understandable to others
• library ieee;
• use ieee.numeric std.all; use ieee.std_logic 1164.all;
• entity iC74f539_tb is
• end ic74f539 tb;
• architecture tb architecture of ic74f539 tb is
• -- Stimulus signals
• signal a : std_logic_vector(l downto 0);
• signal p : std_logic;
• signal e _ bar : std_loglc;
• signal oe_bar : std_logic;
• -- Observed signals
• signal 0 : std_logic_vector(3 downto 0);
• -- stimulus application interval
• constant period: time := 20 ns;

• Unit Under Test port map
• UUT : entity ic74f539
• port map (a => a, p => p, e bar => e bar, oe bar => oe_bar, o => 0) ;
• Stimulus and monitor process
• Stim _mon: process
• Variable o _ exp: std_logic _ vector(3 downto 0);
• begin
• -- verify output enable functionality
• oe_bar <= '1';
• for i in 0 to 15 loop
• (p, e_bar, a(l), a(0)) <= to_unsigned(i, 4);
• wait for period;
• assert (o = "ZZZZ") report "output enable failed" severity error;
• end loop;
• -- verify enable unasserted functionality
• oe bar <= '0';
• e_bar <= '1';
• for i in 0 to 7 loop
• (p, a(l), a(0)) <= to _ unsigned(i, 3);
• wait for period;
• o_exp := p & p & p & p;
• assert (o = o_exp) report "enable unasserted failed" severity error;
• end loop;
• -- verify enable asserted decoder functionality
• e_bar <= '0';
• for i in 0 to 7 loop
• (p, a(l), a(0)) <= to_unsigned(i, 3);
• wait for period;
• o exp := (p & p & p & p) xor to _ std _logic _vector(“000l" rol
to _ integer (unsigned(a) ));
assert (0 = o_exp) report "enable asserted failed" severity error;
• end loop;
• wait;
• end process;
Sequential ckt testbench
• All synchronous systems require system clock. So a testbench must
provide this signal.
• System clocks are often specified as having a 50% duty cycle. An
example of a 50 % duty cycle clock generated using a concurrent
signal assignment statement is where constant period specifies the
clock's period and is declared in the declarative part of the testbench
architecture.
• Clk <= not clk after period/2;
• Where constant period specifies the clock’s period and is declared in
the declarative part of the testbench architecture.
• Signal clk must be given an initial value of either , ‘0' or '1' when it is
declared. Otherwise, since the not of 'U' is 'U', the clock would remain
'U' throughout the simulation.
Process to generate 50% clock
• clock_gen: process
• constant period: time := 100 ns;
• begin
• clk <= '0'; Initial phase of the clock
• loop
• wait for period/2;
• clk <= not clk;
• end loop;
• end process;
• when simulating a sequential system without using a time limit, the
system clock generated by either of the previous methods runs
continuously.
• The simu1ation does not end because the clock is always generating
new events, even after the last data or control stimulus has been
applied.
• As a result, if the clock is nol stopped, the simulation does not stop.
• A boolean signal can be used to stop the clock.
• For example, if boolean signal end _ sim is assigned the value false at
the beginning of the testbench, the clock runs until end_sim is assigned
the value true.
• clock_gen : process
• begin
• clk <= '0';
• loop
• wait for period/2;
• clk <= not clk;
• exit when end sim true;
• end loop;
• wait;
• end process;
• clock_gen: process .
• constant duty_cycle real:= 0.40;
• constant period: time := 100 ns ;
• constant clk_high: time := duty_cycle * period
• begin
• loop
• clk <= '0';
• wait for period - clk_high; clock low time
• clk <= '1';
• wait for clk_high; -- clock high time
• end loop;
• end process;
• end behavioral;
Process for a reset pulse
• reset: process
• begin
• Reset _ bar <= '0';
• for i in 1 to 2
• loop
• wait until clk = '1';
• end loop;
• reset _ bar <= '1';
• wait;
• end process;
• This process first assigns a '0' to reset _bar.
• A loop then counts two rising edges of clk.
• After these two rising edges, reset_bar is assigned a ‘1'.
• An advantage of this approach is that if the system clock period is
changed, the reset pulse is automatically adjusted to provide the
minimum required duration.
Monitor process for n bit binary counter

• monitor: process
• constant n : integer .- 2; -- number of bits in counter
• begin
• for i in 1 to 2 loop skip clocks while counter is reset
• wait until clk = '1';
• end loop;
• wait for 1 ns;
• for i in 0 to 2**n loop - - count until clock rolls over to 0
• assert count = (std_logic_vector(to_unsigned(i mod 2**n, n)))
• report "Count of " & integer'image (i mod 2**n) & " failed“
• severity error;
• wait until clk = '1';
• wait for 1 ns ;
• end loop;
• end sim <= true;
• wait;
• end process;
• The first loop in process monitor skips the first two triggering clock
edges, which occur while the counter is reset. Since we are skipping
the clock edges that occur while the counter is reset, a simpler
alternative is to replace the first loop with the instruction:
Two-phase clock generated by
concurrent calls to a procedure
• library ieee;
• use ieee.std_Iogic 1164.al1;
• entity shaft encoder is
• port ( clk_a : out std_logic; clk_b : out std_logic);
• end shaft_encoder;
• architecture behavioral of shaft encoder is
• procedure clock_gen (signal clk: out std logic;
• constant period, high, phase : in time ) is
• begin
• clk <= '0';
• wait for phase;
• loop
• clk <= '1', '0' after high;
• wait for period;
• end loop;
• end clock_gen;
• begin
• clock_gen (clk_a, 100 ns, 50 ns, 0 ns);
• clock_gen (clk_b, 100 ns, 50 ns, 25 ns) ;
• end behavioral;
USING PROCEDURES FOR
STIMULUS GENERATION
• A useful approach to generating stimulus waveforms is to
focus on the operations that can be performed by a UUT
and write procedures to encapsulate the stimulus to
activate those operations.
• These procedures are written so that they synchronize
themselves to the system clock.
• In the testbench, these procedures are simply called in the
appropriate order to produce the desired sequence of UUT
operations.
• For example, operations for a D flip-flop require only three
procedures: a set procedure, a clear procedure, and a load
procedure.
Procedure that generates stimulus to load a D
flip-flop with synchronous set and clear
• procedure load( din: in std logic;
• signal elk: in std logic;
• signal d : out std_logic;
• signal set_bar: out std_logic;
• signal clr bar : out std_logic) is
• begin
• d <= din;
• set bar <= '1';
• clr bar <= '1';
• wait on clk until clk ='1'; - - wait for rising edge of clock
• wait for thold;
• d <= 'X';
• set_bar <= 'X';
• clr_bar <= 'X';
• wait for period - thold - tsetup;
• end load;
Testbench for D flip-flop using
procedures
• library ieee;
• use ieee.std_logic l164.all;
• entity d_ff_pe_ssc_tb is
• end d_ff-pe_ssc_tb;
• Architecture tb_architecture of d_ff_pe_ssc_tb is
• -- Signals mapped to the input ports of tested entity
• signal d : std_logic;
• signal clk : std_logic := '0';
• signal set_bar : std_logic;
• signal clear bar : std logic;
• -- Signals mapped to the output ports of tested entity
• signal q : std_logic;
• -- Constants
• constant period: time := 100 ns;
• constant tsetup : time := 10 ns;
• constant thold : time := 2 ns;
• procedure clear (
• Signal clk : in std_logic; signal d : out std_logic;
• signal set bar : out std_logic ;
• Signal clr bar: out std_logic; )
• begin
• d <= '1';
• set bar <= '1';
• clr bar <= '0';
• wait on clk until clk =‘1’;
• wait for thold;
• d <= 'X';
• set_bar <= 'X';
• clr_bar <= 'X';
• wait for period - thold - tsetup;
• end clear;
• procedure set(
• signal clk: in std_logic;
• signal d : out std_logic;
• signal set bar: out std_logic;
• signal clr bar : out std_logic) is
• begin
• d <= '0';
• set bar <= '0';
• clr bar <= '1';
• wait on clk until clk = '1';
• wait for thold;
• d <= 'X';
• set_bar <= 'X';
• clr_bar <= 'X';
• wait for period - thold - tsetup;
• end set;
• procedure load( din : in std logic;
• signal clk : in std logic;
• signal d : out std_logic;
• signal set bar : out std_logic;
• signal clr bar: out std_logic;) is
• begin
• d <= din;
• set bar <= '1';
• clr bar <= '1';
• wait on clk until clk=‘1’;
• wait for thold;
• d <= 'X';
• set_bar <= ' X' ;
• clr_bar <= 'X';
• wait for period - thold - tsetup;
• end load;
• Begin
• Unit Under Test port map
• UUT : entity d_ff-pe_ssc
• port map (d => d, clk => clk, set_bar => set bar, clear_bar =>
clear_bar, q => q );
• Clock generation
• clock_gen: clk <= not clk after period/2;
• - - Test case
• operations : process
• begin
• clear(clk, d, set bar, clear bar);
• load('l', clk, d, set_bar, clear_bar);
• load('O', clk, d, set_bar, clear_bar);
• set(clk, d, set_bar, clear_bar);
• load('O', clk, d, set_bar, clear_bar);
• load('l', clk, d, set_bar, clear_bar);
• wait;
• end process;
• End tb_architecture;
OUTPUT VERIFICATION IN
STIMULUS PROCEDURES
• Using assertion statements in a stimulus procedure to verify outputs.
• procedure load(
• din : in std_logic;
• signal clk : in std_logic;
• signal d : out std_logic;
• signal set_bar out std_logic; signal clr bar : out std_logic) is
• begin
• d <= din;
• set bar <= '1';
• Clk_bar<= '1‘;
• Wait on clk until clk = ‘1’;
• assert q' stable (period - teo) - - Cheek previous output
remained stable report "previous output not stable",
• wait for thold,
• d <= 'X',
• set_bar <= 'X',
• clr_bar <= 'X',
• wait for tco – thold;
• assert q = din Check new output is correct
• report "load operation failed",
• wait for period – tco - tsetup,
• end load;
Library ieee;
Use ieee.std_logic_1164.all;
Entity even_ detector_ testbench is
End even_ detector_ testbench;
Architecture arch of even_ detector_ testbench is
Component even_detector
Port( a: in std_logic_vector(2 downto 0);
Even: out std_logic);
End component;
Signal testin: std_logic_vector(2 downto 0);
Signal testout: std_logic;
Begin
U1:even_detector
• Port map(a=>testin, even=>testout);
• Process
• Begin
• Testin<=“000”;
• Wait for 200 ps;
• Testin<=“001”;
• Wait for 200 ps;
• Testin<=“010”;
• Wait for 200 ps;
• Testin<=“011”;
• Wait for 200 ps;
• Testin<=“100”;
• Wait for 200 ps;
• Testin<=“101”;
• Wait for 200 ps;
• Testin<=“110”;
• Wait for 200 ps;
• Testin<=“111”;
• Wait for 200 ps;
• End process;
• Process
• Variable error_status: boolean;
• Begin
• Wait on testin;
• Wait for 200 ps;
• If((testin=“000” and testout=‘1’)or
• (testin=“001” and testout=‘0’)or
• testin=“010” and testout=‘0’)or
• testin=“011” and testout=‘1’)or
• testin=“100” and testout=‘0’)or
• testin=“101” and testout=‘1’)or
• testin=“110” and testout=‘1’)or
• testin=“111” and testout=‘0’))
• Then
• Error_status:= false;
• Else
• Error_status:= true;
• End if;
• Assert not error_status
• Report “test failed”
• Severity note;
• End process;
• End arch;
• Another way to apply stimulus to a set of signals is to store the set of vectors
in a constant table or in an ASCII file. Here is an example that stores the input
vectors in a table.
• constant NO_OF_BITS: INTEGER := 4;
• constant NO_OF_VECTORS: INTEGER := 5;
• type TABLE_TYPE is array (1 to NO_OF_VECTORS) of
• MVL_VECTOR(1 to NO_OF_BITS);
• constant VECTOR_PERIOD: TIME := 100 ns;
• constant INPUT_VECTORS: TABLE_TYPE :=
• ("1001", "1000", "0010", "0000", "0110");
• signal INPUTS: MVL_VECTOR(1 to NO_OF_BITS);
• signal A, B, C: MVL;
• signal D: MVL_VECTOR(0 to 1);
• Assume that the entity under test has four inputs. A, B, C, and D. If the vectors
are to be applied at regular time intervals, a generate statement can be used as
shown.
• G1: for J in 1 to NO_OF_VECTORS generate
• INPUTS <= INPUT_VECTORS(J) after (VECTOR_PERIOD * J);
• end generate G1;
• A<= INPUTS(1);
• B <= INPUTS(4);
• C<=INPUTS(1);
• D<=INPUTS(2 to 3);
• If the vectors were to be applied at arbitrary intervals, a concurrent signal
assignment statement with multiple waveforms can be used.
• INPUTS <= INPUT_VECTORS(1) after 10 ns,
• INPUT_VECTORS(2) after 25 ns,
• INPUT_VECTORS(3) after 30 ns,
• INPUT_VECTORS(4) after 32 ns,
• INPUT_VECTORS(5) after 40 ns;
• Using this approach, it is possible to assign one vector column to more than
one signal.
• The input vectors could also be specified in an ASCII file as a sequence of
values. The following statements define a file and read the vectors from the
file.
• process
• type VEC_TYPE is file of MVL.VECTOR;
• file VEC_FILE: VEC_TYPE is in "/usr/jb/EXAMPLE.vec";
• variable LENGTH: INTEGER;
• variable IN_VECTOR: MVL_VECTOR(1 to 4);
• begin
• LENGTH := 4; - The number of bits to be read.
• while (not ENDFILE(VEC_FILE)) loop
• READ (VEC_FILE, tN_VECTOR, LENGTH);
• - It is necessary to specify the LENGTH of the vector to be read
• - since the file contains values of an unconstrained array type.
• :
• :
• end loop;
• end process;
Library ieee;
Use ieee.std_logic_1164.all;
Entity even_ detector_ testbench is
End even_ detector_ testbench;
Architecture arch of even_ detector_ testbench is
Component even_detector
Port( a: in std_logic_vector(2 downto 0);
Even: out std_logic);
End component;
Signal testin: std_logic_vector(2 downto 0);
Signal testout: std_logic;
Begin
U1:even_detector
• Port map(a=>testin, even=>testout);
• Process
• Begin
• Testin<=“000”;
• Wait for 200 ps;
• Testin<=“001”;
• Wait for 200 ps;
• Testin<=“010”;
• Wait for 200 ps;
• Testin<=“011”;
• Wait for 200 ps;
• Testin<=“100”;
• Wait for 200 ps;
• Testin<=“101”;
• Wait for 200 ps;
• Testin<=“110”;
• Wait for 200 ps;
• Testin<=“111”;
• Wait for 200 ps;
• End process;
• Process
• Variable error_status: boolean;
• Begin
• Wait on testin;
• Wait for 200 ps;
• If((testin=“000” and testout=‘1’)or
• (testin=“001” and testout=‘0’)or
• testin=“010” and testout=‘0’)or
• testin=“011” and testout=‘1’)or
• testin=“100” and testout=‘0’)or
• testin=“101” and testout=‘1’)or
• testin=“110” and testout=‘1’)or
• testin=“111” and testout=‘0’))
• Then
• Error_status:= false;
• Else
• Error_status:= true;
• End if;
• Assert not error_status
• Report “test failed”
• Severity note;
• End process;
• End arch;
• Another way to apply stimulus to a set of signals is to store the set of vectors
in a constant table or in an ASCII file. Here is an example that stores the input
vectors in a table.
• constant NO_OF_BITS: INTEGER := 4;
• constant NO_OF_VECTORS: INTEGER := 5;
• type TABLE_TYPE is array (1 to NO_OF_VECTORS) of
• MVL_VECTOR(1 to NO_OF_BITS);
• constant VECTOR_PERIOD: TIME := 100 ns;
• constant INPUT_VECTORS: TABLE_TYPE :=
• ("1001", "1000", "0010", "0000", "0110");
• signal INPUTS: MVL_VECTOR(1 to NO_OF_BITS);
• signal A, B, C: MVL;
• signal D: MVL_VECTOR(0 to 1);
• Assume that the entity under test has four inputs. A, B, C, and D. If the vectors
are to be applied at regular time intervals, a generate statement can be used as
shown.
• G1: for J in 1 to NO_OF_VECTORS generate
• INPUTS <= INPUT_VECTORS(J) after (VECTOR_PERIOD * J);
• end generate G1;
• A<= INPUTS(1);
• B <= INPUTS(4);
• C<=INPUTS(1);
• D<=INPUTS(2 to 3);
• If the vectors were to be applied at arbitrary intervals, a concurrent signal
assignment statement with multiple waveforms can be used.
• INPUTS <= INPUT_VECTORS(1) after 10 ns,
• INPUT_VECTORS(2) after 25 ns,
• INPUT_VECTORS(3) after 30 ns,
• INPUT_VECTORS(4) after 32 ns,
• INPUT_VECTORS(5) after 40 ns;
• Using this approach, it is possible to assign one vector column to more than
one signal.
• The input vectors could also be specified in an ASCII file as a sequence of
values. The following statements define a file and read the vectors from the
file.
• process
• type VEC_TYPE is file of MVL.VECTOR;
• file VEC_FILE: VEC_TYPE is in "/usr/jb/EXAMPLE.vec";
• variable LENGTH: INTEGER;
• variable IN_VECTOR: MVL_VECTOR(1 to 4);
• begin
• LENGTH := 4; - The number of bits to be read.
• while (not ENDFILE(VEC_FILE)) loop
• READ (VEC_FILE, tN_VECTOR, LENGTH);
• - It is necessary to specify the LENGTH of the vector to be read
• - since the file contains values of an unconstrained array type.
• :
• :
• end loop;
• end process;

You might also like