Signal assignment in state machine losing values

J

jdl1291$pam

Hi, I have a quick newbie question concerning signal assignments inside
a state machine. The code snippet below is a smaller, idealized version
of what I'm working on, but hopefully demonstrates my question. When
the state machine sits in the "idle" state, ModelSIM reports the value
of AC as "0011", ie, the last assignment from state "three". However,
when I load a similar version into an FPGA, (running AC through a
7-Segment decoder), the value of AC seems undefined. (I've seen values
of "0000" and "1111"). I have verified that the LED-decoder does in
fact work correctly, so I feel that my understanding of signal
assignments is missing something obvious. An asynchronous reset is also
coded in the design, and the FPGA shows similar undefined values for AC
after resetting.


[snip]

process (present_state) begin
case present_state is
when reset =>
AC <= "0001";
next_state <= two;
when two =>
AC <= "0010";
next_state <= three;
when three =>
AC <= "0011";
next_state <= idle;
when idle =>
next_state <= idle;
end case;
end process;


Of course the above code is trivial, but it leads to my question: once
the signal is assigned in one of the states, will it hold that value
until the signal is later modified? (Regardless of the time in
between?) Could something else be causing AC to flake out?

Thanks,

-- Joe Lawrence
 
M

MM

Joe,

It is hard to see what happens from the code you posted. My feeling is that
your state machine goes into an illegal state and this in its turn causes AC
to go into undefined state as well. You defined AC only for the three legal
states, try adding 'when others' into your case statement to define it for
all possible cases.
Of course the above code is trivial, but it leads to my question: once
the signal is assigned in one of the states, will it hold that value
until the signal is later modified? (Regardless of the time in
between?)

You seem to have coded a combinatorial logic for AC, which doesn't have its
own 'memory'. If you described a flip-flop it would have been able to hold
AC value. In your case AC fully depends on the present_state. As soon as the
present_state changes, AC will change as well after a small combinatorial
delay...


/Mikhail
 
M

Mike Treseler

jdl1291$pam said:
However,
when I load a similar version into an FPGA, (running AC through a
7-Segment decoder), the value of AC seems undefined. (I've seen values
of "0000" and "1111").

Of course the above code is trivial, but it leads to my question: once
the signal is assigned in one of the states, will it hold that value
until the signal is later modified?

Yes, values are always held until the next assignment.
When coding for synthesis, consider using the synchronous template:


entity state_example is
port (
rst : in std_ulogic;
clock : in std_ulogic;
AC : out std_logic_vector
);
end entity state_example;

architecture synth of state_example is
begin -- architecture synth
process(rst, clock) is
type state_t is (reset, two, three, idle);
variable state : state_t;
begin
if (rst = '1') then
AC <= (AC'range => '0');
state := reset;
elsif rising_edge(clock) then
case state is
when reset =>
AC <= "0001";
state := two;
when two =>
AC <= "0010";
state := three;
when three =>
AC <= "0011";
state := idle;
when idle =>
state := idle; -- not really needed
end case;
end if;
end process;
end architecture synth; -- Mike Treseler
 
C

Charles M. Elias

jdl1291$pam said:
Hi, I have a quick newbie question concerning signal assignments inside
a state machine. The code snippet below is a smaller, idealized version
of what I'm working on, but hopefully demonstrates my question. When
the state machine sits in the "idle" state, ModelSIM reports the value
of AC as "0011", ie, the last assignment from state "three". However,
when I load a similar version into an FPGA, (running AC through a
7-Segment decoder), the value of AC seems undefined. (I've seen values
of "0000" and "1111"). I have verified that the LED-decoder does in
fact work correctly, so I feel that my understanding of signal
assignments is missing something obvious. An asynchronous reset is also
coded in the design, and the FPGA shows similar undefined values for AC
after resetting.


[snip]

process (present_state) begin
case present_state is
when reset =>
AC <= "0001";
next_state <= two;
when two =>
AC <= "0010";
next_state <= three;
when three =>
AC <= "0011";
next_state <= idle;
when idle =>
next_state <= idle;
end case;
end process;


Of course the above code is trivial, but it leads to my question: once
the signal is assigned in one of the states, will it hold that value
until the signal is later modified? (Regardless of the time in
between?) Could something else be causing AC to flake out?

Thanks,

-- Joe Lawrence

Joe,

It is not clear from your code snippet whether you are using a
2-process or 1-process state machine. If it is a 1-process machine
then AC should be synthesized as a register of 4 flops and will
"remember" its last state in the hardware. However, if you don't
assign it a value in every state, AC could, at least temporarily, take
on a random value. If it is a 2-process machine then the synthesis
program might infer latches for AC since you don't assign it a value
in all states. It is good pratice to assign values for state machine
outputs in every state. I do not do this for "illegal" states since
my "when others" statement will return the state machine to a legal
state where all state outputs are assigned values. I am curious about
your idle state. There is no exit logic from this state--maybe
because your post included just a snippet.

Best regards,

Charles
 
J

jdl1291$pam

Thanks for the responses guys (Mikhail, Mike and Charles). Sorry for
snipping down the code so small, but you guys hit the nail on the head.
After looking at the synthesis report, my two-process state machine
was indeed creating a latch instead of a flip-flop/register out of AC.
Switching over to the one-process methodology Mike suggested
successfully created a register and the design worked as intended. The
larger design that this problem arose from was a simple four instruction
CPU. In some states, the accumulator AC is left unchanged. The code
snippet I included in the first post was simply to test the behavior of
AC during that "idle" state (when AC was not assigned a value). I was
confused as ModelSIM left AC as is while the hardware version did not.
What is proper coding practice for such occurrences? In those states
that leave AC untouched, should I include something like: AC<=AC; (Or
are the rules different for latches vs. registers.) Sometimes I look at
VHDL from a software language perspective rather than from a
"what-hardware-will-it-synthesize-to" point of view and that gets me in
trouble. :)

