Search code examples
system-verilogmodelsim

Why doesn't 'd0 extend the full width of the signal (as '0 does)?


Using SystemVerilog and Modelsim SE 2020.1, I was surprised to see a behavior:

bus_address is a 64b signal input logic [63:0] bus_address

Using '0

.bus_address ('0),

enter image description here

Using 'd0

.bus_address ('d0),

enter image description here

Riviera-Pro 2020.04 (too buggy, we gave up using it and we are in a dispute with Aldec)

  • 'd0:

rivierapro

  • '0:

rivierapro_wrong

Investigation/Answer:

  • 11.3.3 Using integer literals in expressions: An unsized, based integer (e.g., 'd12 , 'sd12 )

  • 5.7.1 Integer literal constants:

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.

That was tricky and I thought it would set 0 all the other bits as '0 does.

I hope specs' authors will think more when defining such non-sense behaviors.


Solution

  • This problem has more with port connections with mismatched sizes than anything to do with numeric literals. It's just that the issue does not present itself when using the fill literals. This is because the fill literal automatically sizes itself eliminating port width mismatch.

    The problem you see exists whether you use literals or other signals like in this example:

    module top;
      wire [31:0] a = 0;
      dut d(a);
    endmodule
    module dut(input wire [63:0] p1);
      initial $strobeb(p1);
    endmodule
    

    According to section 23.3.3.7 Port connections with dissimilar net types (net and port collapsing), the nets a and p1 might get merged into a single 64-bit net, but only the lower 32-bits remain driven, or 64'hzzzzzzzz00000000.

    If you change the port connection to a sized literal, dut d(32'b0);, you see the same behavior 64'hzzzzzzzz00000000.

    Now let's get back to the unsized numeric literal 'd0. Unsized is a misnomer—all numbers have a size. It's just that the size is implicit and never the size you want it to be. 😮 How many people write {'b1,'b0,'b1,'b0} thinking they've just wrote the same thing as 4'b1010? This is actually illegal in the LRM, but some tools silently interpret it as {32'b1,32'b0,32'b1,32'b0}.

    Just never use an unsized literal.