VHDL subset for our Hierarchical Test Generation System (HTGS)

 

This section explains basic principles of writing RT-Level VHDL description for our HTGS. As an example, design MULT8x8 is used.

 

Definition of Architecture

The overall style of design supported by our HTGS is a single process description (in VHDL terms). Design should be partitioned into the datapath and controller. Datapath is represented by a netlist of interconnected blocks. The building blocks of datapath are registers, multiplexers and functional units (FU), where functions can be arbitrary arithmetic or logic operations. Datapath can be represented by a system of AGs, where for each primary output and for each register, an AG corresponds. In the graph models, the non-terminal nodes correspond to control signals and terminal nodes represent operations. Register transfers and constant assignments are treated as special cases of operations. Branches between the nodes determine, which operation will be assigned to the variable by each value combination of the control signals? Figure 1 explains the AG representation of a datapath register for the general case.

 

 

 

Figure 1 Alternative graph representation for a datapath register

 

The control part of an RTL description is described as a Finite State Machine (FSM) state table. Similar to the datapath, the state table can be represented by an AG model. In that case the non-terminal nodes correspond to current state and conditions (FSM inputs), and terminal nodes hold the values of next state and control signals (FSM outputs). Fig. 2 shows an example of a fragment of a FSM state table and the corresponding AG representation. In the AG, q denotes the next state and q’ denotes the current state value. The variables out1, out2, out3 and out4 are output variables of the FSM. The graph in Fig.2. describes the behaviour of the FSM at the current state being s5.

 

Figure 2 Representing a fragment of a FSM state table by an AG

 

Coding restrictions

General partitioning

For our HTGS, design should be divided into 3 parts: descriptions of top-level entity, datapath (DP) and finite-state machine (FSM). Each part should be in a separate file and all three files should have common beginning of filename and special end to describe the type of file (e.q. mult8x8_TL.vhdl, mult8x8_DP.vhdl and mult8x8_FSM.vhdl). Additionally, library of decision diagrams (DD) describing FUs is needed (ag_lib).

 

Top-level entity

In VHDL file, describing the uppermost level of design (design name + _TL.vhdl extension), should be declaration of the top-level entity and structural descriprtion of the architecture. Architecture description should include component declarations for DP and FSM entities and signal declarations.

 

Datapath

Declarations of DP entity and description of architecture should be together in DP file (design name + _DP.vhdl extension). Architecture should be described in structural mode and should include signal declarations and configuration specifications. In architecture description all DP components should be instantiated.

 

Finite-state machine

As in top-level and in DP, also in FSM, declarations of FSM entity and description of architecture should be together in FSM file (design name + _FSM.vhdl extension). In FSM file architecture should describe behaviour. Whole FSM should be described as one CASE statement. Additionally is allowed signal assignments outside CASE statement and reset handling.

 

Port types

At the moment only IN and OUT ports are allowed.

 

Signal types

Allowed types are std_logic, std_logic_vector and u_std_logic_vector. Vectors are allowed in both directions (downto as well as to)

 

Configurations

All FUs should use ag_lib entities. Example configuration:

 FOR I_EQ_1 : AG_EQ USE ENTITY WORK.AG_EQ(behave) ;

 

Constants

All constants should be represented in binary format.

 

Components instantiation

All components defined in an architecture should be instantiated. Generic constants as well as component ports should be defined. For example:

 I_ADDER_2 : AG_ADDER

GENERIC MAP (16, 16)

PORT MAP (REGR_1, REG_2, ADDER_2) ;

 

Case statement

Only WHEN statements are allowed inside CASE statement as shown in the following example. WHEN OTHERS part is optional:

CASE pres_state IS

WHEN "000" =>

next_state <= "001" ;

MUX2_1_ADDRESS <= '0' ;

REGR_1_RESET <= '1' ;

WHEN "001" =>

….

WHEN OTHERS =>

next_state <= "000";

MUX2_3_ADDRESS <= '1' ;

REG_4_ENABLE <= '1' ;

END CASE ;

 

When statement

Inside WHEN statement currently are allowed IF statements and signal assignments. For example:

 

WHEN "101" =>