Thanks,

-- Joe Lawrence
 
W

Weng Tianxiang

jdl1291$pam said:
Hi, I have a quick newbie question concerning signal assignments inside
a state machine. The code snippet below is a smaller, idealized version
of what I'm working on, but hopefully demonstrates my question. When
the state machine sits in the "idle" state, ModelSIM reports the value
of AC as "0011", ie, the last assignment from state "three". However,
when I load a similar version into an FPGA, (running AC through a
7-Segment decoder), the value of AC seems undefined. (I've seen values
of "0000" and "1111"). I have verified that the LED-decoder does in
fact work correctly, so I feel that my understanding of signal
assignments is missing something obvious. An asynchronous reset is also
coded in the design, and the FPGA shows similar undefined values for AC
after resetting.


[snip]

process (present_state) begin
case present_state is
when reset =>
AC <= "0001";
next_state <= two;
when two =>
AC <= "0010";
next_state <= three;
when three =>
AC <= "0011";
next_state <= idle;
when idle =>
next_state <= idle;
end case;
end process;


Of course the above code is trivial, but it leads to my question: once
the signal is assigned in one of the states, will it hold that value
until the signal is later modified? (Regardless of the time in
between?) Could something else be causing AC to flake out?

Thanks,

-- Joe Lawrence

Joe,

It is not clear from your code snippet whether you are using a
2-process or 1-process state machine. If it is a 1-process machine
then AC should be synthesized as a register of 4 flops and will
"remember" its last state in the hardware. However, if you don't
assign it a value in every state, AC could, at least temporarily, take
on a random value. If it is a 2-process machine then the synthesis
program might infer latches for AC since you don't assign it a value
in all states. It is good pratice to assign values for state machine
outputs in every state. I do not do this for "illegal" states since
my "when others" statement will return the state machine to a legal
state where all state outputs are assigned values. I am curious about
your idle state. There is no exit logic from this state--maybe
because your post included just a snippet.

Best regards,

Charles

Your program is good if you do the following change:

process(clock, nRESET) <--- Add this process to make all states of
the state machine registers
begin
if(nRESET) then
present_state <= reset; <--- initial state for the machine
elsif(clock'event and clock = '1') then
present_state <= next_state; <-- they are registers
end if;
end process;

process (present_state) begin
AC <= "0000"; <--- default value if no AC assignment is made or it
is missed
case present_state is
when reset =>
AC <= "0001";
next_state <= two;
when two =>
AC <= "0010";
next_state <= three;
when three =>
AC <= "0011";
next_state <= idle;
when idle => <--- at this state, the above default value
will be used
next_state <= idle;
end case;
end process;

After that you can use AC at any place you want and AC will have a
meaning you assign to it.
For example at "two", AC would have value of "0010", no any ambiguity!

This method to write state machine may be classified as two process
method. It is better than one process method. Why? Save clocks and
save logic resources.

Weng
 
M

Mike Treseler

jdl1291$pam said:
What is proper coding practice for such occurrences? In those states
that leave AC untouched, should I include something like: AC<=AC;

That would have no effect on performance in any case.

(Or
are the rules different for latches vs. registers.)

Yes, the rule is don't infer any analog structures
like latches or one-shots in a synchronous sim.

Sometimes I look at
VHDL from a software language perspective rather than from a
"what-hardware-will-it-synthesize-to" point of view and that gets me in
trouble. :)

As long as you stick to the synchronous template,
the software language perspective will always
be applicable.

-- Mike Treseler
 
M

MM

What is proper coding practice for such occurrences? In those states
that leave AC untouched, should I include something like: AC<=AC;

No, but you need to have a default value. Weng showed how to do it for your
original style.
(Or are the rules different for latches vs. registers.)

They are. When you describe a register you don't need to say what to do
between the clocks:

You normally write it like this:

process(clk)
begin
if rising_edge(clk) then
q <= d;
end if
end process

and not like this:

process(clk)
begin
if rising_edge(clk) then
q <= d;
else
q <= q;
end if
end process

However, it wouldn't hurt if you did.

On the other hand when you are trying to describe combinatorial logic
failure to define a default state can lead to inferring a latch, i.e. you
get different result:

This will be a latch:

process(ena)
begin
if ena then -- ena is boolean
q<='1';
end if;
end process;

and this won't be a latch:

process(ena)
begin
q<='0';
if ena then
q<='1';
end if;
end process;

or

process(ena)
begin
if ena then
q<='1';
else
q<='0';
end if;
end process;

Synthesizers usually give you warnings when they generate latches...

/Mikhail
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top