Background


Previous page | Content| Home

Testbench and simulation

Bahavioral simulation

Figure 43: Structure of a test bench

It is essential to catch bugs as early as possible in the design process, since the time to find and correct a bug increases by an order of magnitude at each level of design integration. The motivation for simulation is therefore to be able to test designs prior to construction and use of the circuit. A test bench is the part of the description that models the environment of the system and permits its testing by supplying stimuli to the input ports of the model under test.
A test bench consists of three modules: As illustrated in Fig. 43, the module tester.vhd generates the stimulus to be applied. A second module model.vhd is the model being tested. The top level module testbench.vhd describes the interconnections between the tester and the model under test.
The design process includes two types of simulation. Behavioral simulation is carried out after the required components and the matching test bench have been created. It is used to detect logical errors in the behavior described by the design and cannot ensure that the VHDL code can also be synthesized. Only back annotation simulation, which is the last step after placing and routing the design, permits a simulation that takes real hardware structure and group delay times into consideration.
All components of the design are simulated using a specific test bench that describes the environmental conditions where the component is located. It is intended to cover each state of input signals that could be obtained, when the design is implemented in the device. A detailed description of all test benches would go beyond the scope of this chapter.
One top level test bench is more closely examined below. It is important to take into consideration that several VHDL descriptions of the test benches contain elements that cannot be synthesized, e.g. the AFTER clause. These components are designed especially for the purpose of simulation.

Test bench for the component ProcessingUnit

This test bench applies a cyclic sensor signal to the processing unit, generated in three steps. Clock_Generator provides HIGH pulses with a period adjusted by the generic parameter ClockPeriod on SystemClock_1. The pulse duty ratio of the output signal, as defined by the subsequent formula, is v = 0.5.

Figure 44: Output waveform of the component Clock_Generator

ImpulsGen generates a pulse with a width of tp = 10 ms. This signal must still be inverted, since ReedContact_In is a LOW active signal. By changing the parameter ClockPeriod, any speed value can therefore be simulated.

Figure 45: Signal transformation by the component ImpulsGen

Initially PerimeterImpulsGen generates pulses on IncWheel to test the wheel circumference setting. ProcessingUnit_tester provides an initial system reset on the line Reset.

Figure 46: Test bench for ProcessingUnit

Furthermore it controls the DisplayMode in order to determine the actual active display mode, New_DisplayMode, indicating a change of the display mode and Reset_Computer for resetting the measured values. The System_Clock_Generator generates a 3.2768 Mhz system clock. For this the generic parameter ClockPeriod is assigned to the corresponding time period.

-- University of Applied Sciences / Munich
-- Federal Technological Education Center / Rio de Janeiro
-- =======================================================
-- = Project : Bicycle computer in VHDL                  =
-- = File    : processingunit_tb_struct.vhd              =
-- = Notes   : BikeCom.ProcessingUnit_tb                 =
-- =======================================================
-- = Datum   : 08.08.2001                                =
-- = Design  : Joachim Reiss                             =
-- = Revision: 001                                       =
-- =======================================================
--
--

--
-- VHDL Entity BikeCom.ProcessingUnit_tb.symbol
--

ENTITY ProcessingUnit_tb IS

END ProcessingUnit_tb ;

--
-- VHDL Architecture BikeCom.ProcessingUnit_tb.struct
--

LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
LIBRARY BikeCom ;
USE BikeCom.data.ALL;

ARCHITECTURE struct OF ProcessingUnit_tb IS

   -- Internal signal declarations
   SIGNAL DisplayMode          : AllModes;
   SIGNAL ImpulsOut            : std_logic;
   SIGNAL LCD_BCD              : std_logic_vector(19 DOWNTO 0);
   SIGNAL New_DisplayMode      : std_logic;
   SIGNAL Print_BCD            : std_logic;
   SIGNAL ReedContact_In       : std_logic;
   SIGNAL Reset                : std_logic;
   SIGNAL Reset_Computer       : std_logic;
   SIGNAL SystemClock          : std_logic;
   SIGNAL SystemClock_1        : std_logic;
   SIGNAL WheelPerimeterAdjust : std_logic;

   -- Component Declarations
   COMPONENT Clock_Generator
   GENERIC (
      ClkPeriod : Time := 10 ms
   );
   PORT (
      ResetClock : IN     std_logic ;
      Clock      : OUT    std_logic 
   );
   END COMPONENT;
   COMPONENT ImpulsGen
   PORT (
      FallingEdge_In : IN     std_logic ;
      Reset          : IN     std_logic ;
      Systemclock    : IN     std_logic ;
      ImpulsOut      : OUT    std_logic 
   );
   END COMPONENT;
   COMPONENT PerimeterImpulsGen
   PORT (
      WheelPerimeterAdjust : OUT    std_logic 
   );
   END COMPONENT;
   COMPONENT ProcessingUnit
   GENERIC (
      CompareValue_KmActual : std_logic_vector(16 DOWNTO 0) := "00000001111101000";
      CompareValue_KmTotal  : std_logic_vector(16 DOWNTO 0) := "11000011010100000";
      StopOnTimeOut         : std_logic_vector(13 DOWNTO 0) := "11101001001000"
   );
   PORT (
      Clock           : IN     std_logic ;
      DisplayMode     : IN     AllModes ;
      Inc_Wheel       : IN     std_logic ;
      New_DisplayMode : IN     std_logic ;
      Reed            : IN     std_logic ;
      Reset           : IN     std_logic ;
      Reset_Computer  : IN     std_logic ;
      LCD_BCD         : OUT    std_logic_vector (19 DOWNTO 0);
      Print_BCD       : OUT    std_logic 
   );
   END COMPONENT;
   COMPONENT ProcessingUnit_tester
   PORT (
      LCD_BCD         : IN     std_logic_vector (19 DOWNTO 0);
      Print_BCD       : IN     std_logic ;
      DisplayMode     : OUT    AllModes ;
      New_DisplayMode : OUT    std_logic ;
      Reset           : OUT    std_logic ;
      Reset_Computer  : OUT    std_logic 
   );
   END COMPONENT;
   COMPONENT System_Clock_Generator
   GENERIC (
      ClockPeriod : Time := 305175 ps
   );
   PORT (
      SystemClock : OUT    std_logic 
   );
   END COMPONENT;

   -- Optional embedded configurations
   -- pragma synthesis_off
   FOR ALL : Clock_Generator USE ENTITY BikeCom.Clock_Generator;
   FOR ALL : ImpulsGen USE ENTITY BikeCom_Reiss.ImpulsGen;
   FOR ALL : PerimeterImpulsGen USE ENTITY BikeCom.PerimeterImpulsGen;
   FOR ALL : ProcessingUnit USE ENTITY BikeCom.ProcessingUnit;
   FOR ALL : ProcessingUnit_tester USE ENTITY BikeCom.ProcessingUnit_tester;
   FOR ALL : System_Clock_Generator USE ENTITY BikeCom.System_Clock_Generator;
   -- pragma synthesis_on

