Skip to content

Randomize high-impedance ('Z) signals with --x-assign (or --z-assign) #6285

@dr-mora

Description

@dr-mora

While Verilator doesn't support handling of 'X values directly, it allows setting them to unique random values rather than zeroing them, via the --x-assign and --x-initial flags. I have found this feature useful for detecting some errors in my code. However, these flags don't seem to handle 'Z (high-impedance) values, which are always treated as 0.

Is there a way to randomize 'Z values as well?

The following code demonstrates some errors/defects I've encountered:

`timescale 1ns/1ps

module uut (
    input  logic  [2:0] sel,
    output logic [15:0] out
);

logic [5:0][15:0] mux;

generate
    for (genvar i = 0; i < 5; i++) begin //FIXME(1): should be <= 5
        assign mux[i] = {4{4'(i+1)}};
    end
endgenerate

assign out = mux[sel]; //FIXME(2): not handling cases 6 and 7

endmodule



module tb;

logic  [2:0] sel;
logic [15:0] out;

initial begin
    for (int i=0; i<8; i++) begin
        sel = 3'(i);
        #1;
        $display("sel = %h | out = %h", sel, out);
    end
    $finish;
end

uut uut_inst (.*);

endmodule

In FIXME(2), the developer hasn't considered sel being 6 or 7, in which case it tries to read from a non-existent element of an array, resulting in out=xxxx. In those cases, the desired behavior in my use case was to output 0, so I was very happy to see that "it worked" in simulation without showing any discrepancies, until I realized that it was actually generating 'X, which might result in synthesis tools generating other values.
Then I was pleased to learn about Verilator's --x-assign unique --x-initial unique flags, which randomize the value of 'X variables. Randomizing is not a perfect solution, but it is good enough to detect this type of mistake.

However, in FIXME(1), the error results in that not all elements of the array are assigned, so element [5] is left as 'Z. Here, Verilator leaves it as all zeros even if you use the --x-assign flag. Since Verilator doesn't seem to handle 'Z values at all, it would be nice if --x-assign also randomized 'Z values and not just 'X values, or if separate --z-assign/--z-initial flags were provided.

As a note of interest, I found that the plusarg +verilator+rand+reset+2 will sometimes work like this, and randomize the content of 'Z values as well, but not always (I haven't figured out the conditions for it to work/fail yet).


verilator --version = Verilator 5.039 devel rev v5.038-164-g60cbbf0ec (freshly cloned and compiled today)

Note that this version already includes the fix provided in PR #5214, which makes the runtime plusarg +verilator+rand+reset+2 unnecessary.
However, the behavior with and without this runtime option seems to differ, since (as I pointed out) with this option sometimes 'Z is randomized as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions