vhdl: Why is aggregate assignment not allowed in this context? - vhdl

I am trying to use aggregate assignments within a conditional assignment statement in the lines labelled "PROBLEMATIC LINE" in the following code implementation for a priority encoder module.
library ieee;
use ieee.std_logic_1164.all;
entity SN74LS148 is -- 8 to 3 line priority encoder module
port(EI : in std_logic; -- input enable
input : in std_logic_vector(0 to 7); -- 8 bit input bus
A : out std_logic_vector(2 downto 0); -- 3 output bits
GS, EO : out std_logic -- valid bit, enable output
);
end SN74LS148;
architecture behavioral of SN74LS148 is
signal truth_table : std_logic_vector(2 downto 0);
begin
truth_table <= "HHH" when input = (others => 'H') else -- PROBLEMATIC LINE
"LLL" when input(7) = 'L' else
"LLH" when input(6) = 'L' else
"LHL" when input(5) = 'L' else
"LHH" when input(4) = 'L' else
"HLL" when input(3) = 'L' else
"HLH" when input(2) = 'L' else
"HHL" when input(1) = 'L' else
"HHH" when input(0) = 'L' else
"XXX";
A <= truth_table when EI = 'L' else -- device enabled (active low)
"HHH" when EI = 'H' else -- device disabled (all outputs inactive)
"XXX";
GS <= 'H' when EI = 'H' -- invalid when device disabled
or input = (others => 'H') else -- or none of the lines asserted (PROBLEMATIC LINE)
'L';
EO <= 'L' when EI = 'L' and input = (others => 'H') else -- PROBLEMATIC LINE
'H';
end behavioral;
I am using the GHDL compiler. The error that I am getting is
encoder8x3.vhd:28:43: 'others' choice not allowed for an aggregate in this context
truth_table <= "HHH" when input = (others => 'H') else
^
encoder8x3.vhd:46:47: 'others' choice not allowed for an aggregate in this context
or input = (others => 'H') else -- or none of the lines asserted
^
encoder8x3.vhd:50:45: 'others' choice not allowed for an aggregate in this context
EO <= 'L' when EI = 'L' and input = (others => 'H') else
^
I guess I can fix this easily by hardcoding the inputs but what I want to know is why I am getting this error when the size of input has been specified in the port. This is not an ambiguity issue right ?

No, it is an ambiguity issue.
See IEEE Std 1076-1993 7.3.2.2 Array aggregates
The subtype of an array aggregate that has an others choice must be determinable from the context. That is, an array aggregate with an others choice may only appear
a. As an actual associated with a formal parameter or formal generic declared to be of a constrained array subtype (or subelement thereof)
...
Here the actual is your array aggregate associated with a parameter of the subprogram parameter for the overloaded equality operator, which is unconstrained. The type mark of that parameter would be the type std_logic_vector, while this would become a subtype in -2008 to allow subtype resolution specification it'd be unconstrained and the language of -2008 9.3.3.3 Array aggregates has been changed:
The index range of an array aggregate that has an others choice shall be determinable from the context.
That actually implies what's important here, the length of the aggregate array value. See 7.2.2 Relational operators:
Two scalar values of the same type are equal if and only if the values are the same. Two composite values of the same type are equal if and only if for each element of the left operand there is a matching element of the right operand and vice versa, and the values of matching elements are equal, as given by the predefined equality operator for the element type.
These rules also tell us the std_logic weak driving 'H' or 'L' enumeration values either as a scalar or an element of a composite value are not equal to the strong driving '1' and '0' values respectively.