IF (EQ_1_OUTPUT = '1') THEN

next_state <= "110" ;

ELSE

next_state <= "111" ;

MUX2_2_ADDRESS <= '1' ;

REG_3_ENABLE <= '1' ;

END IF ;

 

If statement

At the moment only structure IF-THEN-ELSE is allowed (ELSIF is forbidden).

 

Reset handling

Outside CASE statement (in FSM part) should be reste handling. It should be implemented in form of IF statement, as shown in example:

END CASE ;

IF (SYN_RESET = '1' ) THEN

next_state <= "000";

MUX2_3_ADDRESS <= '0' ;

REG_4_ENABLE <= '1' ;

END IF ;

 

Design Example

 

mult8x8_TL.vhdl

 

-- Entity generated from: mult8x8_beh_syn1

-----------------------------------------------------------------

ENTITY mult8x8_beh_syn1 IS

PORT (

-- control ports:

SYN_CLOCK : IN std_logic ;

SYN_RESET : IN std_logic ;

-- data (non-control) ports:

X : IN std_logic_vector (7 downto 0) ;

Y : IN std_logic_vector (7 downto 0) ;

RES : OUT std_logic_vector (15 downto 0) ) ;

END ;

 

 

-- Architecture generated from: mult8x8_beh_syn1

-----------------------------------------------------------------

ARCHITECTURE STRUCTURE OF mult8x8_beh_syn1 IS

 

-- component declarations:

COMPONENT mult8x8_beh_syn1_FSM

PORT (

-- control ports:

SYN_CLOCK : IN std_logic ;

EQ_1_OUTPUT : IN std_logic ;

LE_1_OUTPUT : IN std_logic ;

MUX2_3_ADDRESS : OUT std_logic ;

MUX2_4_ADDRESS : OUT std_logic ;

MUX2_1_ADDRESS : OUT std_logic ;

MUX2_2_ADDRESS : OUT std_logic ;

REG_2_ENABLE : OUT std_logic ;

REG_5_ENABLE : OUT std_logic ;

REG_1_ENABLE : OUT std_logic ;

REG_3_ENABLE : OUT std_logic ;

REG_4_ENABLE : OUT std_logic ;

REGR_1_ENABLE : OUT std_logic ;

REGR_1_RESET : OUT std_logic ;

REGR_2_ENABLE : OUT std_logic ;

REGR_2_RESET : OUT std_logic ;

SYN_RESET : IN std_logic ) ;

END COMPONENT ;

COMPONENT mult8x8_beh_syn1_DP

PORT (

-- control ports:

SYN_CLOCK : IN std_logic ;

EQ_1_OUTPUT : OUT std_logic ;

LE_1_OUTPUT : OUT std_logic ;

MUX2_3_ADDRESS : IN std_logic ;

MUX2_4_ADDRESS : IN std_logic ;

MUX2_1_ADDRESS : IN std_logic ;

MUX2_2_ADDRESS : IN std_logic ;

REG_2_ENABLE : IN std_logic ;

REG_5_ENABLE : IN std_logic ;

REG_1_ENABLE : IN std_logic ;

REG_3_ENABLE : IN std_logic ;

REG_4_ENABLE : IN std_logic ;

REGR_1_ENABLE : IN std_logic ;

REGR_1_RESET : IN std_logic ;

REGR_2_ENABLE : IN std_logic ;

REGR_2_RESET : IN std_logic ;

-- data (non-control) ports:

RES : OUT std_logic_vector (15 downto 0) ;

X : IN std_logic_vector (7 downto 0) ;

Y : IN std_logic_vector (7 downto 0) ) ;

END COMPONENT ;

 

-- signal declarations (nets with no ports):

SIGNAL EQ_1_OUTPUT : std_logic;

SIGNAL MUX2_3_ADDRESS, MUX2_4_ADDRESS,

MUX2_1_ADDRESS, MUX2_2_ADDRESS, REG_2_ENABLE,

REG_5_ENABLE, REG_1_ENABLE, REG_3_ENABLE,

REG_4_ENABLE, REGR_1_ENABLE, REGR_1_RESET,

