Variables are not Signals

Variables in VHDL are sometimes misused.  The results can be dangerous.  In general, variables should not be used in VHDL, except for some very specific cases.

One misuse of variables is to declare signals inside the process where they are used.  The intent is to declare them in a local scope.  VHDL-2002 doesn’t support directly declaring signals within a process — only variables.  The issue is that variables only have a blocking assign. Below is an example of using a variable as a register.

-- Improper use of VHDL variables:
p_bad : process (Clk) is
  variable state : std_logic;
begin
  if (Clk'event and Clk='1') then
    if (state = '1') then
      --actions
    end if;

    -- update state "register"
    state := not state;
  end if;
end process;

The above seems like perfectly valid, functional VHDL code.  In fact it is.  The issue isn’t that variables can’t be used as registers.  The issue is that they shouldn’t be used as registers.

In the above example, the variable is updated at the end of the process.  This is the first issue — the code is highly location dependent.  In many other cases, a process can be written so almost any block can be re-ordered.  This allows logic to appear near other related logic.  With variables, this isn’t always the case.

p_fail : process (Clk) is
  variable x,y : integer range 0 to 9;
begin
  if (Clk'event and Clk = '1') then
    -- code that uses x and y

    -- update x
    if (y = 9 and x = 3) then
      x := 0;
    elsif (x = 9) then
      x := 0;
    else
      x := x + 1;
    end if;

    -- update y
    if (y = 9 and x = 3) then
      y := 0;
    elsif (x = 9) then
      y := y + 1;
    end if;

  end if;
end process;

The above code would suggest a decimal counter that counts from 0 to 93.  But it actually doesn’t do that.  When 93 occurs, “x” is updated to 0.  This prevents “y” from updating to 0.  The sequence would be 0 1 2 … 88 89 90 91 92 93 90 91 92 93 90 …

p_fail : process (Clk) is
  variable x,y : integer range 0 to 9;
begin
  if (Clk'event and Clk = '1') then
    -- code that uses x and y

    -- update y
    if (y = 9 and x = 3) then
      y := 0;
    elsif (x = 9) then
      y := y + 1;
    end if;

    -- update x
    if (y = 9 and x = 3) then
      x := 0;
    elsif (x = 9) then
      x := 0;
    else
      x := x + 1;
    end if;

  end if;
end process;

Changing the order doesn’t fix this one either.  Now the count is 0 1 2 … 91 92 93 4 5 6 …

A programming mindset would pick up on the interdependency between “x” and “y”, and would realize a temporary variable could be used.  But this doesn’t help readability either.

Using variables as registers is a bad idea because it doesn’t make the code more readable.  Blocks of code can no longer be placed near related blocks — any variable-based registers must be assigned at the end of the process.  The code is also more difficult to write — the above example shows that.  Modifications to the code also require more attention to signals vs. variables.

    -- update y
    if (y = 9 and x = 3) then
      y := 0;
    elsif (x = 9) then
      y := y + 1;
    end if;
This entry was posted in VHDL. Bookmark the permalink.

Comments are closed.