Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)

A problem of FSM

Altera_Forum
Honored Contributor II
2,211 Views

The verilog code below is a FSM I designed . I find this FSM can run correctly and jump between different states at first ,  

but after running several seconds it will fall into a fixed state(state=0, state2=0 or state=7,state2=4) and never come out again.  

According to the logic , the FSM can step into state 0 only once after power on reset; moreover ,any time when falling into state 0,it  

should can come out and step into state 1. But the reality is that it never come out again.  

Is there any problem with this FSM code ? How to deal with this problem? 

Thanks! 

 

code: 

reg [2:0] state; 

reg [2:0] state2; 

reg [9:0] count; 

 

always @(posedge CLK) 

begin 

if(RESET)//power on reset 

begin 

state <= 0; 

state2 <= 0; 

count <= 0; 

end 

else 

begin 

case (state) 

0: 

begin 

case (state2) 

0:  

begin  

if (count == 0) 

begin 

//process 

count <= count + 1; 

end 

else if (count < 2) 

begin 

//process 

count <= count + 1; 

end 

else  

begin 

count <= 0; 

state2 <= 1; 

end 

[/INDENT]end 

1:  

begin 

if (count == 0) 

begin 

//process 

count <= count + 1; 

end 

else if (count < 6) 

begin 

//process 

count <= count + 1; 

end 

else  

begin 

count <= 0; 

state2 <= 2; 

end 

[/INDENT]end 

2:  

begin 

if (count == 0) 

begin 

//process 

count <= count + 1; 

end 

else if (count < 6) 

begin 

//process 

count <= count + 1; 

end 

else  

begin 

count <= 0; 

state2 <= 3; 

end 

[/INDENT]end 

3:  

begin  

if (count == 0) 

begin 

//process 

count <= count + 1;  

end 

if (count == 1) 

begin 

//process 

count <= 0; 

state2 <= 0; 

state <= 1; 

end 

[/INDENT]end 

endcase  

[/INDENT][/INDENT]end 

1: 

begin 

//process 

state <= 2; 

end 

2: 

begin 

//process 

state <= 3; 

end 

3: 

begin 

//process 

state <= 4; 

end 

4: 

begin 

//process 

state <= 5; 

end 

5: 

begin 

//process 

state <= 6; 

end 

6: 

begin 

//process 

state <= 1; 

end 

default: 

begin 

state <= 1;  

end 

endcase  

[/INDENT]end 

[/INDENT]end
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
832 Views

According to your code, there is no state 7. That would therefore be impossible. Also there is no state2 == 4. Also impossible. The only way this can be happening is if there is some input to the system not illustrated in the code that affects the state machine. That input may be an upset caused by the fact that you're not meeting timing. Are you meeting timing requirements? 

 

Also, are you sure you are getting a clean reset? 

 

May I suggest the following: 

reg state; reg state2; reg count; always @(posedge CLK or posedge RESET) begin if(RESET) begin //power on reset state <= 0; state2 <= 0; count <= 0; end else begin case (state) 0: case (state2) 0: begin count <= count + 1; if(count == 2) begin state2 <= 1; count <= 0' end end 1: begin count <= count + 1; if(count == 6) begin state2 <= 2; count <= 0' end end 2: begin count <= count + 1; if(count == 6) begin state2 <= 3; count <= 0' end end 3: begin count <= count + 1; if(count) begin state <= 1; state2 <= 0; count <= 0; end end endcase 1: state <= 2; 2: state <= 3; 3: state <= 4; 4: state <= 5; 5: state <= 6; 6: state <= 1; default: state <= 0; endcase end end
0 Kudos
Altera_Forum
Honored Contributor II
832 Views

Thank you very much for your suggestions! 

Following facts may give you more information about this problem: 

1.The compilation report shows the timing is meeted. 

2.The "RESET" sigal is generated from following module: 

 

module SELF_RESET(// power on reset 

input CLK10, 

output reg SELF_RESET 

); 

 

reg [3:0] count; 

always @(posedge CLK10) 

begin 

if(count != 10) 

begin  

count <= count + 1; 

SELF_RESET <= 1'b1; 

end 

else 

SELF_RESET <= 1'b0; 

[/INDENT]end 

[/INDENT]  

endmodule 

 

The CLK10 is 10MHz.The CLK in FSM is a 90MHz clock generated from a PLL in the FPGA with the input of 15MHz . Both the 10MHz and 15MHz are inputs of FPGA and these two clocks are in different clock domain. 

3. Whatever signal cause the FSM jump into a state which is not exist or unwanted , the FSM should can jump out of this state according to the logic. 

For example, when the state is changed to 7, FSM should jump into the default state and then jump into state 1. When the state is changed to 0, it also can come out of state o and jump into state 1. But the fact is once the FSM fall into state 7 or state 0 after running correctly for several seconds, it  

