vhdl case...is and with...select - select

I'm trying to write something on VHDL, but it's not working. Here's part of my code:
case currentState is
when ST000 =>
with A select nextState <=
ST025 when "01",
ST050 when "10",
ST000 when "11",
currentState when others;
when ST001 => ...
when others => ...
end case;
It says there's a problem in these lines, like this: Line 62. parse error, unexpected WITH. Why is this with unexpected? Is it wrong to mix these two syntaxes, case...is and with...select, together?

Unless otherwise notes, reference are from IEEE Std 1076-2008, IEEE VHDL Language Reference Manual.
10. Sequential statements
10.1 General
The various forms of sequential statements are described in this clause. Sequential statements are used to define algorithms for the execution of a subprogram or process; they execute in the order in which they appear.
10.9 Case statement
A case statement selects for execution one of a number of alternative sequences of statements; the chosen alternative is defined by the value of an expression.
A sequence of statements indicates sequential statements.
10.5.4 Selected signal assignments
The selected signal assignment represents an equivalent case statement that assigns values to signals or that forces or releases signals.
However...
Annex E
(informative)
Changes from IEEE Std 1076-2002
...
Clause 10
— 10.5: Addition of force and release assignment; addition of simple, conditional and selected signal assignment.
In revisions of the VHDL standard earlier than -2008 selected signal assignments were only available as concurrent signal assignment statements (See 11.6 Concurrent signal assignment statements, or found in Clause/Chapter 9 Concurrent Statements, subsection 9.5.2 Selected signal assignment in earlier revisions of the VHDL standard).
Note that when inconvenient or lacking support for this -2008 feature you can substitute a case statement:
case currentState is
when ST000 =>
case A is
when "01" =>
nextState <= ST025;
when "10" =>
nextState <= ST050;
when "11" =>
nextState <= ST000;
when others =>
nextState <= CurrentState;
end case;
when ST001 => ...
when others => ...
end case;

Related

How does SystemVerilog handle possible wildcard conflicts in case statements?

When I write a case statement that includes wildcards for the cases, how are more or less specific cases handled?
always_comb case(selector)
4'b0???: begin // Pick me if the msb is 0, unless the two lsb's are 01.
end
4'b0?01: begin // Pick me if the msb is 0 and the two lsb's are 01.
end
default: begin // Pick me if the msb is X or 1.
end
endcase
In the simplified example above, the first case (all wildcards) could be selected for any value of selector, but I want it to select the most specific possible case. Is that how cases are handled?
SystemVerilog assumes the case statement is in priority order - the second item is never matched. So you need to move the most specific cases first. SystemVerilog has unique case and priority case constructs to better specify your intent.

VHDL 'range => '0' command

