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 ;