REGR_2_ENABLE, REGR_2_RESET : std_logic ;

SIGNAL LE_1_OUTPUT : std_logic;

 

-- configuration (binding of instances):

-- FOR ctrl_inst : mult8x8_beh_syn1_FSM USE ENTITY mult8x8_beh_syn1_FSM(BEHAVIOUR) ;

-- FOR dp_inst : mult8x8_beh_syn1_DP USE ENTITY mult8x8_beh_syn1_DP(STRUCTURE) ;

BEGIN

ctrl_inst : mult8x8_beh_syn1_FSM

PORT MAP (SYN_CLOCK, EQ_1_OUTPUT, LE_1_OUTPUT,

MUX2_3_ADDRESS, MUX2_4_ADDRESS, MUX2_1_ADDRESS,

MUX2_2_ADDRESS, REG_2_ENABLE, REG_5_ENABLE, REG_1_ENABLE,

REG_3_ENABLE, REG_4_ENABLE, REGR_1_ENABLE,

REGR_1_RESET, REGR_2_ENABLE, REGR_2_RESET,

SYN_RESET) ;

dp_inst : mult8x8_beh_syn1_DP

PORT MAP (SYN_CLOCK, EQ_1_OUTPUT, LE_1_OUTPUT,

MUX2_3_ADDRESS, MUX2_4_ADDRESS, MUX2_1_ADDRESS,

MUX2_2_ADDRESS, REG_2_ENABLE, REG_5_ENABLE, REG_1_ENABLE,

REG_3_ENABLE, REG_4_ENABLE, REGR_1_ENABLE,

REGR_1_RESET, REGR_2_ENABLE, REGR_2_RESET,

RES, X, Y) ;

END ;

 

 

--configuration CFG_MULT8X8_BEH_SYN1_BEHAVIORAL of mult8x8_beh_syn1 is

-- for STRUCTURE

-- for ctrl_inst : MULT8X8_BEH_SYN1_FSM

-- -- use configuration WORK.CFG_MULT8X8_BEH_SYN1_FSM_BEHAVIOUR;

-- end for;

-- for dp_inst : MULT8X8_BEH_SYN1_DP

-- -- use configuration WORK.CFG_MULT8X8_BEH_SYN1_DP_STRUCTURE;

-- end for;

-- end for;

-- end CFG_MULT8X8_BEH_SYN1_BEHAVIORAL;

 

 

 

mult8x8_DP.vhdl

 

-- Entity generated from: mult8x8_beh_syn1

-----------------------------------------------------------------

USE work.ag_lib.all ;

 

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_misc.all;

use IEEE.std_logic_arith.all;

use IEEE.std_logic_components.all;

 

ENTITY mult8x8_beh_syn1_DP IS

PORT (

-- control ports:

SYN_CLOCK : IN std_logic ;

EQ_1_OUTPUT : OUT std_logic ;

LE_1_OUTPUT : OUT std_logic ;

MUX2_3_ADDRESS : IN std_logic ;

MUX2_1_ADDRESS : IN std_logic ;

MUX2_4_ADDRESS : IN std_logic ;

MUX2_2_ADDRESS : IN std_logic ;

REG_4_ENABLE : IN std_logic ;

REG_2_ENABLE : IN std_logic ;

REGR_2_ENABLE : IN std_logic ;

REG_1_ENABLE : IN std_logic ;

REGR_1_ENABLE : IN std_logic ;

REG_5_ENABLE : IN std_logic ;

REG_3_ENABLE : IN std_logic ;

REGR_2_RESET : IN std_logic ;

REGR_1_RESET : IN std_logic ;

-- data (non-control) ports:

RES : OUT std_logic_vector (15 downto 0) ;

X : IN std_logic_vector (7 downto 0) ;

Y : IN std_logic_vector (7 downto 0) ) ;

END ;

 

-- USE work.ag_lib.all ;

 

 

-- Architecture generated from: mult8x8_beh_syn1

-----------------------------------------------------------------

ARCHITECTURE STRUCTURE OF mult8x8_beh_syn1_DP IS

 

-- signal declarations (nets with no ports):