As equality operator is defined by VHDL (7.2.2 of IEEE-1076-1993), there is no direct constraint between operands. For instance, if both operands are of the same array type, they may be not the same length (and equality will be always false), if they are of same length, elements are matched in order (whatever the range of array). This gives no strong constraint between operands.
In some contexts, literal array aggregates with others can be determined from context (initializations, assignments, etc.). Valid cases are listed in 7.3.2.2. Equality operator operands is not one of them.
You may still write an aggregate with an explicit range, for instance input = (input'range => 'H').

Related

VHDL parse error, unexpected INTEGER_LITERAL, expecting RETURN or IDENTIFIER or RSQBRACK Process "Check Syntax" failed

I am writing a VHDL Program for 4:1 MUX and am facing a error on the line where process clause starts
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux_41 is
Port ( inp : in STD_LOGIC_VECTOR (0 downto 3);
outp : out STD_LOGIC;
sel : in STD_LOGIC_VECTOR (1 downto 0));
end mux_41;
architecture Behavioral of mux_41 is
begin
Process(inp[0],inp[1],inp[2],inp[3],sel[0],sel[1])
begin
if(sel = "00")
then outp <= inp[0];
elsif(sel = "01")
then outp <= inp[1];
elsif(sel = "10")
then outp <= inp[2];
else outp <= inp[3];
end if;
end process;
end Behavioral;
Is this the right way to pass sensitivity list to process?
In VHDL when you want to access to a particular element of an array (std_logic_vector are array), you have to use () instead of [].
Process(inp(0),inp(1),inp(2),inp(3),sel(0),sel(1))
begin
if(sel = "00")
then outp <= inp(0);
elsif(sel = "01")
then outp <= inp(1);
elsif(sel = "10")
then outp <= inp(2);
else outp <= inp(3);
end if;
end process;
The OP doesn't show the complete error message.
It appears to be in the sensitivity list for the process where inp is a signal_name and the particular parser doesn't use syntactic predicates:
IEEE Std 1076-2008 10.2 Wait statements
sensitivity_list ::= signal_name { , signal_name }
and here the selected names (8.3) are all static names (8.1) and all the elements of both sel and inp are evaluated in the process if statement (10.8) and should be included in the sensitivity set (10.2).
1.3.2 Syntactic description
The form of a VHDL description is described by means of context-free syntax using a simple variant of the Backus-Naur form (BNF); in particular:
...
g) If the name of any syntactic category starts with an italicized part, it is equivalent to the category name without the italicized part. The italicized part is intended to convey some semantic information. For example, type_name and subtype_name are both syntactically equivalent to name alone
...
It's possible to write a parser that uses a symbol table containing declarations of named entities (which precede the use of a name in a description). It simplifies both syntactical and semantic analysis while allowing the rules of visibility and scope to be tracked.
In any event not using syntactic predicates results in a different error message. Instead of an error describing a signal as not having a signature you get an error message saying the signature is malformed or isn't applicable (there are several rules that might be applicable without the syntactic predicates).
The error actually occurs for the first left square bracket. Selected names uses parentheses (round brackets in parts or Europe) instead of square brackets. Also inp by itself has elements 3 downto 0 or 0 to 3 (noting inp : in STD_LOGIC_VECTOR (0 downto 3) has a null range (5.2.1) and no elements).
5.2.1 pargraphs 3 and 4:
A range specifies a subset of values of a scalar type. A range is said to be a null range if the specified subset is empty.
The range L to R is called an ascending range; if L > R, then the range is a null range. The range L downto R is called a descending range; if L < R, then the range is a null range. ...
With a process sensitivity list a process statement (11.3) is assumed to have a single implicit wait statement as it's last sequential statement. The rule for constructing the sensitivity set for the implicit wait statement in a process statement are found in 10.2 Wait statement, where the implicit wait statement will use the longest static prefix (8.1) of any signal name in the process sensitivity list and would be equivalent to process (sel, inp).
11.3 Process statement paragraph 4:
If a process sensitivity list appears following the reserved word process, then the process statement is assumed to contain an implicit wait statement as the last statement of the process statement part; this implicit wait statement is of the form
wait on sensitivity_list ;
where the sensitivity list is determined in one of two ways. If the process sensitivity list is specified as a sensitivity list, then the sensitivity list of the wait statement is that following the reserved word process. ...
10.2 Wait statement paragraphs 3 and 4:
The sensitivity clause defines the sensitivity set of the wait statement, which is the set of signals to which the wait statement is sensitive. Each signal name in the sensitivity list identifies a given signal as a member of the sensitivity set. Each signal name in the sensitivity list shall be a static signal name, and each name shall denote a signal for which reading is permitted. If no sensitivity clause appears, the sensitivity set is constructed according to the following (recursive) rule:
The sensitivity set is initially empty. For each primary in the condition of the condition clause, if the primary is
— A simple name that denotes a signal, add the longest static prefix of the name to the sensitivity set.
— An expanded name that denotes a signal, add the longest static prefix of the name to the sensitivity set.
— A selected name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set.
— An indexed name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set and apply this rule to all expressions in the indexed name.
— A slice name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set and apply this rule to any expressions appearing in the discrete range of the slice name.
...
This rule is also used to construct the sensitivity sets of the wait statements in the equivalent process statements for concurrent procedure call statements (11.4), concurrent assertion statements (11.5), and concurrent signal assignment statements (11.6). Furthermore, this rule is used to construct the sensitivity list of an implicit wait statement in a process statement whose process sensitivity list is the reserved word all (11.3).
What this tells us is that the longest static prefix is sufficient in the sensitivity list.
8.1 paragraph 7:
A static signal name is a static name that denotes a signal. The longest static prefix of a signal name is the name itself, if the name is a static signal name; otherwise, it is the longest prefix of the name that is a static signal name. ...
With a non-null range for inp, using parentheses instead of square brackets your mux_41 could be expressed:
library ieee;
use ieee.std_logic_1164.all;
entity mux_41 is
port (
inp: in std_logic_vector (3 downto 0);
outp: out std_logic;
sel: in std_logic_vector (1 downto 0)
);
end entity mux_41;
architecture behavioral of mux_41 is
begin
process (sel, inp)
begin
if sel = "00" then
outp <= inp(0);
elsif sel = "01" then
outp <= inp(1);
elsif sel = "10" then
outp <= inp(2);
else
outp <= inp(3);
end if;
end process;
end architecture behavioral;
Here with the process sensitivity list supplied with the longest static prefix.
This code will analyze (compile) successfully.

