• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
    • Interfacing-tools
    • Hardware-verification
      • Gl
      • Esim
      • Vl2014
        • Warnings
        • Primitives
        • Use-set
        • Syntax
        • Getting-started
        • Utilities
        • Loader
        • Transforms
          • Expression-sizing
          • Occform
          • Oprewrite
          • Expand-functions
          • Delayredux
          • Unparameterization
          • Caseelim
          • Split
          • Selresolve
          • Weirdint-elim
          • Vl-delta
          • Replicate-insts
          • Rangeresolve
          • Propagate
          • Clean-selects
          • Clean-params
          • Blankargs
          • Inline-mods
          • Expr-simp
          • Trunc
          • Always-top
            • Edgesynth
            • Stmtrewrite
            • Cblock
            • Vl-always-convert-regports
            • Vl-always-convert-regs
            • Stmttemps
              • Vl-modulelist-stmttemps
              • Vl-ifstmt-stmttemps
              • Vl-assignstmt-stmttemps
              • Vl-stmt-stmttemps
              • Vl-alwayslist-stmttemps
              • Vl-always-stmttemps
              • Vl-module-stmttemps
              • Vl-design-stmttemps
            • Edgesplit
            • Vl-always-check-reg
            • Vl-convert-regs
            • Latchsynth
            • Vl-always-check-regs
            • Vl-match-always-at-some-edges
            • Unelse
            • Vl-always-convert-reg
            • Vl-design-always-backend
            • Vl-stmt-guts
            • Vl-always-convert-regport
            • Vl-always-scary-regs
            • Eliminitial
            • Ifmerge
            • Vl-edge-control-p
            • Elimalways
          • Gatesplit
          • Gate-elim
          • Expression-optimization
          • Elim-supplies
          • Wildelim
          • Drop-blankports
          • Clean-warnings
          • Addinstnames
          • Custom-transform-hooks
          • Annotate
          • Latchcode
          • Elim-unused-vars
          • Problem-modules
        • Lint
        • Mlib
        • Server
        • Kit
        • Printer
        • Esim-vl
        • Well-formedness
      • Sv
      • Fgl
      • Vwsim
      • Vl
      • X86isa
      • Svl
      • Rtl
    • Software-verification
    • Math
    • Testing-utilities
  • Always-top

Stmttemps

Replace if conditions and right-hand sides into temporary wires.

This is a preprocessing step in synthesizing always blocks. We expect it to be run only after expressions are sized.

We rewrite statements throughout each flop-like always block, adding temporary wires for:

  1. non-trivial conditions of if expressions
  2. non-sliceable right-hand sides of assignment statements

We don't apply this transform to latch-like blocks, because it would interfere with our sensitivity-list checking. That is, if our sensitivity list is something like @(en1 or en2 or d) and we rewrite if (en1 & en2) ... to if (temp_123) ..., we would think the resulting sensitivity list was incorrect.

Regarding (1), this is mainly an optimization. The idea is that we want to simplify the condition expressions, since we might end up duplicating them across many flops. That is, if we have a block like:

always @@(posedge clk)
  if (foo1 + foo2 + foo3 + foo4 == 1) begin
     a <= b;
     c <= d;
  end

Then this might lead to flops like:

myflop flop1 (a, (foo1 + foo2 + foo3 + foo4 == 1) ? b : a, clk);
myflop flop2 (c, (foo1 + foo2 + foo3 + foo4 == 1) ? d : c, clk);

And we'll be redundantly synthesizing this complex expression. This wouldn't necessarily be any kind of problem, but it seems like we can do better by pulling the combinational logic out of the conditions, e.g.:

wire temp = |( foo1 + foo2 + foo3 + foo4 == 1);

always @(posedge clk)
  if (temp) begin
    a <= b;
    c <= d;
  end

When we synthesize this simpler block, we'll avoid introducing the repeated subexpression. That is, our output will be something like:

wire temp = |( foo1 + foo2 + foo3 + foo4 == 1);
myflop flop1 (a, temp ? b : a, clk);
myflop flop2 (c, temp ? d : c, clk);

Regarding (2), the idea here is that to support blocks that write to different bits of wires, we may need to split up the right-hand sides. For instance, if we are trying to synthesize something like:

always @@(posedge clk)
  if (cond)
     {a[1:0], a[3:2]} <= b1 + b2;
  else
     a[3:0] <= b1 + b2 + 1;

Then we're basically going to end up dealing with this at the bit level, and we're going to have to talk about bit 0 of these compound expressions like b1 + b2. So we will want to be able to split up the right-hand sides we see. We also split up any wires where the widths of the lhs/rhs don't agree, so that later transforms just need to deal with compatible assignments.

Subtopics

Vl-modulelist-stmttemps
(vl-modulelist-stmttemps x) maps vl-module-stmttemps across a list.
Vl-ifstmt-stmttemps
Introduce temp wires for if-statement conditions.
Vl-assignstmt-stmttemps
Introduce temp wires for right-hand sides.
Vl-stmt-stmttemps
Apply the stmttemps transform to a statement
Vl-alwayslist-stmttemps
Vl-always-stmttemps
Vl-module-stmttemps
Vl-design-stmttemps
Top-level stmttemps transform.