SIGNAL SCON_W1_P1 : std_logic_vector (0 downto 0) ;

SIGNAL SCON_W16_M32768 : std_logic_vector (15 downto 0) ;

SIGNAL SCON_W4_P1 : std_logic_vector (3 downto 0) ;

SIGNAL SHIFT_RIGHT_1 : std_logic_vector (7 downto 0) ;

SIGNAL MUX2_1 : std_logic_vector (7 downto 0) ;

SIGNAL REG_1 : std_logic_vector (7 downto 0) ;

SIGNAL SHIFT_LEFT_1 : std_logic_vector (15 downto 0) ;

SIGNAL REG_2 : std_logic_vector (15 downto 0) ;

SIGNAL SUBTR_1 : std_logic_vector (15 downto 0) ;

SIGNAL REGR_1 : std_logic_vector (15 downto 0) ;

SIGNAL MUX2_2 : std_logic_vector (15 downto 0) ;

SIGNAL REG_3 : std_logic_vector (15 downto 0) ;

SIGNAL MUX2_3 : std_logic_vector (15 downto 0) ;

SIGNAL ADDER_2 : std_logic_vector (15 downto 0) ;

SIGNAL MUX2_4 : std_logic_vector (15 downto 0) ;

SIGNAL REG_5 : std_logic_vector (15 downto 0) ;

SIGNAL SHIFT_RIGHT_2 : std_logic_vector (15 downto 0) ;

SIGNAL ADDER_3 : std_logic_vector (3 downto 0) ;

SIGNAL REGR_2, SCON_W4_P6 : std_logic_vector (3 downto 0) ;

-- configuration (binding of instances):

FOR I_ADDER_2 : AG_ADDER USE ENTITY WORK.AG_ADDER(behave) ;

FOR I_ADDER_3 : AG_ADDER USE ENTITY WORK.AG_ADDER(behave) ;

FOR I_EQ_1 : AG_EQ USE ENTITY WORK.AG_EQ(behave) ;

FOR I_LE_1 : AG_LE USE ENTITY WORK.AG_LE(behave) ;

FOR I_SHIFT_LEFT_1 : AG_SHIFT_LEFT USE ENTITY WORK.AG_SHIFT_LEFT(behave) ;

FOR I_SHIFT_RIGHT_2 : AG_SHIFT_RIGHT USE ENTITY WORK.AG_SHIFT_RIGHT(behave);

FOR I_SHIFT_RIGHT_1 : AG_SHIFT_RIGHT USE ENTITY WORK.AG_SHIFT_RIGHT(behave);

FOR I_SUBTR_1 : AG_SUBTR USE ENTITY WORK.AG_SUBTR(behave) ;

FOR I_MUX2_3 : AG_MUX2 USE ENTITY WORK.AG_MUX2(behave) ;

FOR I_MUX2_4 : AG_MUX2 USE ENTITY WORK.AG_MUX2(behave) ;

FOR I_MUX2_1 : AG_MUX2 USE ENTITY WORK.AG_MUX2(behave) ;

FOR I_MUX2_2 : AG_MUX2 USE ENTITY WORK.AG_MUX2(behave) ;

FOR I_REG_2 : AG_REG USE ENTITY WORK.AG_REG(behave) ;

FOR I_REG_5 : AG_REG USE ENTITY WORK.AG_REG(behave) ;

FOR I_REG_1 : AG_REG USE ENTITY WORK.AG_REG(behave) ;

FOR I_REG_3 : AG_REG USE ENTITY WORK.AG_REG(behave) ;

FOR I_REG_4 : AG_REG USE ENTITY WORK.AG_REG(behave) ;

FOR I_REGR_1 : AG_REGR USE ENTITY WORK.AG_REGR(behave) ;

FOR I_REGR_2 : AG_REGR USE ENTITY WORK.AG_REGR(behave) ;

 

BEGIN

-- instantiations of FU's etc (AG_LIB modules):

SCON_W16_M32768 <= "1000000000000000"; -- constant value: -32768

SCON_W4_P6 <= "0110"; -- constant value: 6

SCON_W1_P1 <= "1"; -- constant value: 1

SCON_W4_P1 <= "0001"; -- constant value: 1

 

I_ADDER_2 : AG_ADDER

GENERIC MAP (16, 16)

PORT MAP (REGR_1, REG_2, ADDER_2) ;

I_ADDER_3 : AG_ADDER

GENERIC MAP (4, 4)

PORT MAP (REGR_2, SCON_W4_P1, ADDER_3) ;

I_EQ_1 : AG_EQ

GENERIC MAP (1, 1)

PORT MAP (REG_1(0 DOWNTO 0), SCON_W1_P1, EQ_1_OUTPUT) ;

I_LE_1 : AG_LE

GENERIC MAP (4, 1)

PORT MAP (REGR_2, SCON_W4_P6, LE_1_OUTPUT) ;

I_SHIFT_LEFT_1 : AG_SHIFT_LEFT

GENERIC MAP (8, 16, 7)

PORT MAP (Y, SHIFT_LEFT_1) ;

I_SHIFT_RIGHT_2 : AG_SHIFT_RIGHT

GENERIC MAP (16, 16, 1)

PORT MAP (REG_5, SHIFT_RIGHT_2) ;

I_SHIFT_RIGHT_1 : AG_SHIFT_RIGHT

GENERIC MAP (8, 8, 1)

PORT MAP (REG_1, SHIFT_RIGHT_1) ;

I_SUBTR_1 : AG_SUBTR

GENERIC MAP (16, 16)

PORT MAP (REGR_1, REG_2, SUBTR_1) ;

I_MUX2_3 : AG_MUX2

GENERIC MAP (16, 16)

PORT MAP (SCON_W16_M32768, REG_3, MUX2_3_ADDRESS, MUX2_3) ;

I_MUX2_4 : AG_MUX2

GENERIC MAP (16, 16)

PORT MAP (ADDER_2, REGR_1, MUX2_4_ADDRESS, MUX2_4) ;

I_MUX2_1 : AG_MUX2

GENERIC MAP (8, 8)

PORT MAP (X, SHIFT_RIGHT_1, MUX2_1_ADDRESS, MUX2_1) ;

I_MUX2_2 : AG_MUX2

GENERIC MAP (16, 16)

PORT MAP (SUBTR_1, REGR_1, MUX2_2_ADDRESS, MUX2_2) ;

I_REG_2 : AG_REG

GENERIC MAP (16, 16)

PORT MAP (SHIFT_LEFT_1, SYN_CLOCK, REG_2_ENABLE, REG_2) ;

I_REG_5 : AG_REG

GENERIC MAP (16, 16)

PORT MAP (MUX2_4, SYN_CLOCK, REG_5_ENABLE, REG_5) ;

I_REG_1 : AG_REG

GENERIC MAP (8, 8)

PORT MAP (MUX2_1, SYN_CLOCK, REG_1_ENABLE, REG_1) ;

I_REG_3 : AG_REG

GENERIC MAP (16, 16)

PORT MAP (MUX2_2, SYN_CLOCK, REG_3_ENABLE, REG_3) ;

I_REG_4 : AG_REG

GENERIC MAP (16, 16)

PORT MAP (MUX2_3, SYN_CLOCK, REG_4_ENABLE, RES) ;

I_REGR_1 : AG_REGR

GENERIC MAP (16, 16)

PORT MAP (SHIFT_RIGHT_2, SYN_CLOCK, REGR_1_ENABLE, REGR_1_RESET, REGR_1) ;

I_REGR_2 : AG_REGR

GENERIC MAP (4, 4)

PORT MAP (ADDER_3, SYN_CLOCK, REGR_2_ENABLE, REGR_2_RESET, REGR_2) ;

END ;

 

 

 

 

 

mult8x8_FSM.vhdl

 

-- Entity generated from: mult8x8_beh_syn1

-----------------------------------------------------------------

USE work.ag_lib.all ;

 

ENTITY mult8x8_beh_syn1_FSM IS