BEGIN
   -- Architecture concurrent statements
   -- eb1 1 
   ReedContact_In <= NOT (ImpulsOut);

   -- Instance port mappings.
   I3 : Clock_Generator
      GENERIC MAP (
         ClkPeriod => 43720 us
      )
      PORT MAP (
         ResetClock => Reset,
         Clock      => SystemClock_1
      );
   I4 : ImpulsGen
      PORT MAP (
         FallingEdge_In => SystemClock_1,
         Reset          => Reset,
         Systemclock    => SystemClock,
         ImpulsOut      => ImpulsOut
      );
   I5 : PerimeterImpulsGen
      PORT MAP (
         WheelPerimeterAdjust => WheelPerimeterAdjust
      );
   I0 : ProcessingUnit
      GENERIC MAP (
         CompareValue_KmActual => "00000001111101000",
         CompareValue_KmTotal  => "11000011010100000",
         StopOnTimeOut         => "11101001001000"
      )
      PORT MAP (
         Clock           => SystemClock,
         DisplayMode     => DisplayMode,
         Inc_Wheel       => WheelPerimeterAdjust,
         New_DisplayMode => New_DisplayMode,
         Reed            => ReedContact_In,
         Reset           => Reset,
         Reset_Computer  => Reset_Computer,
         LCD_BCD         => LCD_BCD,
         Print_BCD       => Print_BCD
      );
   I1 : ProcessingUnit_tester
      PORT MAP (
         LCD_BCD         => LCD_BCD,
         Print_BCD       => Print_BCD,
         DisplayMode     => DisplayMode,
         New_DisplayMode => New_DisplayMode,
         Reset           => Reset,
         Reset_Computer  => Reset_Computer
      );
   I2 : System_Clock_Generator
      GENERIC MAP (
         ClockPeriod => 305175 ps
      )
      PORT MAP (
         SystemClock => SystemClock
      );

END struct;

Clock generator

Figure 47: Output ports of the component
System_Clock_Generator

This component provides at the output port SystemClock an alternating signal with a pulse duty ratio v of 0.5. The architecture body declares a constant of the type time containing the generic value ClockPeriod defined in the entity System_Clock_ Generator. Sys_clk_tmp stores the internal state of the clock generator.
The process process0 is sensitive to the signal sys_clk_tmp and is reactivated on each transition of this signal. The AFTER clause specifies the scheduling for the assignment of the right-hand side to sys_clk_tmp. The signal inverts itself after a half period of ClockPeriod. Each signal assignment of sys_clock_tmp transfers the actual state of this signal to the output port System_Clock.

-- University of Applied Sciences / Munich
-- Federal Technological Education Center / Rio de Janeiro
-- =======================================================
-- = Project : Bicycle computer in VHDL                  =
-- = File    : system_clock_generator_flow.vhd           =
-- = Notes   : BikeCom.System_Clock_Generator            =
-- =======================================================
-- = Datum   : 07.08.2001                                =
-- = Design  : Joachim Reiss                             =
-- = Revision: 001                                       =
-- =======================================================
--
--

--
-- VHDL Entity BikeCom.System_Clock_Generator.symbol
--

LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY System_Clock_Generator IS
   GENERIC( 
      ClockPeriod : Time := 305175 ps
   );
   PORT( 
      SystemClock : OUT    std_logic 
   );

-- Declarations

END System_Clock_Generator ;

--
-- VHDL Architecture BikeCom.System_Clock_Generator.flow
--

ARCHITECTURE flow OF System_Clock_Generator IS

   -- Architecture declarations
   CONSTANT sys_clk_prd : time := ClockPeriod;
   SIGNAL sys_clk_tmp : std_logic := '0';

BEGIN

   ---------------------------------------------------------------------------
   process0 : PROCESS (sys_clk_tmp)
   ---------------------------------------------------------------------------
   BEGIN
      sys_clk_tmp <= NOT sys_clk_tmp AFTER sys_clk_prd / 2;
      SystemClock <= sys_clk_tmp;
   END PROCESS process0;


END flow;

Resetable clock generator

Figure 48: Output ports of the component
Clock_Generator

For simulation of the reed sensor pulses a component is required that generates the time base for these pulses. This component provides an asynchronous reset input defined by the if-statement in process0. On condition that Falling_Edge detects a transition from HIGH to LOW on ResetClock, the internal signal clk_tmp takes on the level HIGH. Otherwise the process inverts clk_tmp after a period specified by the generic parameter ClkPeriod. The assignment of clk_tmp to Clock transfers the internal signal to the output port.

