• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Community
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
    • Interfacing-tools
    • Hardware-verification
      • Gl
      • Esim
      • Vl2014
      • Sv
      • Fgl
      • Vwsim
      • Vl
        • Syntax
        • Loader
        • Warnings
        • Getting-started
        • Utilities
        • Printer
        • Kit
        • Mlib
        • Transforms
          • Unparameterization
          • Elaborate
          • Addnames
          • Annotate
            • Increment-elim
            • Make-implicit-wires
              • Shadowcheck
              • Implicit-wires-minutia
              • Implicit-wires-generate-scoping
                • Vl-modulelist-make-implicit-wires
                • Vl-interfacelist-make-implicit-wires
                • Vl-genelementlist-flatten
                • Vl-interface-make-implicit-wires
                • Vl-module-make-implicit-wires
                • Vl-design-make-implicit-wires-aux
                • Vl-design-make-implicit-wires
              • Vl-genbase-make-implicit-wires
              • Vl-expr-names-for-implicit
              • Vl-make-implicit-wires-main
              • Vl-implicitst
              • Vl-make-port-implicit-wires
              • Vl-import-update-implicit
              • Vl-blockitemlist-update-implicit
              • Vl-blockitem-update-implicit
              • Vl-make-ordinary-implicit-wires
              • Vl-remove-declared-wires
              • Vl-implicitsts-restore-fast-alists
              • Vl-genblock-under-cond-make-implicit-wires
              • Vl-collect-exprs-for-implicit-wires-from-namedargs
              • Vl-genblock-make-implicit-wires
              • Vl-collect-exprs-for-implicit-wires-from-portargs
              • Vl-collect-exprs-for-implicit-wires-from-namedarg
              • Vl-gateinst-exprs-for-implicit-wires
              • Vl-modinst-exprs-for-implicit-wires
              • Vl-genelementlist-make-implicit-wires
              • Vl-packagemap-find-name
            • Basic-bind-elim
            • Argresolve
            • Basicsanity
            • Portdecl-sign
            • Enum-names
            • Port-resolve
            • Udp-elim
            • Vl-annotate-design
            • Vl-annotate-module
          • Clean-warnings
          • Eliminitial
          • Custom-transform-hooks
          • Problem-modules
      • X86isa
      • Svl
      • Rtl
    • Software-verification
    • Math
    • Testing-utilities
  • Make-implicit-wires

Implicit-wires-generate-scoping

Some details about generate block scoping quirks which affect implicit wire handling and other aspects of scoping.

AFAICT none of the following is discussed in the SystemVerilog-2012 standard.

Unlike any other kind of generate statement, it seems that plain old begin ... end style generate blocks with no names are treated by commercial simulators in a special way. In particular, they don't (at least at the top level; see below) introduce new scopes.

This has implications for correctly introducing implicit wires and also for scoping in general. We want to be smart enough to prohibit things like:

module m;
  not(v, w);       // implicit declaration of w
  begin
    wire w = 1;    // illegal (redefinition of w)
  end
endmodule

while at the same time allowing legal things like:

module m;
  not(v, w);       // implicit declaration of w
  begin : myblock
    wire w = 1;    // fine (this is a new scope)
  end
endmodule
Top-level begin/end: no name = no scope

On both NCV and VCS, at least at the top level of a module, an unnamed block does NOT appear to introduce a new scope. Instead, wires declared inside it become visible to the rest of the module after the generate, just as if they were declared before the begin/end block.

Moreover, the following seem to be roughly(*) equivalent,

module m ;                    module m ;
  begin
    ...              vs.           ...
  end
endmodule                     endmodule

(*) Exceptions we're aware of: begin/end blocks aren't allowed to have ports, specify blocks, and specparams (Section 27.3) and parameter declarations inside of begin/end blocks are supposed to be treated as localparams. Testing suggests that these restrictions still hold for unnamed top-level begin/end blocks. See especially vl-genelementlist-flatten.

Interior begin/end: no name = unclear scope

We find that NCV and VCS disagree about the handling of scopes for nested begin/end generate blocks. In particular, consider something like:

module m ;
begin
  wire [3:0] w1 = 0;
  begin
    wire [3:0] w2 = 1;
  end
  wire [3:0] w3 = w1;
  wire [3:0] w4 = w2;
end
endmodule

This code is happily accepted by NCVerilog, suggesting that the inner begin/end block is not given its own scope. However, VCS instead produces an error saying that w2 is not declared, which suggests that VCS treats interior begin/end blocks as new scopes. Note however that VCS still treats top-level begin/end blocks as not being new scopes. Messy.

In VL we choose to follow the behavior of NCVerilog since it is seems more consistent. That is, we will universally regard any unnamed begin/end generate blocks as not introducing a scope.

Eliminating begin/end blocks

Since we are going to treat unnamed begin/end blocks as not having their own scopes, there's really no reason to keep them around.

It also seems like a good idea to get rid of them. If we keep unnamed begin/end blocks around, then when building scopes for vl-scopestacks, we would need to would need to collect all the items from (say) the module, and then also dive down into the begin/end blocks and (recursively) collect up the items within them. It seems much nicer and simpler to inline the contents of these generate blocks into their surroundings. Similarly we would need to do this sort of thing for packages.

We do this inlining as part of introducing implicit wires. This seems like a reasonable place: it certainly needs to happen before or during implicit wire introduction in order to get implicit wires right. It also needs to happen before we create scopestacks for shadowchecking.

Subtopics

Vl-modulelist-make-implicit-wires
(vl-modulelist-make-implicit-wires x ss) maps vl-module-make-implicit-wires across a list.
Vl-interfacelist-make-implicit-wires
(vl-interfacelist-make-implicit-wires x ss) maps vl-interface-make-implicit-wires across a list.
Vl-genelementlist-flatten
Special flattening of unnamed begin/end blocks.
Vl-interface-make-implicit-wires
Vl-module-make-implicit-wires
Vl-design-make-implicit-wires-aux
Vl-design-make-implicit-wires