will never come out again. 

 

Is my understanding about this FSM correct?
0 Kudos
Altera_Forum
Honored Contributor II
832 Views

Hi tigre, 

 

1) It is good design practice to always provide an external reset signal to your system. This is definitly required when you are targeting an ASIC design. 

 

2) On an FPGA where the registers are initialized to a known state after configuration, you can of course provide a "Power Up" reset signal as you are doing. 

 

3) Your design is working in two different clock domains, that are unrelated. You have one external clock of 10MHz and a second unrelated clock of 90MHz generated by a PLL from a separte 15MHz signal.  

 

When you are resting your circuit operating at 90MHz by a reset signal that is generated from an unrelated 10MHz clock, there is no direct correlation between the arrival of the RESET signal and the 90MHz CLK clock signal. This means that your RESET signal will be "racing" with the CLK signal to arrive first at the specific registers in your design. Depending on the specific wiring configuration obtained during the Fitting of your design, it can occur that some registers get reset and other do not. So the behavior that you describe is to be expected. 

 

Operating among clock domains is not trivial and you can always suffer from metastability.  

 

You can at least improve the behavior of your FSM by "synchronizing" your RESET signal via a number of registers in a chain. This could for example be done as follows for your design: 

 

reg RESET, RESET1; wire RESET2; always @(posedge CLK) begin RESET = RESET1; RESET1 = RESET2; end SELF_RESET u1 (clock, RESET2);This adds two intermediate signals RESET1 and RESET2. In each flipflop the RESET signal will be "synchronized" better to the 90MHz CLK signal. The problems with metastability will be lower at least. 

 

Hope this helps...
0 Kudos
Altera_Forum
Honored Contributor II
832 Views

I don't see a reason for the reported behaviour in the posted code. Because no asynchronous events are processed in the FSM (which is the most likely cause for FSM erratic behaviour), PLL loss of lock should be considered. 

 

Although a reliable design operation can't be expected with an unstable clock, you can prevent FSM lockup in illegal states by specifying safe FSM in general synthesis options or synthesis attributes. To make safe FSM coding effective, both state machines should have default states. 

 

This is the respective Verilog syntax for specifying safe state machine synthesis 

reg state /* synthesis syn_encoding = "safe" */; reg state2 /* synthesis syn_encoding = "safe" */;
0 Kudos
Altera_Forum
Honored Contributor II
832 Views

@FvM 

 

The code for the FSM (with the addition of the "default:" in all case statements) as suggested by jacobjones should work. 

 

Once started up the FSM from the "SELF_RESET" the FSM should operate without the problems mentioned by tigre. 

 

@tigre 

 

Is the behavior (after several seconds) that you describe occuring with the "SELF_RESET" that you posted before? 

 

1) If YES. Why do you generated the "SELF_RESET" from a 10MHz clock unrelated to the 90MHz CLK? 

 

2) If NO. I suppose that you are generating a RESET at several instances from an external signal in the 10MHz clock domain. If this is the case, your design can be influenced by races. (for a solution see my previous post).
0 Kudos
Altera_Forum
Honored Contributor II
832 Views

 

--- Quote Start ---  

The code for the FSM (with the addition of the "default:" in all case statements) as suggested by jacobjones should work. 

--- Quote End ---  

 

As far as I see, no default state is yet implemented for state2. Generally, without forcing safe state machine synthesis, you shouldn't make assumptions about behaviour in illegal states. Also, as long as you don't specify an explicite FSM processing, one state hot is the default coding style for any state machine recognized by the compiler. This implies additional possible illegal states outside the expected binary state variable number range. Safe state machine or explicite state encoding is the only way to avoid this issue. 

 

Furthermore, I realized that the FSM code in the original post isn't representing a full design, because it hasn't any output. Thus I wonder, if any details of the real design, omitted in the post, may cause the discussed problem. To be sure about, I would like to see a full design that still reproduces the issue. 

 

P.S.: Regarding the RESET discussion, I agree that driving the SELF_RESET logic from a different clock basically causes an asynchronous reset, that may cause a FSM to change to an illegal state at worst case. Thus the reset should be better synchronized to the FSM CLK by usual means. But this issue can't explain a FSM failure after correct initial startup.
0 Kudos
Altera_Forum
Honored Contributor II
832 Views

@sanmao 

1)There is only one SELF_RESET instance in my project. The 10MHz clock is the main clock in the project and  

the 90MHz clock is only used in one module. 

2)I will rewrite the SELF_RESET code as you suggested. 

 

@FvM 

1) I have check the pll "locked" signal after the FSM problem appears, it is in high level . So ,the 90MHz  

clock is stable. 

2)/*synthesis syn_encoding = "safe"*/ added behind "state" definition can work in Quartus2? Does it have the same effect as "default" item in case statement?
0 Kudos
Reply