VHDL has two types of what-would-normally-be-called-variables:
signal
s, which must be used for inter-process communication, and can be used for process-local storagevariable
s which are local to a process.
(there’s also variables of a protected type
which we’ll ignore for now as they’re another thing altogether)
Now one of the big differences between signal
s and variable
s is the way they are updated. When a signal
is used within a process
and is assigned to to change its value, the value does not update until the end of the process. For example (assume foo
is “ to start with):
process
begin
wait until rising_edge(clk);
foo <= 1; -- an update is scheduled
sig <= foo + 1; -- but hasn't happened yet, so sig is assigned 1 (again, only scheduled)
end process; -- at this point, foo is updated with the value 1 and sig also gets 1
Compare with the situation where foo
is a variable:
process
variable foo : integer;
begin
wait until rising_edge(clk);
foo := 1; -- foo gets 1 immediately
sig <= foo + 1; -- so sig has an update to 2 scheduled
end process; -- at this point, foo is already 1 and sig gets its scheduled update to 2
This can cause some interesting effects on coding style – take for example this question on StackOverflow.
A code example is provided there which shows what has to happen due to the update semantics of signal
s – deeply nested if
s.
Here’s an alternative. Let’s define a procedure first of all to increment a variable and wrap around if it is greater than some maximum value. Also return a flag to inform us if the variable wrapped:
procedure inc_wrap (i : inout integer; maximum : positive; wrapped : inout boolean) is
begin
if i = maximum then
wrapped := true;
i := 0;
else
wrapped := false;
i := i + 1;
end if;
end procedure;
Then our update process looks like this:
if second_enable = '1' then
inc_wrap(s_ls_int, 9, wrapped);
if wrapped then
inc_wrap(s_ms_int, 5, wrapped);
end if;
if wrapped then
inc_wrap(m_ls_int, 9, wrapped);
end if;
if wrapped then
inc_wrap(m_ms_int, 5, wrapped);
end if;
if wrapped then
if h_ms_int < 2 then -- wrap at 9 for 0-19 hour
inc_wrap(h_ls_int, 9, wrapped);
else -- wrap at 3 if past 20 hours
inc_wrap(h_ls_int, 3, wrapped);
end if;
end if;
if wrapped then
inc_wrap(h_ms_int, 2, wrapped);
end if;
end if;
All the code from this posting is at Github