Understanding VHDL Attributes
Attributes are a feature of VHDL that allow you to extract additional information about an object (such as a signal, variable or type) that may not be directly related to the value that the object carries. Attributes also allow you to assign additional information (such as data related to synthesis) to objects in your design description.
There are two classes of attributes: those that are predefined as a part of the 1076 standard, and those that have been introduced outside of the standard, either by you or by your design tool supplier.
Predefined attributes
The VHDL specification describes five fundamental kinds of attributes. These five kinds of attributes are categorized by the results that are returned when they are used. The possible results returned from these attributes are: a value, a function, a signal, a type or a range.
Predefined attributes are always applied to a prefix (such as a signal or variable name, or a type or subtype name), as in the statement:
wait until Clk = ‘1’ and Clk’event and Clk’last_value = ‘0’;
In this statement, the attributes ‘event and ‘last_value have been applied to the prefix Clk, which is a signal.
Some attributes also include parameters, so they are written in much the same way you would write a call to a function:
variable V: state_type := state_type’val(2); – V has the value of Strobe
In this case, the attribute ‘val has been applied to the prefix state_type (which is a type name) and has been given an attribute parameter, the integer value 2.
Value kind attributes: ‘Left, ‘Right, ‘High, ‘Low, ‘Length, ‘Ascending
The value kind attributes that return an explicit value and are applied to a type or subtype include the following:
‘Left—This attribute returns the left-most element index (the bound) of a given type or subtype.
Example: type bit_array is array (1 to 5) of bit;
variable L: integer := bit_array’left; -- L has a value of 1
‘Right—Returns the right-most bound of a given type or subtype.
Example: type bit_array is array (1 to 5) of bit;
variable R: integer := bit_array’right; -- R has a value of 5
‘High—returns the upper bound of a given scalar type or subtype.
Example: type bit_array is array(-15 to +15) of bit;
variable H: integer := bit_array’high; -- H has a value of 15
‘Low—returns the upper bound of a given scalar type or subtype.
Example: type bit_array is array(15 downto 0) of bit;
variable L: integer := bit_array’low;
-- L has a value of 0
‘Length—returns the length (number of elements) of an array.
Example: type bit_array is array (0 to 31) of bit;
variable LEN: integer := bit_array’length -- LEN has a value of 32
‘Ascending—(VHDL ’93 attribute) returns a boolean true value of the type or subtype is declared with an ascending range.
Example: type asc_array is array (0 to 31) of bit;
type desc_array is array (36 downto 4) of bit;
variable A1: boolean := asc_array’ascending; -- A1 has a value of true
variable A2: boolean := desc_array’ascending; -- A2 has a value of false
As you can see from the examples, value kind attributes (and all other predefined attributes) are identified by the ‘ (single quote) character. They are applied to type names, signals names and other identifiers, depending on the nature of the attribute. The value type attributes are used to determine the upper and lower (or left and right) bounds of a given type.
The following sample architecture uses the ‘right and ‘left attibutes to determine the left- and right-most element indices of an array in order to describe a width-independent shift operation:
architecture behavior of shifter is
begin
reg: process(Rst,Clk)
begin
if Rst = ‘1’ then -- Async reset
Qreg := (others => ‘0’);
elsif rising_edge(Clk) then
Qreg := Data(Data’left+1 to Data’right) & Data(Data’left);
end if;
end process;
end behavior;
The ‘right, ‘left, ‘high and ‘low attributes can be used to return non-numeric values. The following example demonstrates how you can use the ‘left and ‘right attributes to identify the first and last items in an enumerated type:
architecture example of enums is
type state_type is (Init, Hold, Strobe, Read, Idle);
signal L, R: state_type;
begin
L <= state_type’left; -- L has the value of Init
R <= state_type’right; -- R has the value of Idle
end example;
Value kind attributes: ‘Structure, ‘Behavior
There are two additional value kind attributes that can be used to determine information about blocks or attributes in a design. These attributes, ‘structure and ‘behavior, return true or false values depending on whether the block or architecture being referenced includes references to lower-level components. The ‘structure attribute returns true if there are references to lower-level components, and false if there are no references to lower-level components. The ‘behavior attribute returns false if there are references to lower-level components, and true if there are no references to lower-level components.
‘Structure—returns a true value if the prefix (which must be an architecture name) includes references to lower-level components.
‘Behavior—returns a true value if the prefix (which must be an architecture name) does not include references to lower-level components.
Value kind attributes: ‘Simple_name, ‘Instance_name, ‘Path_name
VHDL 1076-1993 added three attributes that can be used to determine the precise configuration of entities in a design description. These attributes return information about named entities, which are various items that become associated with identifiers, character literals or operator symbols as the result of a declaration. For more information about these attributes, refer to the IEEE VHDL Language Reference Manual.
‘Simple_name—returns a string value corresponding to the prefix, which must be a named entity.
‘Instance_name—returns a string value corresponding to the complete path (from the design hierarchy root) to the named entity specified in the prefix, including the names of all instantiated design entities. The string returned by this attribute has a fixed format that is defined in the IEEE VHDL Language Reference Manual.
‘Path_name—returns a string value corresponding to the complete path (from the design hierarchy root) to the named entity specified in the prefix. The string returned by this attribute has a fixed format that is defined in the IEEE VHDL Language Reference Manual.
Function kind attributes: ‘Pos, ‘Val, ‘Succ, ‘Pred, ‘Leftof, ‘Rightof
Attributes that return information about a given type, signal, or array value are called function kind attributes. VHDL defines the following function kind attributes that can be applied to types:
‘Pos(value)—returns the position number of a type value.
Example: type state_type is (Init, Hold, Strobe, Read, Idle);
variable P: integer := state_type’pos(Read); -- P has the value of 3
‘Val(value)—returns the value corresponding to a position number of a type value.
Example: type state_type is (Init, Hold, Strobe, Read, Idle);
variable V: state_type := state_type’val(2); -- V has the value of Strobe
‘Succ(value)—returns the value corresponding to position number after a given type value.
Example: type state_type is (Init, Hold, Strobe, Read, Idle);
variable V: state_type := state_type’succ(Init); -- V has the value of Hold
‘Pred(value)—returns the value corresponding to position number preceding a given type value.
Example: type state_type is (Init, Hold, Strobe, Read, Idle);
variable V: state_type := state_type’pred(Hold); -- V has the value of Init
‘Leftof(value)—returns the value corresponding to position number to the left of a given type value.
Example: type state_type is (Init, Hold, Strobe, Read, Idle);
variable V: state_type := state_type’leftof(Idle); -- V has the value of Read
‘Rightof(value)—returns the value corresponding to position number to the right of a given type value.
Example: type state_type is (Init, Hold, Strobe, Read, Idle);
variable V: state_type := state_type’rightof(Read); -- V has the value of Idle
From the above descriptions, it might appear that the ‘val and ‘succ attributes are equivalent to the attributes ‘leftof and ‘rightof. One case where they would be different is the case where a subtype is defined that changes the ordering of the base type:
type state_type is (Init, Hold, Strobe, Read, Idle);
subtype reverse_state_type is state_type range Idle downto Init;
variable V1: reverse_state_type := reverse_state_type’leftof(Hold);
-- V1 has the value of Strobe
variable V2: reverse_state_type := reverse_state_type’pred(Hold);
-- V2 has the value of Init
Function kind array attributes: ‘Left, ‘Right, ‘High, ‘Low
The function kind attributes that can be applied to array objects include:
‘Left(value)—returns the index value corresponding to the left bound of a given array range.
Example: type bit_array is array (15 downto 0) of bit;
variable I: integer :=
bit_array’left(bit_array’range);
-- I has the value of 15
‘Right(value)—returns the index value corresponding to the right bound of a given array range.
Example: type bit_array is array (15 downto 0) of bit;
variable I: integer :=
bit_array’right(bit_array’range);
-- I has the value of 0
‘High(value)—returns the index value corresponding to the upper-most bound of a given array range.
Example: type bit_array is array (15 downto 0) of bit;
variable I: integer :=
bit_array’high(bit_array’range);
-- I has the value of 15
‘Low(value)—returns the index value corresponding to the lower bound of a given array range.
Example: type bit_array is array (15 downto 0) of bit;
variable I: integer :=
bit_array’low(bit_array’range);
-- I has the value of 0
Function kind attributes: ‘Event, ‘Active, ‘Last_event, ‘Last_value, ‘Last_active
Function kind attributes that return information about signals (such as whether that signal has changed its value or its previous value) include:
‘Event—returns a true value of the signal had an event (changed its value) in the current simulation delta cycle.
Example: process(Rst,Clk)
begin
if Rst = ‘1’ then
Q <= ‘0’;
elsif Clk = ‘1’ and Clk’event then
-- Look for clock edge
Q <= D;
end if;
end process;
‘Active—returns true if any transaction (scheduled event) occurred on this signal in the current simulation delta cycle.
Example: process
variable A,E: boolean;
begin
Q <= D after 10 ns;
A := Q’active; -- A gets a value of True
E := Q’event; -- E gets a value of False
. . .
end process;
‘Last_event—returns the time elapsed since the previous event occurring on this signal.
Example: process
variable T: time;
begin
Q <= D after 5 ns;
wait 10 ns;
T := Q’last_event; -- T gets a value of 5 ns
. . .
end process;
‘Last_value—returns the value of the signal prior to the last event.
Example: process
variable V: bit;
begin
Q <= ‘1’;
wait 10 ns;
Q <= ‘0’;
wait 10 ns;
V := Q’last_value; -- V gets a value of ‘1’
. . .
end process;
‘Last_active—returns the time elapsed since the last transaction (scheduled event) of the signal.
Example: process
variable T: time;
begin
Q <= D after 30 ns;
wait 10 ns;
T := Q’last_active; -- T gets a value of 10 ns
. . .
end process;
Note: the ‘active, ‘last_event, ‘last_value and ‘last_active attributes are not generally supported in synthesis tools. Of the preceding five attributes, only ‘event should be used when describing synthesizable registered circuits. The ‘active, ‘last_event, ‘last_value and ‘last_active attributes should only be used to describe circuits for test purposes (such as for setup and hold checking). If they are encountered by a synthesis program, they will either be ignored, or the program will return an error and halt operation.
Function kind attributes: ‘Image, ‘Value
The ‘image and ‘value attributes were added in the 1993 specification to simplify the reporting of information through Text I/O. These attributes both return string results corresponding to their parameter values.
‘Image(expression)—(VHDL ’93 attribute) returns a string representation of the expression parameter, which must be of a type corresponding to the attribute prefix.
Example: assert (Data.Q = ‘1’)
report "Test failed on vector " &
integer’image(vector_idx)
severity WARNING;
‘Value(string)—(VHDL ’93 attribute) returns a value, of a type specified by the prefix, corresponding to the parameter string.
Example: write(a_outbuf,string’(“Enter desired state (example: S1)”));
writeline(OUTPUT,a_outbuf);
readline(INPUT,a_inbuf);
read(a_inbuf,instate); -- instate is a string type
next_state <= state_type’value(instate);
-- convert string to type state_type
write(a_outbuf,string’("Enter duration (example: 15)"));
writeline(OUTPUT,a_outbuf);
readline(INPUT,a_inbuf);
read(a_inbuf,induration); -- induration is a string type
duration <= integer’value(induration);
-- convert string to type integer
Signal kind attributes: ‘Delayed, ‘Stable, ‘Quiet, ‘Transaction
The signal kind attributes are attributes that, when invoked, create special signals that have values and types based on other signals. These special signals can then be used anywhere in the design description that a normally declared signal could be used. One example of where you might use such an attribute is to create a series of delayed clock signals that are all based on the waveform of a base clock signal.
Signal kind attributes include the following:
‘Delayed(time)—creates a delayed signal that is identical in waveform to the signal the attribute is applied to. (The time parameter is optional, and may be omitted.)
Example: process(Clk’delayed(hold))
-- Hold time check for input Data
begin
if Clk = ‘1’ and Clk’stable(hold) then
assert(Data’stable(hold))
report "Data input failed hold time check!"
severity warning;
end if;
end process;
‘Stable (time)—creates a signal of type boolean that becomes true when the signal is stable (has no event) for some given period of time.
Example: process
variable A: Boolean;
begin
wait for 30 ns;
Q <= D after 30 ns;
wait 10 ns;
A := Q’stable(20 ns);
-- A gets a value of true (event has not
-- yet occurred)
wait 30 ns;
A := Q’stable(20 ns);
-- A gets a value of false (only 10 ns
-- since event)
. . .
end process;
‘Quiet (time)—creates a signal of type boolean that becomes true when the signal has no transactions (scheduled events) or actual events for some given period of time.
Example: process
variable A: Boolean;
begin
wait for 30 ns;
Q <= D after 30 ns;
wait 10 ns;
A := Q’quiet(20 ns);
-- A gets a value of false (10 ns since
-- transaction)
wait 40 ns;
A := Q’quiet(20 ns);
-- A finally gets a value of true (20 ns
-- since event)
. . .
end process;
‘Transaction—creates a signal of type bit that toggles its value whenever a transaction or actual event occurs on the signal the attribute is applied to.
Type kind attribute: ‘Base
‘Base—returns the base type for a given type or subtype.
Example: type mlv7 is (‘0’,’1’,’X’,’Z’,’H’,’L’,’W’);
subtype mlv4 is mlv7 range ‘0’ to ‘Z’;
variable V1: mlv4 := mlv4’right;
-- V1 has the value of ‘Z’
variable V2: mlv7 := mlv4’base’right;
-- V2 has the value of ‘W’
variable I1: integer := mlv4’width;
-- I1 has the value of 4
variable I2: integer := mlv4’base’width;
-- I2 has the value of 7
Range Kind Attributes: ‘Range, ‘Reverse_range
The range kind attributes return a special value that is a range, such as you might use in a declaration or looping scheme.
‘Range—returns the range value for a constrained array.
Example: function parity(D: std_logic_vector) return
std_logic is
variable result: std_logic := ‘0’;
begin
for i in D’range loop
result := result xor D(i);
end loop;
return result;
end parity;
‘Reverse_range—returns the reverse of the range value for a constrained array.
Example: STRIPX: for i in D’reverse_range loop
if D(i) = ‘X’ then
D(i) = ‘0’;
else
exit; -- only strip the terminating Xs
end if;
end loop;
Custom attributes
Custom attributes are those attributes that are not defined in the IEEE specifications, but that you (or your simulation or synthesis tool vendor) define for your own use. A good example is the attribute enum_encoding, which is provided by a number of synthesis tool vendors (most notably Synopsys) to allow specific binary encodings to be attached to objects of enumerated types.
An attribute such as enum_encoding is declared (again, either by you or by your design tool vendor) using the following method:
attribute enum_encoding: string;
This attribute could be written directly in your VHDL design description, or it could have been provided to you by the tool vendor in the form of a package. Once the attribute has been declared and given a name, it can be referenced as needed in the design description:
type statevalue is (INIT, IDLE, READ, WRITE, ERROR);
attribute enum_encoding of statevalue: type is "000 001 011 010 110";
When these declarations are processed by a synthesis tool that supports the enum_encoding attribute, information about the encoding of the type statevalue will be used by that tool. When the design is processed by design tools (such as simulators) that do not recongnize the enum_encoding attribute, it will simply be ignored.
Custom attributes are a convenient “back door” feature of VHDL, and design tool vendors have created many such attributes to give you more control over the synthesis and simulation process. For detailed information about custom attributes, refer to your design tool documentation.