-- University of Applied Sciences / Munich
-- Federal Technological Education Center / Rio de Janeiro
-- =======================================================
-- = Project : Bicycle computer in VHDL                  =
-- = File    : clock_generator_flow.vhd                  =
-- = Notes   : BikeCom.Clock_Generator                   =
-- =======================================================
-- = Datum   : 08.08.2001                                =
-- = Design  : Joachim Reiss                             =
-- = Revision: 001                                       =
-- =======================================================
--
--

--
-- VHDL Entity BikeCom.Clock_Generator.symbol
--

LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY Clock_Generator IS
   GENERIC( 
      ClkPeriod : Time := 10 ms
   );
   PORT( 
      ResetClock : IN     std_logic  ;
      Clock      : OUT    std_logic 
   );

-- Declarations

END Clock_Generator ;

--
-- VHDL Architecture BikeCom.Clock_Generator.flow
--

ARCHITECTURE flow OF Clock_Generator IS

   -- Architecture declarations
   SIGNAL clk_tmp : std_logic := '0';

BEGIN

   ---------------------------------------------------------------------------
   process0 : PROCESS (ResetClock, clk_tmp)
   ---------------------------------------------------------------------------
   BEGIN
      IF Falling_Edge (ResetClock) THEN
         clk_tmp <= '1';
         Clock <= clk_tmp;
      END IF;
      clk_tmp <= NOT clk_tmp AFTER ClkPeriod;
      Clock <= clk_tmp;
   END PROCESS process0;


END flow;

Pulse generator

The generation of pulses triggered by synchronous input signal requires more complex processing. The component consists of a state machine, that detects falling edges of the input signal FallingEdge_In and monitors all other internal signals including that of the timer component TimeOut.

Figure 49: Block diagram of the component ImpulsGen

An incoming pulse on FallingEdge_In forces the state machine to initialize the counter TimeOut with InitValue, specified by embedded block eb2. The defined value is not the value transferred into the internal counter of the component, but determines the time in steps of 10 ms, until CarryOut signals that the down counter has run into underflow. ImpulsOut takes on the level HIGH. Now TimeOut counts down the internal register and provides a pulse on CarryOut, as soos as the counter has underflowed. After this, ImpulsOut returns to LOW level.

-- University of Applied Sciences / Munich
-- Federal Technological Education Center / Rio de Janeiro
-- =======================================================
-- = Project : Bicycle computer in VHDL                  =
-- = File    : impulsgen_struct.vhd                      =
-- = Notes   : BikeCom.ImpulsGen                         =
-- =======================================================
-- = Datum   : 08.08.2001                                =
-- = Design  : Joachim Reiss                             =
-- = Revision: 001                                       =
-- =======================================================
--
--

--
-- VHDL Entity BikeCom.ImpulsGen.symbol
--

LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY ImpulsGen IS
   PORT( 
      FallingEdge_In : IN     std_logic  ;
      Reset          : IN     std_logic  ;
      Systemclock    : IN     std_logic  ;
      ImpulsOut      : OUT    std_logic 
   );

-- Declarations

END ImpulsGen ;

--
-- VHDL Architecture BikeCom.ImpulsGen.struct
--

LIBRARY BikeCom_Reiss;

ARCHITECTURE struct OF ImpulsGen IS

   -- Internal signal declarations
   SIGNAL CarryOut  : std_logic;
   SIGNAL EnCnt     : std_logic;
   SIGNAL InitValue : std_logic_vector(13 DOWNTO 0);
   SIGNAL LoadCnt   : std_logic;

   -- Component Declarations
   COMPONENT ImpulsGen_StateMachine
   PORT (
      CarryOut       : IN     std_logic ;
      FallingEdge_In : IN     std_logic ;
      Reset          : IN     std_logic ;
      Systemclock    : IN     std_logic ;
      ImpulsOut      : OUT    std_logic ;
      LoadCnt        : OUT    std_logic 
   );
   END COMPONENT;
   COMPONENT TimeOut
   PORT (
      Systemclock : IN     std_logic ;
      EnCnt       : IN     std_logic ;
      InitValue   : IN     std_logic_vector (13 DOWNTO 0);
      Reset       : IN     std_logic ;
      CarryOut    : OUT    std_logic ;
      CountOut    : OUT    std_logic_vector (13 DOWNTO 0);
      LoadCnt     : IN     std_logic 
   );
   END COMPONENT;

   -- Optional embedded configurations
   -- pragma synthesis_off
   FOR ALL : ImpulsGen_StateMachine USE ENTITY BikeCom.ImpulsGen_StateMachine;
   FOR ALL : TimeOut USE ENTITY BikeCom.TimeOut;
   -- pragma synthesis_on