VHDL initialize signal with maximum value of type

I have this definition:
subtype sample_t is signed(SAMPLE_WIDTH-1 downto 0);
Now in the code I want to set a signal to the maximum value of sample_t divided by 2:
signal max_sample : sample_t;
max_sample <= to_signed(max_sample'<some attribute>/2,max_sample'LENGTH);
I've looked at attributes sample_t'HIGH and sample_t'RIGHT but these seem to return the highest subscript of the array.
From this list: https://www.csee.umbc.edu/portal/help/VHDL/attribute.html
T'HIGH is the highest value of type T.
A'HIGH is the highest subscript of array A or constrained array type.
How to use the first definition on sample_t?
One of the commenters suggestions:
max_sample <= (max_sample'LEFT => '0', others => '1');
works. But this:
max_sample <= (max_sample'LEFT => '0', others => '1')/2;
fails with "OTHERS is illegal aggregate choice for unconstrained target".
why this error?
In VHDL, signed is an array type, not an integer. The core language only knows that it is a collection of std_logic objects. It's interpretation as a number is only by convention introduced by the numeric_std library functions defining the operators and type casts for signed. As such, integer specific attributes aren't going to work on an array type.
The reason why your last attempt at division fails is that the aggregate expression forming the dividend doesn't yet have a fully determined range due to the others. The aggregate is still just an intermediate temporary and can't pick up its length from max_sample. That prevents the division operator from compiling.
It will compile if you use a fully constrained range:
max_sample <= (max_sample'high => '0', max_sample'high-1 downto max_sample'low => '1') / 2;
Or if you use a qualified expression:
max_sample <= sample_t'(max_sample'high => '0', others => '1') / 2;
An alternate solution is just to subtype integer instead of using signed. Then you can use it in a more integery way:
constant SAMPLE_T_MAX : integer := 2**(SAMPLE_WIDTH-1)-1;
subtype sample_t is integer range -SAMPLE_T_MAX-1 to SAMPLE_T_MAX;
max_sample <= sample_t'high; -- Assuming that the "divide by 2" was just to avoid the sign bit
This will not work if sample_t_max exceeds the largest integer size your tooling supports which is still typically 32-bits including the sign. Also, for practical reasons, it is best not to use integer types for signals that will be exposed on the top level port after synthesis.
Otherwise you have to work within the limitations of using array types for numerics. Your options are to resort to bit twiddling as above or just directly compute the max value similarly to the integer subtype:
constant SAMPLE_T_MAX : integer := 2**(sample_t'length-1)-1;
max_sample <= to_signed(SAMPLE_T_MAX, max_sample'length);
The accepted answer from Kevin Thibedeau could not be readily reconciled with the actual question (why this error?). The answer can be explained in terms of the VHDL standard.
First a Minimum, Complete, and Verifiable example can be constructed for the question:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture fum of foo is
constant SAMPLE_WIDTH: natural := 42; -- pick a number
subtype sample_t is signed(SAMPLE_WIDTH-1 downto 0);
signal max_sample : sample_t;
begin
-- max_sample <= (max_sample'LEFT => '0', others => '1'); -- analyzes
max_sample <= (max_sample'LEFT => '0', others => '1')/2; -- Doesn't analyze
end architecture;
Because we're dealing with semantic rules during analysis (compile) the example doesn't have to do anything besides replicate the error. Error messages aren't standardized in VHDL and will vary by implementation.
The semantics for using an others choice in an aggregate:
IEEE Std 1076-2008 9.3 Aggregates, 9.3.3 Array aggregates, para 7 (in part):
The index range of an array aggregate that has an others choice shall be determinable from the context. That is, an array aggregate with an others choice shall appear only in one of the following contexts:
...
e) As a value expression in an assignment statement, where the target is a declared object (or member thereof), and either the subtype of the target is a fully constrained array subtype or the target is a slice name
This is why the first example (commented out) analyzes. sample_t is a fully constrained subtype, see 5. Types, 5.1 General the definition of fully constrained, para 6 (in part):
A composite subtype is said to be fully constrained if:
-- It is an array subtype with an index constraint and the element subtype either is not a composite subtype or is a fully constrained composite type, or
...
Where the sample_t element base type is std_ulogic and the subtype has an index constraint.
Back to the second example.
We don't satisfy rule e), the aggregate isn't a value expression for the assignment statement, it's an operand for the division operator defined by the "/" function for overload in IEEE package numeric_std:
-- Id: A.25
function "/" (L : UNRESOLVED_SIGNED; R : INTEGER) return UNRESOLVED_SIGNED;
-- Result subtype: UNRESOLVED_SIGNED(L'LENGTH-1 downto 0)
-- Result: Divides an UNRESOLVED_SIGNED vector, L, by an INTEGER, R.
-- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH.
(For earlier revisions of numeric_std the parameter and result types would be SIGNED instead of UNRESOLVED_SIGNED, -2008 formally defines how resolution functions of composite types drivers are defined.)
Because the rules of 9.3.3 paragraph 7 are inclusive instead of exclusive we
need to find a rule that allows us to use the aggregate, and one is readily identified:
i) As the operand of a qualified expression whose type mark denotes a fully constrained array subtype
We can use a qualified expression:
max_sample <= sample_t'(max_sample'LEFT => '0', others => '1')/2;
And this analyzes (compiles) successfully.
To clarify the value expression being assigned to max_sample is the result of division by 2 which uses an operator overload and who's function does not return a constrained subtype. (UNRESOLVED_SIGNED or SIGNED is not constrained).
The reason why there are inclusive rules is to allow the code for associating values with elements of an aggregate to be determined at analysis time (compile time). You'd find by examining previous revisions of the VHDL standard that the list of inclusive rules has been expanded.
The answer to your question with respect to the second example:
max_sample <= (max_sample'LEFT => '0', others => '1')/2;
is that the elements of the aggregate can't be identified without knowing the subtype from context.
If you were to look at the output of the parser producing an abstract syntax tree used for semantic analysis the right hand side expression in the assignment statement can be expressed hierarchically. (11.6 Concurrent signal assignment statements, the waveform is comprised of one or more waveform elements, see 10.5.2 Simple signal assignments, 10.5.2.1 General, a waveform element can contain a value expression, see 10.5.2.2 Executing a simple assignment statement, 9. Expressions, 9.1 General the BNF.)
Using inclusive rules alleviates the need of traversing the expression hierarchy and calculating the subtype of the aggregate (an operand) during analysis and would require semantic characterization of the "/" function not required by the standard. You can also construct cases where the subtype can't be readily ascertained by characterization at analysis time. The result is the rules found in 9.3.3 Array aggregates paragraph 7.
The qualified expression provides the subtype directly.

Modelsim: Does a 'X' in a std_logic_vector affect the other bits in the vector?

I have a Signal myVec : std_logic_vector(8 down 0). Modelsim shows this value: 0X000010. So bit(6) is Undefined. Does this affect other bits for example to bit(1)?
I change the state with the following:
if myVec(1) = '0' then
--change the state to x
else
--change state to y
end if;
The problem is that the state always switches to y and I don't know why.
Could it be that bit(6) of myVec has an affect to bit(1) or the other bits?
'X' is not undefined. std_logic_1164 defines 'X' as "Forcing Unknown". IF required, 'U' is used for "uninitialized" =~ undefined.
'X' actually means that a signal could not be properly resolved, e.g. it is driven by both '1' and '0'. If you change the type from std_logic to std_ulogic, you will probably see where this happens.
But your question: Unless implemented differently, the individual elements in an array do not affect each other.

Others => '1' statement in Verilog

I have used VHDL all my life and only been using Verilog for a short time, I have to create a logic in Verilog for a very large array and assign it to 1 or 0 depending on the condition of an input.
Here is my VHDL code
if (data_track == '1' ) then
my_array(MAX-1:MIN) <= (others=> '1');
else
my_array(MAX-1:MIN) <= (others=> '0');
end if;
MAX and MIN are parameters for the block, set during the synthesis depending on the type of system we are accessing.
Is there a way to do this in Verilog easily?
A mix of parameter with curly braces will help in resolving (the inner curly brace will act as replication operator)
Code eg:
parameter MAX = 16;
assign high_val = 1'b1;
assign low_val = 1'b0;
if ( data_track ==1'b1)
my_array[MAX-1:MIN] <= {MAX{high_val}};
else
my_array[MAX-1:MIN] <= {MAX{low_val}};
Here in the above code the if statement with curly brace will propogate MSB to LSB with 1 values resulting in all 1's in our case 16 then result will be a 16'b1111111111111111 and it is the vice versa for else condition
Assuming that data_track is one bit wide, then this can be collapsed into one line by replicating the data_track input and assigning it to my_array:
assign my_array[MAX-1:MIN] = {(MAX-MIN){data_track}};

Can a constant expression ever be valid in a VHDL case statement?

I recall that in Verilog it can be valid to use a constant in the expression of a case statement, but is it also valid in VHDL?
// Verilog example
case(1'b1)
A[2]: Y<=2'b11;
A[1]: Y<=2'b10;
A[0]: Y<=2'b01;
default:Y<=2'b00;
endcase
The following code is not exactly parallel to your example, but it may be useful:
This compiles:
process
constant S : std_logic := '1';
begin
case S is
when '0' =>
when '1' =>
when others =>
end case;
end process;
So does this:
process
begin
case std_logic'('1') is
when '0' =>
when '1' =>
when others =>
end case;
end process;
This does not:
process
begin
case '1' is
when '0' =>
when '1' =>
when others =>
end case;
end process;
'1' is ambiguous (std_logic / character).
Now, what you're actually doing is a bit different, and I'm not sure what your intent is. You seem to want to determine the highest bit that is set. In VHDL, your construct would only be valid syntactically if A is also constant (case choices need to be locally static), in which case there are much easier ways to accomplish this (e.g. a for loop). There's the problem of mutual exclusion, though - in general, case choices are bound to overlap, and I would think that should be illegal (though ModelSim didn't complain when I tried it - synthesis tools may be another story). I would say it's definitely not a great idea either way.
No you can't express the case statement as a VHDL case statement
Unlike Verilog, IEEE Std 1364-2005 9.5 Case statement para 4:
The case expression and the case item expression can be computed at
run time; neither expression is required to be a constant expression.
In IEEE Std 1076-1993 8.8 Case statement, para 8 (also representative of -2008):
The simple expression and discrete ranges given as choices in a case
statement must be locally static. A choice defined by a discrete range
stands for all values in the corresponding range. The choice others is
only allowed for the last alternative and as its only choice; it
stands for all values(possibly none) not given in the choices of
previous alternatives. An element simple name (see 7.3.2 ) is not
allowed as a choice of a case statement alternative.
From the glossary:
locally static expression: An expression that can be evaluated during the analysis of the design unit in which it appears.
analysis: The syntactic and semantic analysis of source code in a VHDL design file and the insertion of intermediate form representations of design units into a design library.
(A fancy way of telling us compile time as opposed to elaboration (linking and loading). VHDL's definitions also embrace interpretive implementation.)
The definition of a locally static expression requires A to be declared as a constant and in the VHDL LRM -1993 version a slice name or index name isn't locally static (See IEEE Std 1076-1993, 7.4.1 Locally static primaries para 1, 7.4.2 Globally static primaries, r. - globally static means at elaboration time). This is changed in the IEEE Std 1076-2008 for static index expressions or static index ranges (See IEEE Std 1076-2008, 9.4.2, n. and o.). It's likely synthesis vendors tools lag, even if you can simulate it, you likely can't synthesis it today.
There's also the issue of multiple choices with the same value. See IEEE Std 1076-1993 8.8 Case statement, para 3 (also representative of -2008 for this issue):
The expression must be of a discrete type, or of a one-dimensional
array type whose element base type is a character type. This type must
be determinable independently of the context in which the expression
occurs, but using the fact that the expression must be of a discrete
type or a one-dimensional character array type. Each choice in a case
statement alternative must be of the same type as the expression; the
list of choices specifies for which values of the expression the
alternative is chosen.
Where the expressions std_logic'('1') or S have a base type of std_ulogic. And this eliminates choices that are not of the base type of std_logic (std_ulogic - 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', See IEEE Std 1076-2008 16.7 Standard multivalue logic package and Annex A footnote 15 which provides a link to the source for package std_logic_1164).
Notice fru1tbat showed choices '0', '1' and others, evaluation of the expressions A(2), A(1) or A(0) returns a std_ulogic subtype and would give you multiple choices representing the same value ('1'). See IEEE Std 1076-1993, 8.8 para 7:
For other forms of expression, each value of the (base) type of the
expression must be represented once and only once in the set of
choices, and no other value is allowed.
So the case statement isn't directly expressible in VHDL, we're only interested in cases where A(2), A(1) and A(0) are '1' and only one choice is allowed. Instead we can use a conditional signal assignment statement:
library ieee;
use ieee.std_logic_1164.all;
entity constexp is
end entity;
architecture foo of constexp is
signal A: std_logic_vector (2 downto 0) := "001";
signal Y: std_logic_vector (1 downto 0);
begin
COND: -- Conditional Signal Assignment statement
Y <= "11" when A(2) = '1' else
"10" when A(1) = '1' else
"01" when A(0) = '1' else
"00";
end architecture;
(And this design specification analyzes, elaborates and simulates.)
A conditional signal assignment is a concurrent statement in the 1076-1993 standard (See 9.5.1 Conditional signal assignments) while a conditional signal assignment can be used as a sequential statement as well in the 1076-2008 standard (See 11.6 Concurrent signal assignment statements and 10.5.3 Conditional signal assignment). Today it's likely synthesis vendors would be -1993 compliant.
And by definition any of the constructs here can be devolved into if statements which are sequential statements.

Resources