5. Data Objects: Signals, Variables and Constants
A data object is created by an object declaration and has a value and type associated with it. An object can be a Constant, Variable, Signal or a File. Up to now we have seen signals that were used as input or output ports or internal nets. Signals can be considered wires in a schematic that can have a current value and future values, and that are a function of the signal assignment statements. On the other hand, Variables and Constants are used to model the behavior of a circuit and are used in processes, procedures and functions, similarly as they would be in a programming language. Following is a brief discussion of each class of objects.
Constant
A constant can have a single value of a given type and cannot be changed during the simulation. A constant is declared as follows,
constant list_of_name_of_constant: type [ := initial value] ;
where the initial value is optional. Constants can be declared at the start of an architecture and can then be used anywhere within the architecture. Constants declared within a process can only be used inside that specific process.
constant RISE_FALL_TME: time := 2 ns;
constant DELAY1: time := 4 ns;
constant RISE_TIME, FALL_TIME: time:= 1 ns;
constant DATA_BUS: integer:= 16;
Variable
A variable can have a single value, as with a constant, but a variable can be updated using a variable assignment statement. The variable is updated without any delay as soon as the statement is executed. Variables must be declared inside a process (and are local to the process). The variable declaration is as follows:
variable list_of_variable_names: type [ := initial value] ;
A few examples follow:
variable CNTR_BIT: bit :=0;
variable VAR1: boolean :=FALSE;
variable SUM: integer range 0 to 256 :=16;
variable STS_BIT: bit_vector (7 downto 0);
The variable SUM, in the example above, is an integer that has a range from 0 to 256 with initial value of 16 at the start of the simulation. The fourth example defines a bit vector or 8 elements: STS_BIT(7), STS_BIT(6),… STS_BIT(0).
A variable can be updated using a variable assignment statement such as
Variable_name := expression;
As soon as the expression is executed, the variable is updated without any delay.
Signal
Signals are declared outside the process using the following statement:
signal list_of_signal_names: type [ := initial value] ;
signal SUM, CARRY: std_logic;
signal CLOCK: bit;
signal TRIGGER: integer :=0;
signal DATA_BUS: bit_vector (0 to 7);
signal VALUE: integer range 0 to 100;
Signals are updated when their signal assignment statement is executed, after a certain delay, as illustrated below,
SUM <= (A xor B) after 2 ns;
If no delay is specified, the signal will be updated after a delta delay. One can also specify multiple waveforms using multiple events as illustrated below,
signal wavefrm : std_logic;
wavefrm <= ‘0’, ‘1’ after 5ns, ‘0’ after 10ns, ‘1’ after 20 ns;
It is important to understand the difference between variables and signals, particularly how it relates to when their value changes. A variable changes instantaneously when the variable assignment is executed. On the other hand, a signal changes a delay after the assignment expression is evaluated. If no delay is specified, the signal will change after a delta delay. This has important consequences for the updated values of variables and signals. Lets compare the two files in which a process is used to calculate the signal RESULT [7].
Example of a process using Variables
|
architecture VAR of EXAMPLE is
signal TRIGGER, RESULT: integer := 0; begin process variable variable1: integer :=1; variable variable2: integer :=2; variable variable3: integer :=3; begin wait on TRIGGER; variable1 := variable2; variable2 := variable1 + variable3; variable3 := variable2; RESULT <= variable1 + variable2 + variable3; end process; end VAR |
Example of a process using Signals
|
architecture SIGN of EXAMPLE is
signal TRIGGER, RESULT: integer := 0; signal signal1: integer :=1; signal signal2: integer :=2; signal signal3: integer :=3; begin process begin wait on TRIGGER; signal1 <= signal2; signal2 <= signal1 + signal3; signal3 <= signal2; RESULT <= signal1 + signal2 + signal3; end process; end SIGN;
|
In the first case, the variables “variable1, variable2 and variable3” are computed sequentially and their values updated instantaneously after the TRIGGER signal arrives. Next, the RESULT, which is a signal, is computed using the new values of the variables and updated a time delta after TRIGGER arrives. This results in the following values (after a time TRIGGER): variable1 = 2, variable2 = 5 (=2+3), variable3= 5. Since RESULT is a signal it will be computed at the time TRIGGER and updated at the time TRIGGER + Delta. Its value will be RESULT=12.
On the other hand, in the second example, the signals will be computed at the time TRIGGER. All of these signals are computed at the same time, using the old values of signal1, 2 and 3. All the signals will be updated at Delta time after the TRIGGER has arrived. Thus the signals will have these values: signal1= 2, signal2= 4 (=1+3), signal3=2 and RESULT=6.