Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
21615 Discussions

Modling a State Machine in VHDL ... with trouble memorizing variables

Altera_Forum
Honored Contributor II
1,868 Views

Hi, 

 

I'm trying to make a state-machine wich remains in one of the states until one of the variables goes from zero to one three times. I assume it should be quite simple, but after some days I can't succeed. I have tried to save the number of changes both in variables and signals, but no result. 

 

To make a simple test, I just made one simple state-machine with two states. It remains on the first one till the signal_to_monitor =1. Then it goes to second state and the idea is to get out of that state after three transitions 0-1 of the signal we are monitoring.  

 

The code used is: 

 

 

architecture ctrl_machine of machine is 

 

type possible_states is (first_st,second_st); 

signal next_state,state: possibles_states; 

signal accumulate : integer range 0 to 5; 

 

 

begin 

 

RefreshState : process (clk,reset) 

begin 

if (reset='1') then 

estat <= idle; 

elsif (clk'event and clk='1') then 

estat <= seguent_estat; 

end if; 

end process RefreshState; 

 

 

NextState : process (state,signal_to_monitor) 

 

begin 

next_state <= state; 

case state is 

 

when first_st =>  

 

if (signal_to_monitor ='1') then  

next_state <= second_st; 

else  

accumulate <=0; 

next_state <= first_st; 

end if; 

 

when second_st =>  

next_state <= buidant_calaix; 

if (signal_to_monitor = '1') then  

accumulate <=accumulate +1; 

end if; 

if (accumulate = 3) then 

next_state<=first_state; 

end if; 

end case; 

end process; 

 

 

 

 

output_proc : process (state) 

begin 

 

case (state) is 

when first_st => output <='0'; 

when second_st => output <='1'; 

 

end case; 

end process ; 

 

 

(...) 

 

I assume it should be a conceptual error but can't find it! The signal (accumulate) gets mad and begins to flip-flop without control (suppose due to accumulate=accumulate+1 but don't know how to accomplish this simple goal!). 

 

Any ideas? 

 

Thanks!!! 

 

Carlos
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
825 Views

Your code is unreadable, because you're mixing original spanish and translated signal and state names. Please post either your original or another consistent code.

0 Kudos
Altera_Forum
Honored Contributor II
825 Views

Sorry! I tried to translate the code for a better understanding. I resend it with the necessary corrections (and in fact the full code I'm working with). I attach also the simulation result (why does the accumulate signal - and so the output - go from 0 to 1 without control????): 

 

 

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.std_logic_arith.all; 

use ieee.std_logic_unsigned.all; 

 

 

entity Counter is 

-- counts three ticks of the signal signal_to_monitor -or thats what I wish 

-- the output signal is integer just to show the evolution in the waveform simulator  

port( 

clk: in std_logic; 

reset,signal_to_monitor: in std_logic; 

output: out integer  

); 

 

end Counter; 

 

 

architecture Behavioral of Counter is 

 

constant NUM_TICKS : integer := 3; 

 

type possible_states is (first_st,second_st); 

signal next_state,state: possible_states; 

signal accumulate: integer range 0 to 2; 

 

 

begin 

 

RefreshState : process (clk,reset) 

begin 

if (reset='1') then 

state <= first_st; 

elsif (clk'event and clk='1') then 

state <= next_state; 

end if; 

end process RefreshState; 

 

 

process (state,signal_to_monitor) 

 

begin 

 

next_state <= state; 

case state is 

 

when first_st =>  

-- no ticks yet 

if (signal_to_monitor ='1') then  

-- count one tick and go to the 'counting' state 

accumulate<=accumulate+1; 

next_state <= second_st; 

else  

accumulate <=0; 

next_state <= first_st; 

end if; 

 

when second_st =>  

-- if the signal goes to one again, count one more till you arrive to NUM_TICKS  

-- then fall back to first_state 

 

if (signal_to_monitor = '1') then  

accumulate <=accumulate +1; 

end if; 

if (accumulate = NUM_TICKS) then 

--  

next_state<=first_st; 

end if; 

end case; 

 

-- just to have a look at the waveform I generate the output here 

output <= accumulate; 

end process; 

 

 

 

process (state) 

begin 

 

--do nothing as the output has been generated just for debugging purposes 

 

end process ; 

 

 

 

end Behavioral;
0 Kudos
Altera_Forum
Honored Contributor II
825 Views

You can't place a counter in the combinational process. The output gets simply unpredictable this way. The accumulator must be assigned under control of an edge sensitive condition, similar to the state variable. 

accumulate<=accumulate+1; 

Also I don't see how the state machine can work with just two states. 

 

I have difficulties to guess the exact intended behaviour. I suggest to sketch a waveform and use a different state for each step. 

 

Care must be taken, if signal_to_monitor is unrelated to the system clock domain, e.g. an external signal. In this case, it's necessary to synchronize it by a clocked register and make the register output control the state machine.
0 Kudos
Altera_Forum
Honored Contributor II
825 Views

Thanks. I did not know I could not use it inside the combinational process. But - as far as I have seen - I can not do it either making a control like: 

 

if (signal_to_monitor'event and signal_to_monitor='1') then accumulate<=accumulate+1 ;end if; 

 

(I include a sample code at the end) 

 

The intended behaviour I tried was just to 'stay in one state till the signal makes a number of changes (three in the example)'. It has no other application. So, I wanted to stay in the first state till the signal goes from 0 to 1. Then stay in second_st till 3 changes have been made in the signal (from 0 to 1). Once that happens (accumulate=3), return to first state and reset accumulate.  

 

 

How can I do this? (the only solution is creating additional states like one_change, two_changes and three_changes? ) (if so, what if I needed 50 changes??? :( ) 

 

Thanks! 

 

 

-- 

 

process (state,signal_to_monitor) 

 

begin 

 

next_state <= state; 

 

if (signal_to_monitor'event and signal_to_monitor='1') then accumulate<=accumulate+1 ;end if; 

 

case state is 

 

when first_st =>  

-- no ticks yet 

if ( signal_to_monitor ='1') then  

-- count one tick and go to the 'counting' state 

next_state <= second_st; 

else  

accumulate <=0; 

next_state <= first_st; 

end if; 

 

when second_st =>  

-- if the signal goes to one again, count one more till you arrive to NUM_TICKS  

-- then fall back to first_state 

 

if (accumulate = NUM_TICKS) then 

--  

next_state<=first_st; 

end if; 

end case;
0 Kudos
Altera_Forum
Honored Contributor II
825 Views

Apart from the "how to count" problem, you'll need at least two "counting" states that reflects a high respectively low input state. Then the transition to the counting_high state can also advance the counter. The counter would be incremented under rising_edge(clk). 

 

Personally I prefer a more compact form of a state machine, that has only one, edge sensitive process. You can easily add things like the said counting action to it.
0 Kudos
Altera_Forum
Honored Contributor II
825 Views

OK! Thanks. I'll try to do it this way.

0 Kudos
Reply