Statemachine working on Xilinx but not on Altera....

S

Stefan Oedenkoven

Guest
Hi Ng,

i have a statemachine which should do some action on a sensor-signal 'sX'


pSYNC_PROC: process (CLK, Reset)
begin
if (Reset='0') then
sCurrentState <= U001;
elsif (CLK'event and CLK = '1') then
sCurrentState <= sNextState;
end if;
end process;

pCOMB_PROC: process (Reset, sCurrentState, sX, sY)
variable vX_read : STD_LOGIC := '0';
begin
if Reset = '0' then
sNextState <= U001;
else

case sCurrentState is

when U001 =>
if sX = '0' then
sNextState <= U002;
vX_read := '1';
else
sNextState <= U001;
end if;

when U002 =>
if sX = '1' then
vX_read := '0'; -- ok, now Signal sX was again high,
so the next falling edge will be used
sNextState <= U002;
elsif sX = '0' then
if vX_read = '0' then
vX_read := '1'; -- this is only working on XilinxISE
and XV9500 ... with Altera Quartus and 10K-Series i never leave U002!
why???
sNextState <= U003;
else
sNextState <= U002;
end if;
end if;

when U003 =>
....
....


Is this the right way to handle asynchronous signals???

thanks in advance,
Stefan
 
Stefan Oedenkoven wrote:

when U001 =
if sX = '0' then
sNextState <= U002;
vX_read := '1';
Ok, going to state 2, and vX_read will be '1'. Let's assume that sX stays
'0'...

when U002 =
....
elsif sX = '0' then
if vX_read = '0' then
vX_read := '1'; -- this is only working on XilinxISE
and XV9500 ... with Altera Quartus and 10K-Series i never leave U002!
why???
sNextState <= U003;
else
sNextState <= U002;
end if;
end if;
With sX being '0', and vX_read being '1', you will always remain in state 2.
If sX will become '1', then vX_read will become '0', and if sX becomes '0'
again after that, _then_ you'll get out of state 2.

So, the question is: what happens? Unless the sequence above is followed, it
appears to me that Altera is handling this correctly.

Now if sX is asynchronous, then I fear for the functionality of your FSM.
Timing will be impossible to get correct, and the behaviour may be _not_
what you intended. The _least_ you need to do is clock sX in twice before
you use its value.

Regards,

Pieter Hulshoff
 
Hi Pieter,

yep that was the problem - even with sX switching many times high - low -
high etc... it remained in state 2...

after some testing i came to this assumptions:
1) -- stupid example:
when state001 =>
sX <= '1';
sNextState <= state002;
when state002 =>
if sX = '1' then
sNextState <= state002;
else
sNextState <= state001;
end;
a)The signal assignment from state001 with Xilinx ISE and CPLD XV9500 will
still be the same in state002.
b) With Altera Quartus and FPGA 10K the signal must again be assigned in
state002, if i need there sX='1'.


2)
-- vTest is 1
if vTest = 1 then
sNextState <= state002;
vTest := 0;
end if;
a) with quartus and XV9500 i get this sequence:
assign sNextState <= state002; assign variable vTest the value 0 and in the
next clock cycle go to state002 (with the statemachine-version i posted)
b) with Altera and 10K:
sNextState seems to get 'hardwired' like sNextState <= state002 when vTest =
1 .
That means immediatly when vTest is set back to 0, sNextState will not be
state002 any more..


It would be nice, if you could comment this... and tell me, if that's the
behaviour you would expect or is it caused by the different Synthesizers or
different Hardware...

regards,
Stefan


"Pieter Hulshoff" <phulshof@xs4all.nl> schrieb im Newsbeitrag
news:4143300e$0$35778$e4fe514c@dreader8.news.xs4all.nl...
Stefan Oedenkoven wrote:

when U001 =
if sX = '0' then
sNextState <= U002;
vX_read := '1';

Ok, going to state 2, and vX_read will be '1'. Let's assume that sX stays
'0'...

when U002 =
...
elsif sX = '0' then
if vX_read = '0' then
vX_read := '1'; -- this is only working on
XilinxISE
and XV9500 ... with Altera Quartus and 10K-Series i never leave U002!
why???
sNextState <= U003;
else
sNextState <= U002;
end if;
end if;

With sX being '0', and vX_read being '1', you will always remain in state
2.
If sX will become '1', then vX_read will become '0', and if sX becomes '0'
again after that, _then_ you'll get out of state 2.

