Variables - VHDL Example

Variables in VHDL act similarly to variables in C. Their value is valid at the exact location in the code where the variable is modified. Therefore, if a signal uses the value of the variable before the assignment, it will have the old variable value. If a signal uses the value of the variable after the assignment it will have the new variable value.

Rules of Variables:

The most important thing to understand is that variables immediately take the value of their assignment. Here's an example that shows one useful way to use variables: storing data for temporary use. It uses a case statement and the ampersand (&) concatenation operator.

  VAR_CASE : process (i_clk)
    variable v_Choices : std_logic_vector(1 downto 0);
  begin

    v_Choices := i_select_1 & i_select_2; -- concatenation
    
    case v_Choices is
      when "00" =>
        o_data <= "0001";
      when "01" =>
        o_data <= "0010";
    -- ETC

In the previous example, we concatenated the two signals so that they could be used in the case statement. The variable v_Choices was immediately available for use as soon as it was assigned. Let's look at another example. The example below is more comprehensive and demonstrates how variables immediately take the value of their assignment. The signals r_Var_Copy1 and r_Var_Copy2 appear to be the same, but r_Var_Copy2 is never able to get to 5 before it is reset.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity variable_ex is
  port (
    i_clk   : in std_logic;
    o_done  : out std_logic
    );
end variable_ex;

architecture rtl of variable_ex is

  signal r_Done      : std_logic := '0';
  signal r_Var_Copy1 : natural range 0 to 5 := 0;
  signal r_Var_Copy2 : natural range 0 to 5 := 0;
  
begin

  EX_VAR : process (i_clk)
    variable v_Count : natural range 0 to 5 := 0;
  begin
    if rising_edge(i_clk) then
      v_Count := v_Count + 1;

      r_Var_Copy1 <= v_Count;

      if v_Count = 5 then
        r_Done  <= '1';
        v_Count := 0;
      else
        r_Done <= '0';
      end if;

      r_Var_Copy2 <= v_Count;

    end if;
  end process EX_VAR;
  
  o_done <= r_Done;
  
end rtl;

In order to simulate our design, we need to create a testbench. Also, variables can be a bit tricky to display in simulation. If you are using Modelsim, read more about how to see your variables in Modelsim's waveform window.

Testbench:

library ieee;
use ieee.std_logic_1164.all;

entity variable_ex_tb is
end variable_ex_tb;

architecture behave of variable_ex_tb is

  component variable_ex
    port (
      i_clk  : in std_logic;
      o_done : out std_logic
      );
  end component variable_ex;

  constant c_CLK_PERIOD : time := 10 ns;

  signal r_CLK  : std_logic := '0';
  signal w_DONE : std_logic;
  
begin

  UUT : variable_ex
    port map (
      i_clk  => r_CLK,
      o_done => w_DONE
      );

  r_CLK <= not r_CLK after c_CLK_PERIOD/2;

end behave;


Variables Example Testbench Waveform

The example above demonstrates how variables act differently from signals. The signals r_Var_Copy1 and r_Var_Copy2 appear to be the same, but r_Var_Copy2 is never able to get to 5 before it is reset.

Read more about how variables and signals are different


Help Me Make Great Content!     Support me on Patreon!     Buy a Go Board!