Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Verilog variables be given local scope to an always block?

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.)

like image 677
mksuth Avatar asked Sep 15 '14 22:09

mksuth


2 Answers

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.

like image 143
Ari Avatar answered Oct 12 '22 11:10

Ari


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!

like image 22
Chiggs Avatar answered Oct 12 '22 09:10

Chiggs