So, the question is: what happens? Unless the sequence above is followed,
it
appears to me that Altera is handling this correctly.

Now if sX is asynchronous, then I fear for the functionality of your FSM.
Timing will be impossible to get correct, and the behaviour may be _not_
what you intended. The _least_ you need to do is clock sX in twice before
you use its value.

Regards,

Pieter Hulshoff
 
Stefan

Infering your requirement and in ignorance of your clock speed ...

I infer thet you are waiting for an ack signal, which you wish to see
asserted for two clock cycles.

Firstly, some good practice observations:
0) don't create latches, such as vX_read by implying 'memory' in unclocked
processes
1) staticise the (asynchronous) input signal sX through two FF clocked by
CLK
2) don't use variables for non-combinatorial logic inside processes, they
are signals treat them as such
3) don't initialise variables in VHDL intended for synthesis, except by
reseting; it can lead to simulation / synthesis missmatches. Initialisation
is, to the first order, for testbenches.

Secondly, some opinions on good practice:
1) put the whole synchronous state machine, now that vX_read has been
synchronised, in one process
2) consider using registers for your state derived outputs (not that you
show any), less delay and less skew
3) use a variable for next state and assign it to state "at the end" of the
process; you can use the variable to the generate any state derived outputs
4) examine carefully and report, to the Ng if appropriate, what the
synthesiser generated and the simulator said; as with all computers design
intent is simply a miss-representation of the specification, what matters is
what the computer decided to do therefore read the listings / reports not
the source code

To respond to your narrow query "Is this a good way of handling asynchronous
signals ?" No

I suggest that you:
a) use two FF to staticise the asynchronous signal, addressing metastability
issues
b) add a third FF and use FF_2 = '1' and FF_3 ='0' as your detection
condition; i.e. look for the rising edge.
c) use another state to encode the armed condition, if you really require to
look for two ones
d) recast the entire FSM as a single synchronous process (now that it's
inputs are synchronous)
e) consider which encoding (binary, 1-hot, Gray) is appropriate for the FSM

Now, if the asynchronous signal is less than several clocks wide or if the
clock frequency or latency requirements are "challenging" the foregoing may
be inapplicable. If so, you could perhaps use a Gray coded state machine
with a single input, and an agressive validation programme. If you do
please report the outcome in the literature.

I hope this is of assistance

Martin

"Stefan Oedenkoven" <stefan-oedenkoven@gmx.de> wrote in message
news:2qghpbFvgkl2U1@uni-berlin.de...
Hi Ng,

i have a statemachine which should do some action on a sensor-signal 'sX'


pSYNC_PROC: process (CLK, Reset)
begin
if (Reset='0') then
sCurrentState <= U001;
elsif (CLK'event and CLK = '1') then
sCurrentState <= sNextState;
end if;
end process;

pCOMB_PROC: process (Reset, sCurrentState, sX, sY)
variable vX_read : STD_LOGIC := '0';
begin
if Reset = '0' then
sNextState <= U001;
else

case sCurrentState is

when U001 =
if sX = '0' then
sNextState <= U002;
vX_read := '1';
else
sNextState <= U001;
end if;

when U002 =
if sX = '1' then
vX_read := '0'; -- ok, now Signal sX was again high,
so the next falling edge will be used
sNextState <= U002;
elsif sX = '0' then
if vX_read = '0' then
vX_read := '1'; -- this is only working on XilinxISE
and XV9500 ... with Altera Quartus and 10K-Series i never leave U002!
why???
sNextState <= U003;
else
sNextState <= U002;
end if;
end if;

when U003 =
....
....


Is this the right way to handle asynchronous signals???

thanks in advance,
Stefan
 
Hello Stefan,

yep that was the problem - even with sX switching many times high - low -
high etc... it remained in state 2...
Ah, things seem to be clear to me now. You see: from a VHDL point of view,
the code is indeed what you intend. The problem is: you're defining
hardware here, and you've defined a value to be stored (vX_read) within a
combinatorial process. Your intention seems to be to have this value stored
in a FlipFlop, but you have not described such in your code.

The Xilinx toolkit seems to understand the intention behind your code. The
Altera toolkit figured you just wanted to define a combinatorial loop. In
this case the Xilinx toolkit is correct, but under different circumstances
this might not have been the case.

The solution is to define signals vX_read and vX_read_next, and treat them
the same as sCurrentState and sNextState.

Regards,

Pieter Hulshoff
 
Hi Martin & Pieter,

thanks for your comments...

Firstly, some good practice observations:
2) don't use variables for non-combinatorial logic inside processes, they
are signals treat them as such.
so variables are simply synthesized to latches? if not - when do i use
variables or should i avoid them generally?