PORT (

-- control ports:

SYN_CLOCK : IN std_logic ;

EQ_1_OUTPUT : IN std_logic ;

LE_1_OUTPUT : IN std_logic ;

MUX2_3_ADDRESS : OUT std_logic ;

MUX2_4_ADDRESS : OUT std_logic ;

MUX2_1_ADDRESS : OUT std_logic ;

MUX2_2_ADDRESS : OUT std_logic ;

REG_2_ENABLE : OUT std_logic ;

REG_5_ENABLE : OUT std_logic ;

REG_1_ENABLE : OUT std_logic ;

REG_3_ENABLE : OUT std_logic ;

REG_4_ENABLE : OUT std_logic ;

REGR_1_ENABLE : OUT std_logic ;

REGR_1_RESET : OUT std_logic ;

REGR_2_ENABLE : OUT std_logic ;

REGR_2_RESET : OUT std_logic ;

SYN_RESET : IN std_logic ) ;

END ;

 

-- Architecture generated from: mult8x8_beh_syn1

-----------------------------------------------------------------

ARCHITECTURE BEHAVIOUR OF mult8x8_beh_syn1_FSM IS

-- TYPE states IS (s1, s2, s3, s4, s5, s6, s7, s8) ;

SIGNAL pres_state, next_state : std_logic_vector(2 downto 0) ;

BEGIN

sequencing:

PROCESS (pres_state, EQ_1_OUTPUT, LE_1_OUTPUT, SYN_RESET)

BEGIN

MUX2_3_ADDRESS <= 'X' ;

MUX2_1_ADDRESS <= 'X' ;

MUX2_4_ADDRESS <= 'X' ;

MUX2_2_ADDRESS <= 'X' ;

REG_4_ENABLE <= '0' ;

REG_2_ENABLE <= '0' ;

REGR_2_ENABLE <= '0' ;

REG_1_ENABLE <= '0' ;

REGR_1_ENABLE <= '0' ;

REG_5_ENABLE <= '0' ;

REG_3_ENABLE <= '0' ;

REGR_2_RESET <= '0' ;

REGR_1_RESET <= '0' ;

CASE pres_state IS

WHEN "000" =>

next_state <= "001" ;

MUX2_1_ADDRESS <= '0' ;

REG_2_ENABLE <= '1' ;

REG_1_ENABLE <= '1' ;

REGR_2_RESET <= '1' ;

REGR_1_RESET <= '1' ;

WHEN "001" =>

IF (LE_1_OUTPUT = '1' ) THEN

next_state <= "010" ;

ELSE

next_state <= "101" ;

END IF ;

WHEN "010" =>

IF (EQ_1_OUTPUT = '1') THEN

next_state <= "011" ;

ELSE

next_state <= "100" ;

MUX2_4_ADDRESS <= '1' ;

REG_5_ENABLE <= '1' ;

END IF ;

WHEN "011" =>

next_state <= "100" ;

MUX2_4_ADDRESS <= '0' ;

REG_5_ENABLE <= '1' ;

WHEN "100" =>

next_state <= "001" ;

MUX2_1_ADDRESS <= '1' ;

REGR_1_ENABLE <= '1' ;

REG_1_ENABLE <= '1' ;

REGR_2_ENABLE <= '1' ;

WHEN "101" =>

IF (EQ_1_OUTPUT = '1') THEN

next_state <= "110" ;

ELSE

next_state <= "111" ;

MUX2_2_ADDRESS <= '1' ;

REG_3_ENABLE <= '1' ;

END IF ;

WHEN "110" =>

next_state <= "111" ;

MUX2_2_ADDRESS <= '0' ;

REG_3_ENABLE <= '1' ;

WHEN OTHERS =>

next_state <= "000";

MUX2_3_ADDRESS <= '1' ;

REG_4_ENABLE <= '1' ;

END CASE ;

IF (SYN_RESET = '1' ) THEN

next_state <= "000";

MUX2_3_ADDRESS <= '0' ;

REG_4_ENABLE <= '1' ;

END IF ;

END PROCESS sequencing ;

--state_memory:

-- PROCESS

-- BEGIN

-- WAIT UNTIL SYN_CLOCK'EVENT AND SYN_CLOCK = '1' ;

-- pres_state <= next_state;

-- END PROCESS state_memory ;

END ;