BEGIN
   -- Architecture concurrent statements
   -- eb1 1
   EnCnt <= '1';

   -- eb2 2
   InitValue <= "00000000000001";

   -- Instance port mappings.
   I1 : ImpulsGen_StateMachine
      PORT MAP (
         CarryOut       => CarryOut,
         FallingEdge_In => FallingEdge_In,
         Reset          => Reset,
         Systemclock    => Systemclock,
         ImpulsOut      => ImpulsOut,
         LoadCnt        => LoadCnt
      );
   I0 : TimeOut
      PORT MAP (
         Systemclock => Systemclock,
         EnCnt       => EnCnt,
         InitValue   => InitValue,
         Reset       => Reset,
         CarryOut    => CarryOut,
         CountOut    => OPEN,
         LoadCnt     => LoadCnt
      );

END struct;

The component ImpulsGen_StateMachine

The counter of TimeOut determines the width of the pulses on line ImpulsOut. Monitoring of this counter and the low active input line FallingEdge_In is by means of this state machine. The initial state WaitRisingEdge, or rather after one clock cycle Trigger_WaitRisingEdge, is used to detect transitions of FallingEdge_In from HIGH to LOW. In this case the state machine moves to the state Impuls, where it sets the output line ImpulsOut to HIGH and restarts the down counter TimeOut by HIGH level on LoadCnt. The state WaitTimeOut is inserted to detect a rising transition of CarryOut, an indication of counter underflow. LoadCnt is reset to zero. After this, the state machine returns to the state WaitRisingEdge, where all output signals take on LOW level.

Figure 50: State diagram of the component ImpulsGen_StateMachine

-- University of Applied Sciences / Munich
-- Federal Technological Education Center / Rio de Janeiro
-- =======================================================
-- = Project : Bicycle computer in VHDL                  =
-- = File    : impulsgen_statemachine_fsm.vhd            =
-- = Notes   : BikeCom.ImpulsGen_StateMachine            =
-- =======================================================
-- = Datum   : 08.08.2001                                =
-- = Design  : Joachim Reiss                             =
-- = Revision: 001                                       =
-- =======================================================
--
--

--
-- VHDL Entity BikeCom.ImpulsGen_StateMachine.interface
--

LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY ImpulsGen_StateMachine IS
   PORT( 
      CarryOut       : IN     std_logic  ;
      FallingEdge_In : IN     std_logic  ;
      Reset          : IN     std_logic  ;
      Systemclock    : IN     std_logic  ;
      ImpulsOut      : OUT    std_logic  ;
      LoadCnt        : OUT    std_logic 
   );

-- Declarations

END ImpulsGen_StateMachine ;

--
-- VHDL Architecture BikeCom.ImpulsGen_StateMachine.fsm
--

ARCHITECTURE fsm OF ImpulsGen_StateMachine IS

   -- Architecture Declarations
   TYPE STATE_TYPE IS (
      WaitRisingEdge,
      Trigger_WaitRisingEdge,
      Impuls,
      WaitTimeOut
   );

   -- State vector declaration
   ATTRIBUTE state_vector : string;
   ATTRIBUTE state_vector OF fsm : ARCHITECTURE IS "current_state" ;


   -- Declare current and next state signals
   SIGNAL current_state : STATE_TYPE ;
   SIGNAL next_state : STATE_TYPE ;

   -- Declare any pre-registered internal signals
   SIGNAL ImpulsOut_cld : std_logic  ;
   SIGNAL LoadCnt_cld : std_logic  ;