Secondly, some opinions on good practice:
1) put the whole synchronous state machine, now that vX_read has been
synchronised, in one process
so, then i need only one signal for the state assignment...

2) consider using registers for your state derived outputs (not that you
show any), less delay and less skew
registers? hmmm it's optional for the signal declaration, right? but i
didn't find anything about this in my vhdl book. Will register-signals
always synthesized to flip-flops? where is the difference to a 'normal'
signal?

3) use a variable for next state and assign it to state "at the end" of
the
process; you can use the variable to the generate any state derived output
a) use two FF to staticise the asynchronous signal, addressing
metastability
issues
b) add a third FF and use FF_2 = '1' and FF_3 ='0' as your detection
condition; i.e. look for the rising edge.
why is it not sufficient to use two FFs and wait for FF_1 = '1' and FF_2 =
'0'

c) use another state to encode the armed condition, if you really require
to
look for two ones
erm, what did you mean?
e) consider which encoding (binary, 1-hot, Gray) is appropriate for the
FSM
ok, my literature say's for CPLD is binary and for FPGA is 1-hot is
appropriate.

ok if i programm a CPLD / FPGA and don't be aware of the exact timings i
should alway avoid asynchronous inputs to FSMs - did i catch this right?

I hope this is of assistance
yes, thanks ;)

Martin
 
so variables are simply synthesized to latches? if not - when do i use
variables or should i avoid them generally?
Variables and signals are synthesized into latches or FFs if they need to
carry their value beyond the current time. Whether they become latches or
FFs depend on if they're level sensitive (latches) or edge sensitive (FFs);
in other words: when do they get their value?

In general I avoid using variables in all cases, unless it is to temporarily
calculate a value I'll be needing a lot in the code (readability).
Variables are usually a pain to find back in the netlist, and are often
hard to trace within simulation (depends on the tool).

Secondly, some opinions on good practice:
1) put the whole synchronous state machine, now that vX_read has been
synchronised, in one process
so, then i need only one signal for the state assignment...
If you have one synchronized process? Yes, you'd only need one signal for
the state assignment.

why is it not sufficient to use two FFs and wait for FF_1 = '1' and FF_2
= '0'
You need two FFs for metastability. Any edge detection must be done using
FFs after the 1st, so the 2nd and 3rd would be usable like Martin
described. Only one FF should be connected to the 1st FF, or you can see
some very interesting behaviour of your design.

ok, my literature say's for CPLD is binary and for FPGA is 1-hot is
appropriate.
I see little reason for using 1 hot encoding. If every part of your design
is synchronous, it doesn't really matter what coding is used, unless you
want it to be used for error detection later on.

ok if i programm a CPLD / FPGA and don't be aware of the exact timings i
should alway avoid asynchronous inputs to FSMs - did i catch this right?
I'm from the school that believes asynchronous designs should be outlawed.
They're an incredible pain to get to work, and even if by some divine
intervention you get a working design you can never be sure it will still
work when you port it to a different technology. About the only thing they
have in favour is they tend to use less power. IF you can get it to work
that is...

Regards,

Pieter Hulshoff
 
Stefan

0) I've interleaved responses to your specific points below.

1) A sketch of an FSM with a Request input, a Strobe output and an Ack input
follows [E&OE]

No testbench, no syntax check, no testing and no warranty.

Note that, as the clock is continuous, I've used synchronous resets; you
always should when you can.

State encoding, timeout, illegal state recovery and post synthesis V&V
are left as exercises for the reader.

Hope this is of assistance

Martin


entity FSM
is port (Rst_n : in Std_Logic;
Clk : in Std_Logic;
Request : in Std_Logic; -- usually this would be negative
active
Strobe : out Std_Logic;
Ack : in Std_Logic);
end FSM;

architecture Synthesisable of FSM
is
type tFSM is (FsmIdle, FsmAssert, FsmArmed);

signal srFSM : tFSM;

signal Rst_n_d1,
Rst_n_d2,
Request_d1,
Request_d2,
Request_d3,
Ack_d1,
Ack_d2 : Std_Logic;

begin

pSynchReset:
process
if Reset_n = '0'
then Rst_n_d1 <= '0';
Rst_n_d2 <= '0';
elsif rising_edge (Clk)
then Rst_n_d1 <= Rst_n;
Rst_n_d2 <= Rst_n_d1;
end if;
end process pSynchReset;

