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:
- Variables can only be used inside processes
- Any variable that is created in one process cannot be used in another process
- Variables need to be defined after the keyword process but before the keyword begin
- Variables are assigned using the := assignment symbol
- Variables that are assigned immediately take the value of the assignment
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.
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;
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