If you are wondering about how the <= operator works; it is what is called a 'nonblocking assignment.' What this means is that the left hand side of all of the <= are performed for a particular event (e.g. rising clock edge) and then once those are all evaluated, the result is placed in the output. This allows you to write shift registers without temporary variables. None of the values change until the left hand calculations are completed, then the results are moved over to the right hand side. It is generally not a good idea to use nonblocking assignments for combinatorial logic. Generally they are only used to create latches and registers and you use regular blocking assignments for combinatorial logic. When synchronized with a clock signal, you can generally consider <= operations to be D flip-flops that sample the input and transfer it to the output atomically on a single clock edge.
'Race conditions' where intermediate indeterminate results appear on the outputs of combinatorial functions are hard to avoid and they can depend greatly on how the design is actually implemented on an ASIC or FPGA. However, most designs are synchronous and so as long as the output settles within one clock period this is not a problem. There are tools that can check the timing performance of a design to check all of the path delays to ensure that the results will always be valid for a given clock frequency, but this is highly dependent not on the actual HDL code but on the way the design is placed and routed.
Synthesizers (not compilers!!!!) will generally perform optimization on combinatorial logic. There are limits to how much the synthesizer can do (e.g. it will not re-architect your system) so you have to know more or less how it will end up being implemented. If you're working on an FPGA, generally the synthesis and place and route will pack any logic function that fits onto LUTs. So if you can separate out a single logic function with up to 4 inputs and 1 output, this will end up on a single LUT and the only delay that matters is the propagation delay of the LUT, which is the same for all of its inputs. In the case of your example function, both pieces of code may be implemented identically on one LUT with three inputs and one output.
suppose if I have two signal declarations as follows
signal x:std_logic_vector(1 downto 0) := (others => '0');
signal y:std_logic_vector(1 downto 0);
does that mean x is static and y is non-static?
No. Values determined by evaluating signals in expressions are not static.
The difference between the declarations of x
and y
is that x
has a default value expression provided that is different than y
. Both have default values, the value for x
is provided by a locally static aggregate expression depending on the locally static range of x
via others
and the locally static value of the enumeration literal '0'
.
From IEEE Std 1076-2008, 9 Expressions, 9.1 General:
An expression is a formula that defines the computation of a value.
From 9.4 Static expressions:
Certain expressions are said to be static. Similarly, certain discrete ranges are said to be static, and the type marks of certain subtypes are said to denote static subtypes.
There are two categories of static expression. Certain forms of expression can be evaluated during the analysis of the design unit in which they appear; such an expression is said to be locally static. Certain forms of expression can be evaluated as soon as the design hierarchy in which they appear is elaborated; such an expression is said to be globally static.
The expressions found in the two signal declarations are all locally static, derived from literals (0
, 1
and '0'
), 0
and 1
specifying locally static ranges, in x
providing the choice others
in the aggregate expression for it's default value, for every element in the index range for x
, a '0'
is provided as the default value.
Also does a vhdl function call fall into the category of a non-static expression?
See 4. Subprograms and packages, 4.1 General, paragraph 2:
There are two forms of subprograms: procedures and functions. A procedure call is a statement; a function call is an expression and returns a value. Certain functions, designated pure functions, return the same value each time they are called with the same values as actual parameters; the remainder, impure functions, may return a different value each time they are called, even when multiple calls have the same actual parameter values. ...
So a function call is an expression. An expression can be either locally static or globally static:
9.4.2 Locally static primaries
An expression is said to be locally static if and only if every operator in the expression denotes an implicitly defined operator or an operator defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE, and if every primary in the expression is a locally static primary, where a locally static primary is defined to be one of the following:
...
e) A function call whose function name denotes an implicitly defined operation or an operation defined
in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE and whose actual parameters are each locally static expressions
...
9.4.3 Globally static primaries
An expression is said to be globally static if and only if every operator in the expression denotes a pure function and every primary in the expression is a globally static primary, where a globally static primary is a primary that, if it denotes an object or a function, does not denote a dynamically elaborated named entity (see 14.6) and is one of the following:
...
i) A function call whose function name denotes a pure function and whose actual parameters are each globally static expressions
...
Essentially the parameters to a function call must be either locally static or globally static and the function must be a pure function for the expression determined by a function call to be static. (All predefined operators for predefined types are pure).
If these requirements are not met then the function call expression is not static. An easy example would be a parameter that is either a variable or a signal, both requiring evaluation during execution.
Best Answer
It's helpful when asking VHDL to question to provide a minimal, complete, and verifiable example pointing to an error.
Here's a solution:
The entire bit analyzes and some_entity_tb elaborates and runs (without actually doing anything useful other than proving connectivity).
You have the ability in VHDL (incl. -93) to associate elements (members) of an array port formal separately.
IEEE Std 1076-1993 4.3.2.2 Association lists, para 14:
And to explain where the error message:
came from:
IEEE Std 1076-1993, 12.3 Elaboration of a declarative part, para 3:
It's telling you that you can't assign an expression as an actual to a formal unless the value of the object
signal_id
is known at elaboration time, and a signal's value isn't known until after elaboration: