10

I sometimes find it useful to use blocking assignments for "local variables" inside clocked always blocks. This can help cut down on repeated code.

To avoid accidentally using the same variable in a different always block (which can be non-deterministic for simulation), I'd like to give it local scope. Is there a nice synthesizable way of doing this?

Something like:

module sum3(
  input            clk,
  input      [7:0] in1,
  input      [7:0] in2,
  input      [7:0] in3,
  output reg [7:0] result,
  output reg [7:0] result_p1);

  begin :sum
    reg [7:0] sum_temp; // local variable
    always @(posedge clk) begin
      sum_temp   = in1 + in2 + in3;
      result    <= sum_temp;
      result_p1 <= sum_temp + 1;
    end
  end

endmodule

(ModelSim seems to be okay with this, but Synplify doesn't seem to like it.)

toolic
  • 57,801
  • 17
  • 75
  • 117
mksuth
  • 1,999
  • 4
  • 17
  • 24
  • To clarify for others: please note that a begin/end block needs to be ***named*** to create a scope. – Moberg Jun 23 '20 at 22:19

3 Answers3

11

I'm not sure of the semantics in plain Verilog, but according to the SystemVerilog LRM section 6.21:

Variable declarations shall precede any statements within a procedural block.

Therefore the following is legal syntax in SystemVerilog:

module sum3(
  input            clk,
  input      [7:0] in1,
  input      [7:0] in2,
  input      [7:0] in3,
  output reg [7:0] result,
  output reg [7:0] result_p1);

  always @(posedge clk) begin : sum
    reg [7:0] sum_temp; // local variable (scope limited to process)
    sum_temp   = in1 + in2 + in3;
    result    <= sum_temp;
    result_p1 <= sum_temp + 1;
  end

endmodule

Note that I have moved the variable declaration sum_temp into the process, thereby limiting the scope and removing the need for the named sum block. This compiles on Modelsim and Riviera (example on EDA Playground).

If your tool doesn't support this syntax, raise a bug!

Chiggs
  • 2,824
  • 21
  • 31
3

Despite the common guideline, using blocking assignments inside clocked always blocks is ok, and sometime as you mentioned useful. See here: https://stackoverflow.com/a/4774450/1383356

Some tools however, may not support local variables defined inside a begin-end block.

Alternatively, you can try putting some or all of the the body of the always block in a task:

task SUM_TASK();
  reg [7:0] sum_temp; // local variable
  sum_temp   = in1 + in2 + in3;
  result    <= sum_temp;
  result_p1 <= sum_temp + 1;
endtask

always @(posedge clk) begin
  SUM_TASK();
end

Verilog tasks can have access to global variables as well as local ones. Also, they can include non-blocking assignments.

Community
  • 1
  • 1
Ari
  • 7,251
  • 11
  • 40
  • 70
3

The standard sythesizable way is to use a continuous assignment with a wire:

module sum3(
  input        clk,
  input  [7:0] in1,
  input  [7:0] in2,
  input  [7:0] in3,
  output reg [7:0] result,
  output reg [7:0] result_p1);

    wire [7:0] sum_temp = in1 + in2 + in3;
    always @(posedge clk) begin
      result    <= sum_temp;
      result_p1 <= sum_temp + 1;
    end
endmodule
toolic
  • 57,801
  • 17
  • 75
  • 117
  • 2
    This works for this simple (and contrived) example, but in more complex cases this can hurt readability (assignments end up far away from where the variables are used). Also, there are cases when you may want to use different intermediate values of the "local variable". – mksuth Sep 16 '14 at 02:36
  • @mksuth I won't hurt readability. `assignments end up far away from where the variables are used`: What do you mean by far away? It is the job of placer and router which you don't need to worry about. If you wanna use `different intermediate values` use another `reg` for it inside the always block. – tod Sep 16 '14 at 09:01
  • 2
    @tod, I am only referring to the human readability of the code. If the `always` block occupied hundreds of lines of code, then using a `wire` for an "intermediate variable", could result in the assignment being far away (in the code) from where the `wire` is actually used inside the `always` block. In my opinion, the code is more readable when the assignment of the variable and the use of the variable are grouped together in the code. – mksuth Sep 16 '14 at 13:57
  • 1
    **grouped together**: provided it is doable. Btw, **hundreds of lines of code** in one `always` block is the problem. Why don't you break it into multiple always blocks wherever suitable? Also you may use loops... – tod Sep 17 '14 at 08:57
  • @tod: Also, I believe this pollutes the module namespace, which will be a problem if you want simple names for the temp variable like "i" (think of a array subscript). – Imperishable Night Nov 19 '17 at 06:11