pSynchRequest:
process

wait for rising_edge (Clk);

Request_d1 <= Request;
Request_d2 <= Request_d1;
Request_d3 <= Request_d2;

end if;

end process pSynchRequest;

pSynchAck:
process

wait for rising_edge (Clk);

Ack_d1 <= Ack;
Ack_d2 <= Ack_d1;

end if;

end process pSynchAck;

pFSM:
process

var vFSM : tFSM;

begin

wait for rising_edge(Clk);

vFSM := srFSM;

if Rst_n_d2 = '0'
then vFSM := FsmIdle;
else case srFSM is

when FsmIdle
=> if (Request_d1 xor Request_d2) = '1' -- Request line
toggles to initiate FSM
then vFSM := FsmAssert;
end if;

when FsmAssert
=> if (Ack_d2 = '1') and (Ack_d3 = '0') -- wait for
rising edge on Ack
then vFSM := FsmArmed;
end if;

when FsmArmed
=> if Ack_d3 = '1' -- wait for two 'samples' of Ack
(intentionally clumsy)
then vFSM := FsmIdle;
end if;

when others
=> assert ...

end case srFSM;

end if;

srFSM <= vFSM; -- location imaterial, as long as it's after the wait

case vFSM is -- vFSM to update State and Strobe simulatneously

when FsmIdle
=> Strobe <= '0';

when FsmAssert,
FsmArmed
=> Strobe <= '1';

when others
=> assert ...

end case;

end process; -- pFSM

end Synthesisable; -- of FSM


"Stefan Oedenkoven" <stefan-oedenkoven@gmx.de> wrote in message
news:2qisuaFvdeshU1@uni-berlin.de...
Hi Martin & Pieter,

thanks for your comments...

Firstly, some good practice observations:
2) don't use variables for non-combinatorial logic inside processes,
they
are signals treat them as such.
so variables are simply synthesized to latches? if not - when do i use
variables or should i avoid them generally?
Yes, variables which implement sequential logic (requiring memory) inside
proceses will be synthesised as latches or flip flops; usually you don't
want to synthesise latches, and the implicit synthesis of flip flops leaves
details such as reset (perhaps) indeterminate.

A good use for variables, IMHO, is for intermediate combinatorial results;
e.g. next state

Secondly, some opinions on good practice:
1) put the whole synchronous state machine, now that vX_read has been
synchronised, in one process
so, then i need only one signal for the state assignment...
Not certain what you mean. But, the vX_read logic would be subsumed into
the FSM

2) consider using registers for your state derived outputs (not that you
show any), less delay and less skew
registers? hmmm it's optional for the signal declaration, right? but i
didn't find anything about this in my vhdl book. Will register-signals
always synthesized to flip-flops? where is the difference to a 'normal'
signal?
Register = flip flop (in this usage); the rationale for output registers is
that the outputs occur after Tclock-to-output rather than Tdata-to-output.
Or, in Mealy / Moore argot: use a Moore machine [see e.g. Cohen, ISBN
0-7923-8474-1 p299]

3) use a variable for next state and assign it to state "at the end" of
the
process; you can use the variable to the generate any state derived
output
a) use two FF to staticise the asynchronous signal, addressing
metastability
issues
b) add a third FF and use FF_2 = '1' and FF_3 ='0' as your detection
condition; i.e. look for the rising edge.
why is it not sufficient to use two FFs and wait for FF_1 = '1' and FF_2
=
'0'
Metastability will (eventually) bite if you don't use a 'synchroniser',
hence the 'extra' FF; use Google to find references e.g. from the silicon
vendors and FAQs

c) use another state to encode the armed condition, if you really
require
to
look for two ones
erm, what did you mean?
What I mean is are you looking for the 0/1 transition or for 0/1/1, as
sugested by your initial posting

e) consider which encoding (binary, 1-hot, Gray) is appropriate for the
FSM
ok, my literature say's for CPLD is binary and for FPGA is 1-hot is
appropriate.
Hmm, those are the default but not necessarily apropriate encodings. If
your design is more than an example, you should read up on this.

ok if i programm a CPLD / FPGA and don't be aware of the exact timings i
should alway avoid asynchronous inputs to FSMs - did i catch this right?
Absolutely, synchronise everything that enters clocked logic including
reset. Or, you're playing hardball.

I hope this is of assistance
yes, thanks ;)

Martin
 
0) Errata is engrossed in the example for known lint; denoted by DTGs
[e.g. -- 12 2200A Sep 04]

