Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2 issues with unsized x/z constants #1423

Closed
veripoolbot opened this issue Apr 30, 2019 · 3 comments
Closed

2 issues with unsized x/z constants #1423

veripoolbot opened this issue Apr 30, 2019 · 3 comments
Assignees
Labels
resolution: fixed Closed; fixed type: feature-IEEE Request to add new feature, described in IEEE 1800

Comments

@veripoolbot
Copy link
Contributor


Author Name: Udi Finkelstein
Original Redmine Issue: 1423 from https://www.veripool.org

Original Assignee: Wilson Snyder (@wsnyder)


Verilator is complaining about this code snippet, even if SV mode:

module t1;
wire [63:0]x;
assign x = 'dx;
endmodule

$ verilator --lint-only t1.sv
%Error: t1.sv:3: Unsized X/Z/? not legal in decimal constant: x
%Error: Exiting due to 1 error(s)
%Error: Command Failed /home/udif/bin/verilator_bin --lint-only t1.sv

This fails both as t.sv and t.v

But according to the quotes below, it is legal, even if not pretty.

In addition, the following code snippet:

module t2 ( output [287:0] o2);
assign o2 = 'hx;
endmodule

Fails with:

$ verilator --lint-only -sv t2.sv
%Warning-WIDTH: t2.sv:2: Operator ASSIGNW expects 288 bits on the Assign RHS, but Assign RHS's CONST '?32?bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' generates 32 bits.
%Warning-WIDTH: Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.
%Error: Exiting due to 1 warning(s)
%Error: Command Failed /home/udif/bin/verilator_bin --lint-only -sv t2.sv

In Verilog-1995, this indeed should be limited to 32 bits, but in SV, unsized constants should be expanded to any width.
(From the little tests I've ran, Cadence simulators extends 'hx to 32 bits in 1995 mode, but then left pads with 0's to according to LHS width. In non 1995 mode, they sign extend to full LHS width).

References:

According to 5.7.1 in IEEE1800-2017:

If the size of the unsigned number is smaller than the size specified for the literal constant, the unsigned
number shall be padded to the left with zeros. If the leftmost bit in the unsigned number is an x or a z, then
an x or a z shall be used to pad to the left, respectively. If the size of the unsigned number is larger than the
size specified for the literal constant, the unsigned number shall be truncated from the left.

The number of bits that make up an unsized number (which is a simple decimal number or a number with a
base specifier but no size specification) shall be at least 32. Unsized unsigned literal constants where the
high-order bit is unknown (X or x) or three-state (Z or z) shall be extended to the size of the expression
containing the literal constant.

NOTE—In IEEE Std 1364-1995, in unsized literal constants where the high-order bit is unknown or three-state, the x or
z was only extended to 32 bits.

So , according to this, in SV 'hx is expanded to any width, and in Verilog-95, it is extended to 32 bits only.

As for the usage of X/Z with 'd, here is part of the BNF from A.8.7 (same IEEE1800-2017 doc):
(I dropped binary and octal BNF)

To summarize the BNF below, decimal numbers may be made of multiple decimal digits (no X/Z),
but as a special case single digit x/z decimal constants are also allowed (both sized and unsized!)
(with optional trailing underscores)

integral_number ::=
decimal_number
| octal_number
| binary_number
| hex_number

decimal_number ::=
unsigned_number
| [ size ] decimal_base unsigned_number
| [ size ] decimal_base x_digit { _ }
| [ size ] decimal_base z_digit { _ }
unsigned_number ::= decimal_digit { _ | decimal_digit }
size ::= non_zero_unsigned_number
non_zero_unsigned_number ::= non_zero_decimal_digit { _ | decimal_digit}
decimal_base ::= '[s|S]d | '[s|S]D

hex_number ::= [ size ] hex_base hex_value
hex_base ::= '[s|S]h | '[s|S]H
hex_value ::= hex_digit { _ | hex_digit }
hex_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | A | B | C | D | E | F
x_digit ::= x | X
z_digit ::= z | Z | ?

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-05-02T00:03:44Z


"'dx" was accidentally unsupported, fixed this in git towards 4.014.

The extension to match the spec I'll look at. I suspect there will still be a warning message, but the behavior if the warning is suppressed will change to match the spec.

As you note the best style is really to use "'x" instead.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-05-08T01:59:02Z


X/Z extension fixed with warning in git towards 4.014.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2019-05-09T01:37:19Z


In 4.014.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution: fixed Closed; fixed type: feature-IEEE Request to add new feature, described in IEEE 1800
Projects
None yet
Development

No branches or pull requests

2 participants