BEGIN

   ----------------------------------------------------------------------------
   clocked : PROCESS(
      Systemclock,
      Reset
   )
   ----------------------------------------------------------------------------
   BEGIN
      IF (Reset = '0') THEN
         current_state <= WaitRisingEdge;
         -- Reset Values
         ImpulsOut_cld <= '0';
         LoadCnt_cld <= '0';
      ELSIF (Systemclock'EVENT AND Systemclock = '1') THEN
         current_state <= next_state;
         -- Default Assignment To Internals
         ImpulsOut_cld <= '0';
         LoadCnt_cld <= '0';

         -- State Actions for internal signals only
         CASE current_state IS
         WHEN WaitRisingEdge =>
            ImpulsOut_cld <= '0';
            LoadCnt_cld <= '0';
         WHEN Trigger_WaitRisingEdge =>
            ImpulsOut_cld <= '0';
            LoadCnt_cld <= '0';
         WHEN Impuls =>
            ImpulsOut_cld <= '1';
            LoadCnt_cld <= '1';
         WHEN WaitTimeOut =>
            ImpulsOut_cld <= '1';
            LoadCnt_cld <= '0';
         WHEN OTHERS =>
            NULL;
         END CASE;

      END IF;

   END PROCESS clocked;

   ----------------------------------------------------------------------------
   nextstate : PROCESS (
      CarryOut,
      FallingEdge_In,
      current_state
   )
   ----------------------------------------------------------------------------
   BEGIN
      CASE current_state IS
      WHEN WaitRisingEdge =>
         IF (FallingEdge_In = '1') THEN
            next_state <= Trigger_WaitRisingEdge;
         ELSE
            next_state <= WaitRisingEdge;
         END IF;
      WHEN Trigger_WaitRisingEdge =>
         IF (FallingEdge_In = '0') THEN
            next_state <= Impuls;
         ELSE
            next_state <= Trigger_WaitRisingEdge;
         END IF;
      WHEN Impuls =>
         IF (CarryOut = '0') THEN
            next_state <= WaitTimeOut;
         ELSE
            next_state <= Impuls;
         END IF;
      WHEN WaitTimeOut =>
         IF (CarryOut = '1') THEN
            next_state <= WaitRisingEdge;
         ELSE
            next_state <= WaitTimeOut;
         END IF;
      WHEN OTHERS =>
         next_state <= WaitRisingEdge;
      END CASE;

   END PROCESS nextstate;

   -- Concurrent Statements
   -- Clocked output assignments
   ImpulsOut <= ImpulsOut_cld;
   LoadCnt <= LoadCnt_cld;


END fsm;

Increasing the wheel perimeter

The component PerimeterImpulsGen provides pulses on the output to the input Inc_Wheel of the ProcessingUnit. The architecture body of this component contains a process without signals specified in a sensitivity list.
A process statement is always active and executes a loop at all time if not suspended.

Synchronisation can be obtained with several solutions:

This process assigns the respective signal levels corresponding to the scheduling, as specified by the after clause. All time values are related to the simulation time zero mark. The WAIT statement suspends the process.

ARCHITECTURE flow OF PerimeterImpulsGen IS

BEGIN
   ---------------------------------------------------------------------------
   process0 : PROCESS
   ---------------------------------------------------------------------------
   BEGIN
      WheelPerimeterAdjust <= '1',
                                               '0' AFTER 5 ms,
                                               '1' AFTER 6 ms,
                                               '0' AFTER 10 ms,
                                               '1' AFTER 11 ms,
                                               '0' AFTER 15 ms,
                                               '1' AFTER 16 ms,
                                               '0' AFTER 20 ms,
                                               '1' AFTER 21 ms;
      wait;
   END PROCESS process0;


END flow;

Previous page | Content | Home