Writing Test Benches: A Free Application Note
Writing Test Benches: A Free Application Note
Introduction
Preamble
We will focus on Black Box Testing which is usually seen as the most daunting task (as
compared with Unitary “glass-box” testing).
So we are going to start with a with a practical and realistic example and go through these steps :
➢ Define the Verification Framework.
➢ Code the test bench skeleton.
➢ Add in the basic Stimuli (clock reset etc)
➢ Find or Design, then integrate a Behavioral Model
➢ Add some code for Self-Testing.
➢ Create a Tcl script to automate the simulation.
➢ Run the simulation and debug both the UUT and the Test Bench !.
This seems a pretty ambitious program and difficult tasks, but we'll see it's not the case provided
you know your HDL basics (that's what our Training courses are for !).
This Application will use VHDL, but it maps directly to (System)Verilog.
© 2009 - ALSE Writing Test Benches www.ALSE-FR.com
Practical Example
Note: This ApNote is about considering the Unit Under Test (UUT) as a “black box” and exercise it,
while it's in fact a single unitary module. In real life, our test bench would rather be part of unitary
verification. In a “glass box” context, we would try to exercise all the code and verify all the features
coded inside (like the initial deadtime).
For the sake of this Application Note, we will not examine the code inside, but only consider the encoder
as a “system”, or a “black box”.
Here is the Entity declaration for the function we want to test. We do not need the architecture ! In fact,
in the “black box” methodology, we should not even have access to the architecture...
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
-- --------------------------------------------
Entity QUAD is
-- --------------------------------------------
port( Rst : in std_logic; -- Asynchronous Reset
Clk : in std_logic; -- System Clock
A,B : in std_logic; -- Quadrature inputs (resynch'ed internally)
Cnt : out std_logic_vector(7 downto 0); -- (un)signed 8 bits position !
Dir : out std_logic); -- Clockwise information (of last step)
end entity QUAD;
You can open the source code (quad.vhd), copy the above piece of code and save it in your new
test bench file.
Important : make sure you have a Text Editor you're reasonably familiar with, and that this editor has a
column mode and supports VHDL syntax-coloring. If you don't have this, consider the small and free
Text Editor “Crimson”.
➢ Create a new file named QUAD_TB.vhd and paste the Entity declaration (preceded by the
libraries) from the original file QUAD.vhd, as seen previous page.
Remove the comment lines, but keep the comments after the ports.
We have outlined in bold characters the code added or modified from this original piece.
➢ Add a Header with the file name and minimal information
➢ Add the two library statements in bold for STD.TEXTIO and IEEE.STD_LOGIC_TEXTIO.
➢ Add the Test bench Entity declaration, in one line (there is no port in a Test Bench).
➢ Add the test bench Architecture with the Begin and End architecture declarations.
➢ Remove the end entity quad; line
➢ Copy Again the Entity declaration and paste it between the Begin and End of the test bench
architecture.
➢ Delete Entity QUAD is port below Architecture (in italic below).
-- QUAD_TB.vhd
-- Test Bench for QUAD
use STD.TEXTIO.all;
Library IEEE;
use IEEE.std_logic_TEXTIO.all;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
Entity QUAD_TB is end;
Architecture TEST of QUAD_TB is
Entity QUAD is
port( Rst : in std_logic; -- Asynchronous Reset
Clk : in std_logic; -- System Clock
A,B : in std_logic; -- Quadrature inputs (resynch'ed internally)
Cnt : out std_logic_vector; -- Position is an unconstrained vector
Dir : out std_logic); -- Clockwise information (of last step)
Begin -- Architecture
Entity QUAD is
port( Rst : in std_logic; -- Asynchronous Reset
Clk : in std_logic; -- System Clock
A,B : in std_logic; -- Quadrature inputs (resynch'ed internally)
Cnt : out std_logic_vector(7 downto 0); -- (un)signed 8 bits position !
Dir : out std_logic); -- Clockwise information (of last step)
End Architecture TEST;
Noe the use of an unconstrained vector for the position information (Cnt). This is a very nice feature in
VHDL. In our case, the actual size of the counter inside the encoder will be determined by the
instantiation in the Test bench (we'll use a size of eight bits).
Begin -- Architecture
UUT: Entity work.QUAD port map (
Rst => Rst,
Clk => Clk,
A => A ,
B => B ,
Cnt => Cnt,
Dir => Dir );
End Architecture TEST;
Note : every designer should know how to quickly write a test bench without help, but some tools can do
the above steps for you, like the free Text Editor Emacs with its sophisticated VHDL mode written by
Reto Zimmermann. There is not much intrinsic value in the steps above, very mechanical.
The Stimuli !
For a simple Test bench and quick verification, we could stop here.
Simulation Automation
Step 5 : Automate
By definition, we are probably going to run the same simulation many times during the development
phase, and probably also later (like for non-regression testing). In both cases, it is important to not rely
on the user to drive all the steps involved, from creating the working library to compiling the proper files,
to loading the right test bench, running the simulation and collate the results.
During the development, the issue is the productivity.
Later, the issue is to be able to reliably re-run a specific test without having to remember or know a lot.
A simple solution is to write a script like this one :
# simquad.do
puts "-- Simulation script (c) ALSE for QUAD encoder --"
vlib work
vcom -93 quad.vhd
vcom -93 quad_tb.vhd
vsim quad_tb
add wave -divider "QUAD (c) ALSE"
add wave A
add wave B
add wave -divider "Outputs:"
add wave Dir
add wave -radix decimal Cnt
run -a
Conclusion
Conclusion
After spending more than 15 years advocating for the use of simulation in FPGA design, I hope this
Application Note will encourage young (and less young !) FPGA Designers into spending more time
upfront for creating solid test benches... and indeed thus saving a lot of time later chasing problems in
hardware.
Bertrand CUZEAU
Technical Manager A.L.S.E.
Write to : info at alse–fr dot com