Strange problem with very simple state machine

R

Roger Dahl

Dear group,

I'm teaching myself VHDL and to that end, I got a prototype board with
a Xilinx Spartan 2 and WebPack 6.3.02 plus service packs.

I was working on a small design when I started having some strange
problems with a state machine. To locate the problem, I separated out
the state machine and simplified it as much as I could while still
retaining the problem. So I now have a complete design with an
extremely simple state machine that exhibits the problem, but I still
can't see that I made any mistakes. I've included that design in VHDL
below.

The state machine has two states. The first state sets a signal to 0,
and the second state inverts the signal. From everything I've read
about state machines and processes, the signal should turn to 1 when
the state machine goes to the second state and stay at 1 until the
state machine goes back to the first state. Instead, what happens is
that while the state machine is in the second state, the signal keeps
inverting as quickly as the chip can manage.

When I view the RTL schematic for the design, it is apparent why this
happens. While the state machine is in the second state, the signal is
simply run in a loop through a NOT gate.

I would much appreciate it if someone that knows more about VHDL than
I could take a look at the code below and see if I have missed
something fundamental about VHDL or state machines, or if this is a
bug in the Xilinx tools.

Thank you for any help!

Roger Dahl

--

library ieee;
use ieee.std_logic_1164.all;

entity sigtest is
port (
mclk : in std_logic;
d: out std_logic
);
end sigtest;

architecture behavioral of sigtest is

type state is (
write_a,
write_b
);

signal d_ctl : std_logic := '0';

signal cur_st : state := write_a;
signal next_st : state := write_b;

begin

d <= d_ctl;

process (mclk)
begin
if rising_edge(mclk) then
cur_st <= next_st;
end if;
end process;

process (cur_st)
begin
case cur_st is
when write_a =>
d_ctl <= '0';
next_st <= write_b;

when write_b =>
d_ctl <= not d_ctl;
next_st <= write_a;
end case;
end process;

end behavioral;
 
M

mike_treseler

Roger said:
Instead, what happens is that while the state machine
is in the second state, the signal keeps
inverting as quickly as the chip can manage.

I expect that you are toggling back and forth
from a to b to a etc.

Your code specifies that

a: d_ctl gets '0'; go to b
b: d_ctl gets inverted to '1'; go to a

and I expect that is exactly what is happening.
Next time consider running a simulation to
debug your code.

-- Mike Treseler
 
R

Roger Dahl

mike_treseler said:
I expect that you are toggling back and forth
from a to b to a etc.

Your code specifies that

a: d_ctl gets '0'; go to b
b: d_ctl gets inverted to '1'; go to a

and I expect that is exactly what is happening.
Next time consider running a simulation to
debug your code.

Thank you for your reply, Mike.

Actually, the frequency that is output when the state machine is in
the second state is much higher than the clock frequency. It displays
only as a voltage of around 0.1V on my 20MHz oscilloscope. When the
state machine is in the first state, I get GND on the output.

The result I see is also consistent with the RTL schematic, but to me,
the RTL schematic is not consistent with my code.

Finally, the VHDL code seems to work when I simulate it in ModelSim.

Thanks again,

Roger
 
N

Neo

The state machine has two states. The first state sets a signal to 0,
and the second state inverts the signal. From everything I've read
about state machines and processes, the signal should turn to 1 when
the state machine goes to the second state and stay at 1 until the
state machine goes back to the first state. Instead, what happens is
that while the state machine is in the second state, the signal keeps
inverting as quickly as the chip can manage.
Thank you for any help!

Roger Dahl

--

library ieee;
use ieee.std_logic_1164.all;

entity sigtest is
port (
mclk : in std_logic;
d: out std_logic
);
end sigtest;

architecture behavioral of sigtest is

type state is (
write_a,
write_b
);

signal d_ctl : std_logic := '0';

signal cur_st : state := write_a;
signal next_st : state := write_b;

begin

d <= d_ctl;

process (mclk)
begin
if rising_edge(mclk) then
cur_st <= next_st;
end if;
end process;

process (cur_st)
begin
case cur_st is
when write_a =>
d_ctl <= '0';
next_st <= write_b;

when write_b =>
d_ctl <= not d_ctl;
next_st <= write_a;
end case;
end process;

end behavioral;
The behaviour you observe is correct as per hardware but wont show in
simulation because the process sensitivity list is for simulator
only(it would have shown if you had as required included the d_ctl in
the sensitivity list) , the hardware is not dictated by it, so for all
practical purposes the hardware comb logic triggers everytime the
d_ctl changes which is nothing but a not gate fed to itself. So to
accurately model your requirement you have to specifically state that
d_ctl <= '1' in the write_b state. but you present assignment is
modelling a clock.
 
M

Mohammed khader

Hi Roger,

What Mike said was correct . The output is switching with half the
frequency of 'mclk'.

some other comments on your code....
1) Dont Initialize the signals when you write code for synthesis
2) All FSMs should have a reset signal.(otherwise system starts from
a unknow state). Hence your First process should be like this...

process (mclk,reset)
begin
if (reset='0')then
cur_st <= write_a; -- If write_a is the initial state
elsif rising_edge(mclk) then
cur_st <= next_st;
end if;
end process;
 
R

Roger Dahl

The behaviour you observe is correct as per hardware but wont show in
simulation because the process sensitivity list is for simulator
only(it would have shown if you had as required included the d_ctl in
the sensitivity list) , the hardware is not dictated by it, so for all
practical purposes the hardware comb logic triggers everytime the
d_ctl changes which is nothing but a not gate fed to itself. So to
accurately model your requirement you have to specifically state that
d_ctl <= '1' in the write_b state. but you present assignment is
modelling a clock.

Neo,

That explains it. I appreciate that you took the time to enlighten me. Thanks!

Roger
 
R

Roger Dahl

Hi Roger,

What Mike said was correct . The output is switching with half the
frequency of 'mclk'.

some other comments on your code....
1) Dont Initialize the signals when you write code for synthesis
2) All FSMs should have a reset signal.(otherwise system starts from
a unknow state). Hence your First process should be like this...

process (mclk,reset)
begin
if (reset='0')then
cur_st <= write_a; -- If write_a is the initial state
elsif rising_edge(mclk) then
cur_st <= next_st;
end if;
end process;

Hi Mohammed,

Thank you for your reply.

Actually, the output is switching as fast as the hardware can manage
while the state machine is in the second state. See Neo's post for the
explanation as to why this happens.

Thanks for the coding tips. Those things were in my original design
but I had shaved them off to make the example as brief as possible for
the group.

Roger
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top