Was hoping someone could answer my question. I came across this command in a VHDL code and was not sure what it does exactly. Could someone clarify the following?
if ( element1 = (element1'range => '0')) then
given that element1 is a 4 bit std_logic_vector, what is this condition saying? I could not find a direct answer for this in the few books I had or on google.
Thanks!
It's saying, create a temporary array aggregate the size of the range specified, with every element set to '0'. Whatever that range is.
Preventing accidents when the size of element1 changes.
EVERY time you see magic numbers like 3 downto 0, or for i in 0 to 3 loop ... try to replace them with this or equivalent, because for i in element1'range loop ... will never loop off the end of your array.
The defined range is necessary because the relational operator = (like <, > and the others) doesn't restrict its arguments to the same length, so the simpler form of aggregate (others => '0') doesn't work, because its size is undefined.
The condition will return true if element1 contains only '0'. It is a way of writing this that does not depend on the size of element1. In this case element1'range is 3 downto 0. If you were to change this to, for example, 5 downto 0, the if condition would still work.
(element1'range => '0') is an array aggregate with element choices for the range of element1 and associates those elements with the value '0' creating a composite value that takes it's type from context - the left hand side of the "=" operator (IEEE Std 1076-2008 9.3.3 Aggregates, 9.3.3.3 Array aggregates).
The if statement (10.8 If statement) condition element1 = (element1'range => '0') determines if element1 is all '0's in a range independent manner, the equality relational operator (9.2.3 Relational operators) returning a BOOLEAN value.
This method of evaluating the value of element1 is immune to the declaration of element1 changing (6.4.2 Object declarations, 6.4.2.3 Signal declarations, 6.4.2.4 Variable declarations, 6.5.2 Interface object declarations).
The outer pair of parentheses for the condition (an expression) are superfluous in VHDL (10.2 Wait statement, the BNF for condition, 9. Expressions, 9.1 General, the BNF for intermediary target primary allows them).

What is the difference between ( := ) and ( = ) in PostgreSQL? [duplicate]

The documentation for PL/pgSQL says, that declaration and assignment to variables is done with :=.
But a simple, shorter and more modern (see footnote) = seems to work as expected:
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$
DECLARE
i int;
BEGIN
i = 0;
WHILE NOT i = 25 LOOP
i = i + 1;
i = i * i;
END LOOP;
RETURN i;
END;
$$ LANGUAGE plpgsql;
> SELECT foo();
25
Please note, that Pl/pgSQL can distinguish assignment and comparison clearly as shown in the line
WHILE NOT i = 25 LOOP
So, the questions are:
Didn't I find some section in the docs which mention and/or explains this?
Are there any known consequences using = instead of :=?
Edit / Footnote:
Please take the "more modern" part with a wink like in A Brief, Incomplete, and Mostly Wrong History of Programming Languages:
1970 - Niklaus Wirth creates Pascal, a procedural language. Critics
immediately denounce Pascal because it uses "x := x + y" syntax
instead of the more familiar C-like "x = x + y". This criticism
happens in spite of the fact that C has not yet been invented.
1972 - Dennis Ritchie invents a powerful gun that shoots both forward
and backward simultaneously. Not satisfied with the number of deaths
and permanent maimings from that invention he invents C and Unix.
In PL/PgSQL parser, assignment operator is defined as
assign_operator : '='
| COLON_EQUALS
;
This is a legacy feature, present in source code since 1998, when it was introduced - as we can see in the PostgreSQL Git repo.
Starting from version 9.4 it is oficially documented.
This idiosyncrasy - of having two operators for same thing - was raised on pgsql users list, and some people requested it to be removed, but it's still kept in the core because fair corpus of legacy code relies on it.
See this message from Tom Lane (core Pg developer).
So, to answer your questions straight:
Didn't I find some section in the docs which mention and/or explains
this?
You did not find it because it was undocumented, which is fixed as of version 9.4.
Are there any known consequences using = instead of :=.
There are no side consequences of using =, but you should use := for assignment to make your code more readable, and (as a side effect) more compatible with PL/SQL.
Update: there may be a side consequence in rare scenarios (see Erwin's answer)
UPDATE: answer updated thanks to input from Daniel, Sandy & others.
Q1
This has finally been added to the official documentation with Postgres 9.4:
An assignment of a value to a PL/pgSQL variable is written as:
variable { := | = } expression;
[...] Equal (=) can be used instead of PL/SQL-compliant :=.
Q2
Are there any known consequences using = instead of :=?
Yes, I had a case with severe consequences: Function call with named parameters - which is related but not exactly the same thing.
Strictly speaking, the distinction in this case is made in SQL code. But that's an academic differentiation to the unsuspecting programmer.1
Consider the function:
CREATE FUNCTION f_oracle(is_true boolean = TRUE) -- correct use of "="
RETURNS text
LANGUAGE sql AS
$func$
SELECT CASE $1
WHEN TRUE THEN 'That''s true.'
WHEN FALSE THEN 'That''s false.'
ELSE 'How should I know?'
END
$func$;
Note the correct use of = in the function definition. That's part of the CREATE FUNCTION syntax - in the style of an SQL assignment.2
Function call with named notation:
SELECT * FROM f_oracle(is_true := TRUE);
Postgres identifies := as parameter assignment and all is well. However:
SELECT * FROM f_oracle(is_true = TRUE);
Since = is the SQL equality operator, Postgres interprets is_true = TRUE as SQL expression in the context of the calling statement and tries to evaluate it before passing the result as unnamed positional parameter. It looks for an identifier is_true in the outer scope. If that can't be found:
ERROR: column "is_true" does not exist
That's the lucky case and, luckily, also the common one.
When is_true can be found in the outer scope (and data types are compatible), is_true = TRUE is a valid expression with a boolean result that is accepted by the function. No error occurs. Clearly, this is the intention of the programmer using the SQL equality operator = ...
This db<>fiddle demonstrates the effect.
Old sqlfiddle
Very hard to debug if you're unaware of the distinction between = and :=.
Always use the the correct operator.
1 When using named notation in function calls, only := is the correct assignment operator. This applies to functions of all languages, not just PL/pgSQL, up to and including pg 9.4. See below.
2
One can use = (or DEFAULT) to define default values for function parameters. That's not related to the problem at hand in any way. It's just remarkably close to the incorrect use case.
Postgres 9.0 - 9.4: Transition from := to =>
The SQL standard for assignment to named function parameters is => (and Oracle's PL/SQL uses it. Postgres could not do the same, since the operator had previously been unreserved, so it's using PL/pgSQL's assignment operator := instead. With the release of Postgres 9.0 the use of => for other purposes has been deprecated. The release notes:
Deprecate use of => as an operator name (Robert Haas)
Future versions of PostgreSQL will probably reject this operator name
entirely, in order to support the SQL-standard notation for named
function parameters. For the moment, it is still allowed, but a
warning is emitted when such an operator is defined.
If you should be using => for something else, cease and desist. It will break in the future.
Postgres 9.5: use => now
Starting with this release, the SQL standard operator => is used. := is still supported for backward compatibility. But use the standard operator in new code that doesn't need to run on very old versions.
Documented in the manual, chapter Using Named Notation.
Here's the commit with explanation in GIT.
This applies to named parameter assignment in function calls (SQL scope), not to the assignment operator := in plpgsql code, which remains unchanged.
A partial answer to my own question:
The PL/pgSQL section Obtaining the Result Status shows two examples using a special syntax:
GET DIAGNOSTICS variable = item [ , ... ];
GET DIAGNOSTICS integer_var = ROW_COUNT;
I tried both := and = and they work both.
But GET DIAGNOSTICS is special syntax, so one can argue, that this is also not a normal PL/pgSQL assignment operation.
Reading the Postgresql 9 documentation:
This page lists "=" as an assignment operator in the table on operator precedence.
But strangely this page (assignment operator documentation) doesn't mention it.

What should '{default:'1} do in system verilog?

I have an array that I would like to initialize to all 1. To do this, I used the following code snippet:
logic [15:0] memory [8];
always_ff #(posedge clk or posedge reset) begin
if(reset) begin
memory <= '{default:'1};
end
else begin
...
end
end
My simulator does what I think is the correct thing and sets the registers to 16'hFFFF on reset. However, my lint tool gives me a warning that bit 0 has an async set while bits 1 through 15 have async resets. This implies that the linter thinks that this code assigns 16'h0001 to the registers.
Since both tools come from the same vendor I file a bug report since they can't both be right.
The question is: Which behavior is correct according to the spec? There is no example that shows this exact situation. Section 5.7.1 mentions that:
An unsized single-bit value can be specified by preceding the single-bit value with an apostrophe ( ' ), but
without the base specifier. All bits of the unsized value shall be set to the value of the specified bit. In a
self-determined context, an unsized single-bit value shall have a width of 1 bit, and the value shall be treated
as unsigned.
'0, '1, 'X, 'x, 'Z, 'z // sets all bits to specified value
I f this is a "self-determined context" then the answer is 1 bit sign extended to 16'h0001, but if it is not, then I guess the example which says it "sets all bits to the specified value" applies. I am not sure if this is a self -determined context.
The simulator is correct: memory <= '{default:'1}; will assign all each bit in memory to 1. The linting tool does have a bug. See IEEE Std 1800-2012 § 10.9.1 Array assignment patterns:
The **default:***value* applies to elements or subarrays that are not matched by either index or type key. If the type of the element or subarray is a simple bit vector type, matches the self-determined type of the value, or is not an array or structure type, then the value is evaluated in the context of each assignment to an element or subarray by the default and shall be castable to the type of the element or subarray; otherwise, an error is generated. ...
The LRM goes beyond what is synthesizable when it comes to assignment patterns. And most of the tools are sill playing catchup with supporting all the SystemVerilog features. Experiment to make sure your tools (simulator,synthesizer, lint tool, logic-equivalency-checker, etc.) all have the necessary support for the features you want.

The forgotten assignment operator "=" and the commonplace ":="

The documentation for PL/pgSQL says, that declaration and assignment to variables is done with :=.
But a simple, shorter and more modern (see footnote) = seems to work as expected:
CREATE OR REPLACE FUNCTION foo() RETURNS int AS $$
DECLARE
i int;
BEGIN
i = 0;
WHILE NOT i = 25 LOOP
i = i + 1;
i = i * i;
END LOOP;
RETURN i;
END;
$$ LANGUAGE plpgsql;
> SELECT foo();
25
Please note, that Pl/pgSQL can distinguish assignment and comparison clearly as shown in the line
WHILE NOT i = 25 LOOP
So, the questions are:
Didn't I find some section in the docs which mention and/or explains this?
Are there any known consequences using = instead of :=?
Edit / Footnote:
Please take the "more modern" part with a wink like in A Brief, Incomplete, and Mostly Wrong History of Programming Languages:
1970 - Niklaus Wirth creates Pascal, a procedural language. Critics
immediately denounce Pascal because it uses "x := x + y" syntax
instead of the more familiar C-like "x = x + y". This criticism
happens in spite of the fact that C has not yet been invented.
1972 - Dennis Ritchie invents a powerful gun that shoots both forward
and backward simultaneously. Not satisfied with the number of deaths
and permanent maimings from that invention he invents C and Unix.
In PL/PgSQL parser, assignment operator is defined as
assign_operator : '='
| COLON_EQUALS
;
This is a legacy feature, present in source code since 1998, when it was introduced - as we can see in the PostgreSQL Git repo.
Starting from version 9.4 it is oficially documented.
This idiosyncrasy - of having two operators for same thing - was raised on pgsql users list, and some people requested it to be removed, but it's still kept in the core because fair corpus of legacy code relies on it.
See this message from Tom Lane (core Pg developer).
So, to answer your questions straight:
Didn't I find some section in the docs which mention and/or explains
this?
You did not find it because it was undocumented, which is fixed as of version 9.4.
Are there any known consequences using = instead of :=.
There are no side consequences of using =, but you should use := for assignment to make your code more readable, and (as a side effect) more compatible with PL/SQL.
Update: there may be a side consequence in rare scenarios (see Erwin's answer)
UPDATE: answer updated thanks to input from Daniel, Sandy & others.
Q1
This has finally been added to the official documentation with Postgres 9.4:
An assignment of a value to a PL/pgSQL variable is written as:
variable { := | = } expression;
[...] Equal (=) can be used instead of PL/SQL-compliant :=.
Q2
Are there any known consequences using = instead of :=?
Yes, I had a case with severe consequences: Function call with named parameters - which is related but not exactly the same thing.
Strictly speaking, the distinction in this case is made in SQL code. But that's an academic differentiation to the unsuspecting programmer.1
Consider the function:
CREATE FUNCTION f_oracle(is_true boolean = TRUE) -- correct use of "="
RETURNS text
LANGUAGE sql AS
$func$
SELECT CASE $1
WHEN TRUE THEN 'That''s true.'
WHEN FALSE THEN 'That''s false.'
ELSE 'How should I know?'
END
$func$;
Note the correct use of = in the function definition. That's part of the CREATE FUNCTION syntax - in the style of an SQL assignment.2
Function call with named notation:
SELECT * FROM f_oracle(is_true := TRUE);
Postgres identifies := as parameter assignment and all is well. However:
SELECT * FROM f_oracle(is_true = TRUE);
Since = is the SQL equality operator, Postgres interprets is_true = TRUE as SQL expression in the context of the calling statement and tries to evaluate it before passing the result as unnamed positional parameter. It looks for an identifier is_true in the outer scope. If that can't be found:
ERROR: column "is_true" does not exist
That's the lucky case and, luckily, also the common one.
When is_true can be found in the outer scope (and data types are compatible), is_true = TRUE is a valid expression with a boolean result that is accepted by the function. No error occurs. Clearly, this is the intention of the programmer using the SQL equality operator = ...
This db<>fiddle demonstrates the effect.
Old sqlfiddle
Very hard to debug if you're unaware of the distinction between = and :=.
Always use the the correct operator.
1 When using named notation in function calls, only := is the correct assignment operator. This applies to functions of all languages, not just PL/pgSQL, up to and including pg 9.4. See below.
2
One can use = (or DEFAULT) to define default values for function parameters. That's not related to the problem at hand in any way. It's just remarkably close to the incorrect use case.
Postgres 9.0 - 9.4: Transition from := to =>
The SQL standard for assignment to named function parameters is => (and Oracle's PL/SQL uses it. Postgres could not do the same, since the operator had previously been unreserved, so it's using PL/pgSQL's assignment operator := instead. With the release of Postgres 9.0 the use of => for other purposes has been deprecated. The release notes:
Deprecate use of => as an operator name (Robert Haas)
Future versions of PostgreSQL will probably reject this operator name
entirely, in order to support the SQL-standard notation for named
function parameters. For the moment, it is still allowed, but a
warning is emitted when such an operator is defined.
If you should be using => for something else, cease and desist. It will break in the future.
Postgres 9.5: use => now
Starting with this release, the SQL standard operator => is used. := is still supported for backward compatibility. But use the standard operator in new code that doesn't need to run on very old versions.
Documented in the manual, chapter Using Named Notation.
Here's the commit with explanation in GIT.
This applies to named parameter assignment in function calls (SQL scope), not to the assignment operator := in plpgsql code, which remains unchanged.
A partial answer to my own question:
The PL/pgSQL section Obtaining the Result Status shows two examples using a special syntax:
GET DIAGNOSTICS variable = item [ , ... ];
GET DIAGNOSTICS integer_var = ROW_COUNT;
I tried both := and = and they work both.
But GET DIAGNOSTICS is special syntax, so one can argue, that this is also not a normal PL/pgSQL assignment operation.
Reading the Postgresql 9 documentation:
This page lists "=" as an assignment operator in the table on operator precedence.
But strangely this page (assignment operator documentation) doesn't mention it.