1) A very good collection of papers on Verilog, synthesis and ..., can be
found at www.sunburst-design.com/papers

2) CummingsSNUG2002SJ_Resets_rev1_1.pdf [OpCit] discusses Async and Sync
resets and includes VHDL examples.

3) Cohen [ISBN 0-7923-8474-1 & 0-7923-8115-7] discusses coding styles for
(synchronous) FSMs.

Martin


entity FSM
is port (Rst_n : in Std_Logic;
Clk : in Std_Logic;
Request : in Std_Logic; -- usually this would be negative
active
Strobe : out Std_Logic;
Ack : in Std_Logic);
end FSM;

architecture Synthesisable of FSM
is
type tFSM is (FsmIdle, FsmAssert, FsmArmed);

signal srFSM : tFSM;

signal Rst_n_d1,
Rst_n_d2,
Request_d1,
Request_d2,
Request_d3,
Ack_d1,
Ack_d2 : Std_Logic;

begin

pSynchReset:
process (Reset_n, Clk) -- 12 2200A Sep 04
if Reset_n = '0'
then Rst_n_d1 <= '0';
Rst_n_d2 <= '0';
elsif rising_edge (Clk)
then Rst_n_d1 <= Rst_n;
Rst_n_d2 <= Rst_n_d1;
end if;
end process pSynchReset;

pSynchRequest:
process

wait until rising_edge (Clk); -- 12 2200A Sep 04

Request_d1 <= Request;
Request_d2 <= Request_d1;
Request_d3 <= Request_d2;

end if;

end process pSynchRequest;

pSynchAck:
process

wait until rising_edge (Clk); -- 12 2200A Sep 04

Ack_d1 <= Ack;
Ack_d2 <= Ack_d1;

end if;

end process pSynchAck;

pFSM:
process

var vFSM : tFSM;

begin

wait until rising_edge (Clk); -- 12 2200A Sep 04

vFSM := srFSM;

if Rst_n_d2 = '0'
then vFSM := FsmIdle;
else case srFSM is

when FsmIdle -- Request line toggles to initiate FSM
=> if (Request_d2 xor Request_d3) = '1' -- 12 2200A Sep
04
then vFSM := FsmAssert;
end if;

when FsmAssert
=> if (Ack_d2 = '1') and (Ack_d3 = '0') -- wait for
rising edge on Ack
then vFSM := FsmArmed;
end if;

when FsmArmed
=> if Ack_d3 = '1' -- wait for two 'samples' of Ack
(intentionally clumsy)
then vFSM := FsmIdle;
end if;

when others
=> assert ...

end case srFSM;

end if;

srFSM <= vFSM; -- location imaterial, as long as it's after the wait

case vFSM is -- vFSM to update State and Strobe simulatneously

when FsmIdle
=> Strobe <= '0';

when FsmAssert,
FsmArmed
=> Strobe <= '1';

when others
=> assert ...

end case;

end process; -- pFSM

end Synthesisable; -- of FSM
 
Hi Pieter & Martin...

....wanted just to thank you for your help.
For the moment Altera Quartus is synthesizing as i want it ;)

best regards,
stefan
 
Pieter Hulshoff wrote:

Variables and signals are synthesized into latches or FFs if they need to
carry their value beyond the current time. Whether they become latches or
FFs depend on if they're level sensitive (latches) or edge sensitive (FFs);
in other words: when do they get their value?
Note that a synchronous process cannot generate latches
and an a combinational process cannot generate flops.

In general I avoid using variables in all cases, unless it is to temporarily
calculate a value I'll be needing a lot in the code (readability).
Variables are usually a pain to find back in the netlist, and are often
hard to trace within simulation (depends on the tool).
This is a matter of style.
I use process variables except
for inter-process communication because
of the improved readability of sequential
value creation.

Using process labels makes it much easier
to find and display local signal and variable waveforms.


I see little reason for using 1 hot encoding. If every part of your design
is synchronous, it doesn't really matter what coding is used,
I agree.

I'm from the school that believes asynchronous designs should be outlawed.
No need for a law.
Such a design provides
its own punishment,
then enlightenment.


-- Mike Treseler
 
Martin Bishop wrote:

1) A sketch of an FSM with a Request input, a Strobe output and an Ack input
follows [E&OE]

No testbench, no syntax check, no testing and no warranty.
Consider cleaning this up a bit and reposting.
I think it would be an excellent example without
the syntax and type errors.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top