When implementing recursive structures such as linked lists, you need another VHDL language feature to complete the declarations. This feature is called the incomplete type. The incomplete type allows the declaration of a type to be defined later.
Following is an example that demonstrates why this would be useful: PACKAGE stack_types IS
TYPE data_type IS ARRAY(0 TO 7) OF std_logic; --line 1
TYPE element_rec; --incomplete type line 2
TYPE element_ptr IS ACCESS element_rec; --line 3 TYPE element_rec IS --line 4
RECORD --line 5
data : data_type; --line 6
nxt : element_ptr; --line 7
END RECORD; --line 8
END stack_types;
USE WORK.stack_types.ALL; ENTITY stack IS
PORT(din : IN data_type; clk : IN std_logic; dout : OUT data_type; r_wb : IN std_logic); END stack;
ARCHITECTURE stack OF stack IS BEGIN
PROCESS(clk)
VARIABLE list_head : element_ptr := NULL; --line 9 VARIABLE temp_elem : element_ptr := NULL; --line 10 VARIABLE last_clk : std_logic := U; --line 11 BEGIN
IF (clk = ‘1’) AND (last_clk = ‘0’) THEN --line 12 IF (r_wb = ‘0’) THEN --line 13 temp_elem := NEW element_rec; --line 14 temp_elem.data := din; --line 15
temp_elem.nxt := list_head; --line 16 list_head := temp_elem; --line 17 --read mode --line 18 ELSIF (r_wb = ‘1’) THEN
dout <= list_head.data; --line 19 temp_elem := list_head; --line 20 list_head := temp_elem.nxt; --line 21 DEALLOCATE (temp_elem); --line 22 ELSE
ASSERT FALSE
REPORT “read/write unknown while clock active” SEVERITY WARNING; --line 23 END IF;
END IF;
last_clk := clk; --line 24 END PROCESS;
END stack;
This example implements a stack using access types. The package stack_typesdeclares all of the types needed for the stack. In line 2, there is a declaration of the incomplete type element_rec. The name of the type is specified, but no specification of the type is present. The purpose of this declaration is to reserve the name of the type and allow other types to gain access to the type when it is fully specified. The full specification for this incomplete type appears in lines 4 through 8.
The fundamental reason for the incomplete type is to allow self- referencing structures as linked lists. Notice that type element_ptris used in type element_recin line 6. To use a type, it must first be de- fined. Notice also that, in the declaration for type element_ptrin line 3, type element_recis used. Because each type uses the other in its re- spective declarations, neither type can be declared first without a spe- cial way of handling this case. The incomplete type allows this scenario to exist.
Lines 4 through 8 declare the record type element_rec. This record type is used to store the data for the stack. The first field of the record is the data field, and the second is an access type that points to the next record in the stack.
The entity for stack declares port dinfor data input to the stack, a clk input on which all operations are triggered, a doutport which transfers data out of the stack, and, finally, a r_wbinput which causes a read oper- ation when high and a write operation when low. The process for the stack is only triggered when the clkinput has an event occur. It is not affected by changes in r_wb.
Lines 9 through 11 declare some variables used to keep track of the data for the stack. Variable list_head is the head of the linked list of
data. It always points to the first element of the list of items in the stack. Variable temp_elemis used to hold a newly allocated element until it is connected into the stack list. Variable last_clkis used to hold the previ- ous value of clk to enable transitions on the clock to be detected. (This behavior can be duplicated with attributes, which are discussed in Chapter 7, “Configurations.”)
Line 12 checks to see if a 0 to 1 transition has occurred on the clk input. If so, then the stack needs to do a read or write depending on the r_wbinput. Line 13 checks to see if r_wbis set up for a write to the stack. If so, lines 14 through 17 create a new data storage element and connect this element to the list.
Line 14 uses the predefined function NEWto allocate a record of type element_rec and return an access value to be assigned to variable temp_elem. This creates a structure that is shown in Figure 4-4.
Lines 15 and 16 fill in the newly allocated object with the data from input din and the access value to the head of the list. After line 16, the data structures look like Figure 4-5.
Finally, in line 17, the new element is added to the head of the list. This is shown in Figure 4-6.
Lines 18 through 22 of the model provide the behavior of the stack when an element is read from the stack. Line 19 copies the data from the stack element to the output port. Lines 20 through 22 disconnect the element from the stack list and return the memory to the system.
Line 20 assigns the temp_elemaccess variable to point to the head of the list. This is shown in Figure 4-7.
Line 21 moves the head of the list to the next element in the list. This is shown in Figure 4-8. Stack Element Data NXT Stack Element Data NXT Stack Element Data NXT List_Head Temp_Elem Figure 4-4
Allocate New Stack Element.
Stack Element Data NXT Stack Element Data NXT Stack Element Data NXT List_Head Temp_Elem Figure 4-5
Point New Element to Head of List. Stack Element Data NXT Stack Element Data NXT Stack Element Data NXT List_Head Temp_Elem Figure 4-6 Point List_Headto New Element. Stack Element Data NXT Stack Element Data NXT Stack Element Data NXT List_Head Temp_Elem Figure 4-7 Point Temp_Elemto List_Head.
Finally, in line 22, the element that had its data transferred out is deal- located, and the memory is returned to the memory pool. This is shown in Figure 4-9.
Access types are very powerful tools for modeling complex and abstract types of systems. Access types bring programming language types of operations to VHDL processes.