I recently fixed a problem with one of my state machines, and I think
that the cause could be a bug in Xilinx XST. Below is the code that
produced the failure. The state-machine worked most of the time,
though occasionally the 'phaseRamWE' signal would be stuck low, even
though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr'
incrementing. I fixed it by explicitly declaring the desired value of
'phaseRamWE' in every state. Notice that all states are defined so it
should recover from any conditions introduced by asynchronous inputs.
Have any of you seen similar behavior? Appears to be an XST bug to me.
parameter [3:0]
S1 = 4'b0000,
S2 = 4'b0001,
S3 = 4'b0010,
S4 = 4'b0011,
S5 = 4'b0100,
S6 = 4'b0101,
S7 = 4'b0110,
S8 = 4'b0111,
S9 = 4'b1000,
S10 = 4'b1001,
S11 = 4'b1010,
S12 = 4'b1011,
S13 = 4'b1100,
S14 = 4'b1101,
S15 = 4'b1110,
S16 = 4'b1111;
always @(posedge rst or posedge clk)
begin
if (rst) // 'rst' is asserted
and deasserted synchronously to 'clk'
begin
rfd <= 1'b0;
phaseRamWE <= 1'b0;
phaseRamWriteAdr <= 0;
phaseRamReadAdr <= 0;
phaseAccum <= 0;
state <= S1;
end
else
begin
case (state)
S1:
begin
if (pipeFill == 1'b1) // 'pipeFill' is
asynchronous to 'clk'
begin
phaseRamWE <= 1'b1;
state <= S2;
end
end
S2:
begin
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S3;
end
S3:
begin
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S4;
end
S4:
begin
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S5;
end
S5:
begin
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S6;
end
S6:
begin
rfd <= 1'b1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S7;
end
else
begin
state <= S8;
end
end
S7:
begin
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S7;
end
else
begin
state <= S8;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
end
end
S8:
begin
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S9;
phaseRamWE <= 1'b0;
phaseAccum <= 0;
rfd <= 1'b0;
phaseRamReadAdr <= 0;
phaseRamWriteAdr <= 0;
end
else
begin
state <= S8;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
end
end
S9: state <= S10;
S10: state <= S11;
S11: state <= S12;
S12: state <= S13;
S13: state <= S14;
S14: state <= S15;
S15: state <= S16;
S16: state <= S1;
endcase
end
end
Xilinx XST and a State Machine - A Mystery
Started by ●September 20, 2010
Reply by ●September 20, 20102010-09-20
Darol Klawetter wrote:> I recently fixed a problem with one of my state machines, and I think > that the cause could be a bug in Xilinx XST. Below is the code that > produced the failure. The state-machine worked most of the time, > though occasionally the 'phaseRamWE' signal would be stuck low, even > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > incrementing. I fixed it by explicitly declaring the desired value of > 'phaseRamWE' in every state. Notice that all states are defined so it > should recover from any conditions introduced by asynchronous inputs. > > Have any of you seen similar behavior? Appears to be an XST bug to me.I have seen similar behaviour with Altera Quartus. It was the same problem: asynchronous inputs changed the state machine and sometimes it hangs. I think it is possible that the state machine is internally implemented with some more bits and it is possible that it hangs, if there are some timing violations or meta stability conditions, because then there is an invalid state encoded and everything can happen with optimized gates. The fix was easy: Creating an input latch (or even two, if you are paranoid) for each asynchronous signal to make it synchronous. -- Frank Buss, http://www.frank-buss.de piano and more: http://www.youtube.com/user/frankbuss
Reply by ●September 20, 20102010-09-20
On Sep 20, 10:52=A0am, Darol Klawetter <darol.klawet...@l-3com.com> wrote:> I recently fixed a problem with one of my state machines, and I think > that the cause could be a bug in Xilinx XST. Below is the code that > produced the failure. The state-machine worked most of the time, > though occasionally the 'phaseRamWE' signal would be stuck low, even > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > incrementing. =A0I fixed it by explicitly declaring the desired value of > 'phaseRamWE' in every state. Notice that all states are defined so it > should recover from any conditions introduced by asynchronous inputs. > > Have any of you seen similar behavior? Appears to be an XST bug to me. ><snip> I only skimmed the code, but this bit jumped out at me: if (pipeFill =3D=3D 1'b1) // 'pipeFill' is asynchronous to 'clk' If pipeFill is really asynchronous to the clock that is running your state machine, using it without synchronizing it first is going to cause you problems. Probably not because of metastability, but because of coherency problems. If pipeFill is changing near the clock edge, some FFs will see the new value, and some the old. This can cause weird and flaky behaviour. Regards, John McCaskill www.FasterTechnology.com
Reply by ●September 20, 20102010-09-20
On Sep 20, 11:00=A0am, Frank Buss <f...@frank-buss.de> wrote:> Darol Klawetter wrote: > > I recently fixed a problem with one of my state machines, and I think > > that the cause could be a bug in Xilinx XST. Below is the code that > > produced the failure. The state-machine worked most of the time, > > though occasionally the 'phaseRamWE' signal would be stuck low, even > > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > > incrementing. =A0I fixed it by explicitly declaring the desired value o=f> > 'phaseRamWE' in every state. Notice that all states are defined so it > > should recover from any conditions introduced by asynchronous inputs. > > > Have any of you seen similar behavior? Appears to be an XST bug to me. > > I have seen similar behaviour with Altera Quartus. It was the same proble=m:> asynchronous inputs changed the state machine and sometimes it hangs. I > think it is possible that the state machine is internally implemented wit=h> some more bits and it is possible that it hangs, if there are some timing > violations or meta stability conditions, because then there is an invalid > state encoded and everything can happen with optimized gates. The fix was > easy: Creating an input latch (or even two, if you are paranoid) for each > asynchronous signal to make it synchronous. > > -- > Frank Buss,http://www.frank-buss.de > piano and more:http://www.youtube.com/user/frankbussI thought the same thing, especially because XST often uses one-hot encoding internally, and that introduces more state bits. Even though I exhaustively defined all states, this may not be the case in the post-synthesis result.
Reply by ●September 20, 20102010-09-20
On Sep 20, 11:05=A0am, John McCaskill <jhmccask...@gmail.com> wrote:> On Sep 20, 10:52=A0am, Darol Klawetter <darol.klawet...@l-3com.com> > wrote: > > > I recently fixed a problem with one of my state machines, and I think > > that the cause could be a bug in Xilinx XST. Below is the code that > > produced the failure. The state-machine worked most of the time, > > though occasionally the 'phaseRamWE' signal would be stuck low, even > > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > > incrementing. =A0I fixed it by explicitly declaring the desired value o=f> > 'phaseRamWE' in every state. Notice that all states are defined so it > > should recover from any conditions introduced by asynchronous inputs. > > > Have any of you seen similar behavior? Appears to be an XST bug to me. > > <snip> > > I only skimmed the code, but this bit jumped out at me: > > =A0 =A0 =A0 =A0 =A0 =A0 if (pipeFill =3D=3D 1'b1) =A0 =A0 =A0 =A0 =A0 =A0==A0 =A0 =A0 =A0 // 'pipeFill' is> asynchronous to 'clk' > > If pipeFill is really asynchronous to the clock that is running your > state machine, =A0using it without synchronizing it first is going to > cause you problems. =A0Probably not because of metastability, but > because of coherency problems. If pipeFill is changing near the clock > edge, some FFs will see the new value, and some the old. =A0This can > cause weird and flaky behaviour. > > Regards, > > John McCaskillwww.FasterTechnology.comAgreed, but the state machine should recover, right? All states are defined.
Reply by ●September 20, 20102010-09-20
On Mon, 20 Sep 2010 08:52:16 -0700 (PDT), Darol Klawetter <darol.klawetter@l-3com.com> wrote:>I recently fixed a problem with one of my state machines, and I think >that the cause could be a bug in Xilinx XST. Below is the code that >produced the failure. The state-machine worked most of the time, >though occasionally the 'phaseRamWE' signal would be stuck low, even >though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' >incrementing. I fixed it by explicitly declaring the desired value of >'phaseRamWE' in every state. Notice that all states are defined so it >should recover from any conditions introduced by asynchronous inputs. > >Have any of you seen similar behavior? Appears to be an XST bug to me.Try adding a (* safe_implementation = "yes" *) to your state register and see if that gets rid of the problem. -- Muzaffer Kal DSPIA INC. ASIC/FPGA Design Services http://www.dspia.com
Reply by ●September 20, 20102010-09-20
On Sep 20, 11:05=A0am, John McCaskill <jhmccask...@gmail.com> wrote:> On Sep 20, 10:52=A0am, Darol Klawetter <darol.klawet...@l-3com.com> > wrote: > > > I recently fixed a problem with one of my state machines, and I think > > that the cause could be a bug in Xilinx XST. Below is the code that > > produced the failure. The state-machine worked most of the time, > > though occasionally the 'phaseRamWE' signal would be stuck low, even > > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > > incrementing. =A0I fixed it by explicitly declaring the desired value o=f> > 'phaseRamWE' in every state. Notice that all states are defined so it > > should recover from any conditions introduced by asynchronous inputs. > > > Have any of you seen similar behavior? Appears to be an XST bug to me. > > <snip> > > I only skimmed the code, but this bit jumped out at me: > > =A0 =A0 =A0 =A0 =A0 =A0 if (pipeFill =3D=3D 1'b1) =A0 =A0 =A0 =A0 =A0 =A0==A0 =A0 =A0 =A0 // 'pipeFill' is> asynchronous to 'clk' > > If pipeFill is really asynchronous to the clock that is running your > state machine, =A0using it without synchronizing it first is going to > cause you problems. =A0Probably not because of metastability, but > because of coherency problems. If pipeFill is changing near the clock > edge, some FFs will see the new value, and some the old. =A0This can > cause weird and flaky behaviour. > > Regards, > > John McCaskillwww.FasterTechnology.comI think I just found the source of the problem, and it's not a bug in XST. In state S1, if 'state' is updated while 'phaseRamWE' is not, then it would produce the symptoms I saw. Early on, I had considered synchronizing pipeFill to the 'clk" domain, but I thought I would just handle it in the robustness of the state machine - my mistake.
Reply by ●September 20, 20102010-09-20
On Sep 20, 11:12=A0am, Darol Klawetter <darol.klawet...@l-3com.com> wrote:> On Sep 20, 11:05=A0am, John McCaskill <jhmccask...@gmail.com> wrote: > > > > > On Sep 20, 10:52=A0am, Darol Klawetter <darol.klawet...@l-3com.com> > > wrote: > > > > I recently fixed a problem with one of my state machines, and I think > > > that the cause could be a bug in Xilinx XST. Below is the code that > > > produced the failure. The state-machine worked most of the time, > > > though occasionally the 'phaseRamWE' signal would be stuck low, even > > > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > > > incrementing. =A0I fixed it by explicitly declaring the desired value=of> > > 'phaseRamWE' in every state. Notice that all states are defined so it > > > should recover from any conditions introduced by asynchronous inputs. > > > > Have any of you seen similar behavior? Appears to be an XST bug to me=.> > > <snip> > > > I only skimmed the code, but this bit jumped out at me: > > > =A0 =A0 =A0 =A0 =A0 =A0 if (pipeFill =3D=3D 1'b1) =A0 =A0 =A0 =A0 =A0 ==A0 =A0 =A0 =A0 =A0 // 'pipeFill' is> > asynchronous to 'clk' > > > If pipeFill is really asynchronous to the clock that is running your > > state machine, =A0using it without synchronizing it first is going to > > cause you problems. =A0Probably not because of metastability, but > > because of coherency problems. If pipeFill is changing near the clock > > edge, some FFs will see the new value, and some the old. =A0This can > > cause weird and flaky behaviour. > > > Regards, > > > John McCaskillwww.FasterTechnology.com > > Agreed, but the state machine should recover, right? All states are > defined.Hello Darol, While you may have specified all the possible states for the width of state variable that you used, unless you tell XST otherwise, it will choose which ever encoding style that it feels is optimal. That is usually a one hot encoding for a state machine the size of yours. By default, XST will assume that states that you do not explicitly have a transition to are truly unreachable and will not worry about them, and will ignore default or when others cases of your case statement. You can change the default behavior. You can force the tools to use an encoding of your choice, and you can use the safe state machine constraint to cause the tools to be more conservative in their assumptions about unreachable states. Doing that will come at a cost that the tools will choose a different encoding that will probably be slower and bigger. I think that you are much better off to always synchronize an asynchronous signal at the boundary of your design. Regards, John McCaskill www.FasterTechnology.com
Reply by ●September 20, 20102010-09-20
On Sep 20, 11:55=A0am, John McCaskill <jhmccask...@gmail.com> wrote:> On Sep 20, 11:12=A0am, Darol Klawetter <darol.klawet...@l-3com.com> > wrote: > > > > > On Sep 20, 11:05=A0am, John McCaskill <jhmccask...@gmail.com> wrote: > > > > On Sep 20, 10:52=A0am, Darol Klawetter <darol.klawet...@l-3com.com> > > > wrote: > > > > > I recently fixed a problem with one of my state machines, and I thi=nk> > > > that the cause could be a bug in Xilinx XST. Below is the code that > > > > produced the failure. The state-machine worked most of the time, > > > > though occasionally the 'phaseRamWE' signal would be stuck low, eve=n> > > > though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr' > > > > incrementing. =A0I fixed it by explicitly declaring the desired val=ue of> > > > 'phaseRamWE' in every state. Notice that all states are defined so =it> > > > should recover from any conditions introduced by asynchronous input=s.> > > > > Have any of you seen similar behavior? Appears to be an XST bug to =me.> > > > <snip> > > > > I only skimmed the code, but this bit jumped out at me: > > > > =A0 =A0 =A0 =A0 =A0 =A0 if (pipeFill =3D=3D 1'b1) =A0 =A0 =A0 =A0 =A0==A0 =A0 =A0 =A0 =A0 // 'pipeFill' is> > > asynchronous to 'clk' > > > > If pipeFill is really asynchronous to the clock that is running your > > > state machine, =A0using it without synchronizing it first is going to > > > cause you problems. =A0Probably not because of metastability, but > > > because of coherency problems. If pipeFill is changing near the clock > > > edge, some FFs will see the new value, and some the old. =A0This can > > > cause weird and flaky behaviour. > > > > Regards, > > > > John McCaskillwww.FasterTechnology.com > > > Agreed, but the state machine should recover, right? All states are > > defined. > > Hello Darol, > > While you may have specified all the possible states for the width of > state variable that you used, unless you tell XST otherwise, it will > choose which ever encoding style that it feels is optimal. That is > usually a one hot encoding for a state machine the size of yours. =A0By > default, XST will assume that states that you do not explicitly have a > transition to are truly unreachable and will not worry about them, and > will ignore default or when others cases of your case statement. > > You can change the default behavior. You can force the tools to use an > encoding of your choice, and you can use the safe state machine > constraint to cause the tools to be more conservative in their > assumptions about unreachable states. Doing that will come at a cost > that the tools will choose a different encoding that will probably be > slower and bigger. > > I think that you are much better off to always synchronize an > asynchronous signal at the boundary of your design. > > Regards, > > John McCaskillwww.FasterTechnology.comThanks for the response, John. Yes, I realized that the Xilinx tools could use different state encoding than that specified by the user, but it seemed reasonable to assume that functionality would be matched (wrong assumption). Anyway, you may have noticed, from a previous post to this thread, that my problem was caused by my own error and was not tool related. I agree with your last paragraph. It's typically better to use a couple of flops on an asynchronous control signal than trying to handle it within the state machine (especially if the tool is going to take encoding liberties).
Reply by ●September 20, 20102010-09-20
On Sep 20, 2:02=A0pm, Darol Klawetter <darol.klawet...@l-3com.com> wrote:> > I agree with your last paragraph. It's typically better to use a > couple of flops on an asynchronous control signal than trying to > handle it within the state machine (especially if the tool is going to > take encoding liberties).- Hide quoted text - >The rule is that any time there is a logic path from an asynchronous input to more than one device that samples the signal(s), you must first synchronize the signal before feeding it into any logic path. This condition occurs for any state machine with more than one state. KJ






