I tried simulating a for loop in ModelSim, but it is not working properly. I know it cannot synthesized, but I don't know why it is not simulating properly.
When simulated, it is not showing any error. But final result is "00000001" (ie incremented only once) instead of the expected output of "00000011".
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_unsigned.ALL;
entity forloop is
port( enable : in std_logic;
data_out : out std_logic_vector(7 downto 0));
end forloop;
architecture behaviour of forloop is
signal temp : std_logic_vector(7 downto 0) := "00000000";
begin
process(enable)
begin
for i in 0 to 3 loop
temp <= temp +1;
end loop;
end process;
data_out <= temp;
end behaviour;
IEEE Std 1076-2008, 10.10 Loop statement:
This has the effect of replicating the temp assignment as dieli indicates in his answer.
Actually has two defects. You've noticed the first one.
First Defect
The first thing to note is that you are performing successive sequential signal assignments to the same signal with assignments located in the same process. Each process has only one set of drivers and process execution occurs until suspended in the same simulation cycle. Suspended by the implied wait statement as a last statement waiting on the sensitivity list.
These assignments occur as successive iterations of a loop and because there's only one projected waveform for any driver for any particular simulation time only the last signal assignment will actually occur. Essentially you're scheduling a signal update for each signal assignment and their projected value is being overwritten by the next until only the last signal assignment is left.
No signal assignment updates a value while any process is still executing or pending in the current simulation cycle.
A signal assignment with a waveform with an element without a delay will cause a delta cycle, and all pending signal assignments for the next queued simulation time will update after the current simulation cycle has completed and before the delta simulation cycle execution begins. Also see this answer - The VHDL Simulation Cycle for a big picture view of what happens during a simulation cycle.
The in depth description is easier to read in previous revisions of the IEEE standard, See IEEE Std 1076-2002/-2000/-1993, 12.6 Execution of a model. The -2008 standard description in 14.7 has had it's readability encumbered by additions to the standard for VHPI and force assignments.
There are several ways to overcome the effects of successive writes to a signal in the same process and occurring during the execution of the same simulation cycle.
Before that let's address the second defect.
Second Defect
Your sensitivity list contains one element,
enable
which triggers execution of the loop statement. This will occur for any transaction onenable
, including to all four binary values represented by std_ulogic as well as it's meta-values. That includes a transition from a '1' to '0', a '0' to '1' or a combination with 'H' and 'L' which are treated identically in synthesis.If you want a latch based counter you could qualify that with a particular value:
This would cause the loop statement to only execute when
enable
transitioned to a '1'.We typically don't use latch based counters, because as you might note this is edge triggered with only 'enable' in the sensitivity list and if you were to expand the sensitivity list for signals not used in the loop but elsewhere in the process your
temp
accumulator would be incremented by other events.Note that you can't get a new value for
temp
while executing the process so it only increments once for each enable transaction as is, even with the loop statement. You effectively assign the new value oftemp + 1
during the 3rd iteration of thei
loop. and when execution of the process is done (as well as any other processes currently active)temp
gets updated.So how can we get
temp
incremented four times?We could simply add 4 to it. That doesn't give us a general solution.
We could declare a process variable, assign it the value of
temp
when the process executes, and assign that totemp
after executing the loop statement:This may not synthesis eligible depending on synthesis tool, because as dieli notes synthesis wants to treat the variable assignments as parallel operations, while we'd be counting on it to be the equivalent of:
This requires a smarter synthesis tool capable of sequencing the additions.
Insuring Synthesis eligibility
We could over come this issue by using an array of ltemp values, something like this:
Notice
temp
has been added to the sensitivity list because latches are transparent while their enable is TRUE.The condition
enable = '1'
isn't of the form of \ given in the now withdrawn IEEE Std 1076.6-2004 for RTL synthesis as an edge sensitive event (all of which require a second term in the condition). Synthesis tools essentially ignore the sensitivity list, meaning we depend on rule c) of 1076.6 6.2.1.1 Level-sensitive storage from process with sensitivity list:and the following:
Which tells us
temp
should have been in the sensitivity list all along to make the process synthesis eligible. Incidentally also making the first two forms of the process shown in this answer synthesis ineligible.This also reveals a third defect when intending to synthesize the process, that it has a feedback loop through
temp
. You'd actually notice the effect of addingtemp
to the sensitivity list and causing feedback during simulation of the process shown above. You'd either run into a delta cycle limit if present in your simulation tool, or the simulator would hang or could depend on some other implementation dependent mechanism to detect an invalid simulation.And the way to get rid of that feedback loop is used an edge sensitive clock.
And that also brings up the idea of using separate processes (which can be inferred by say separate concurrent conditional signal assigments to
ltemp
elements promoted to signals when we can't perform all the additions in one clock cycle.The simulation output is correct. The for loop in VHDL expands to parallel assignments and not what you get in C (sequential assignments). This means that
will become
Note that temp is a signal and will be updated in the next cycle, hence the +1 is assigned to the same temp value for all 4 lines of code. Besides that, you don't use the enable signal in the sensitivity list. And are you sure you want to use an asynchronous process?