State machine style.

P

Paul Marciano

Guest
Hi, another dumb question:

Text books describe Mealy and Moore state machines and all academic
examples I've seen use explicit next_state registers with a construct
similar to:

always @(posedge clk)
state <= next_state;


However, all real verilog I've seen uses a single state register,
assigned in contexts such as:

reg [...] state;

always @(...)
case (state)
`STATE_1: begin
if (foo)
begin
outputs <= values;
state <= `STATE_2;
end
...
end

`STATE_2: begin
if (bar)
begin
outputs <= values;
state <= `STATE_3;
end
...
end

....
endcase


Is there a preferred real-world style to state machine coding, or is it
just down to the engineer?

(yes, this is a really really dumb question - please humor me)

Thanks,
Paul.
 
Paul Marciano wrote:
Hi, another dumb question:

Text books describe Mealy and Moore state machines and all academic
examples
Advice I've given before: Forget the words "Mealy" and "Moore." In the
Real World, they're irrelevant.

I've seen use explicit next_state registers with a construct
similar to:

always @(posedge clk)
state <= next_state;

However, all real verilog I've seen uses a single state register,
assigned in contexts such as:

reg [...] state;

always @(...)
case (state)
`STATE_1: begin
if (foo)
begin
outputs <= values;
state <= `STATE_2;
end
...
end

`STATE_2: begin
if (bar)
begin
outputs <= values;
state <= `STATE_3;
end
...
end

...
endcase


Is there a preferred real-world style to state machine coding, or is it
just down to the engineer?

(yes, this is a really really dumb question - please humor me)
Some ancient synthesis tools were too stupid to extract state machines
from a single-always-block description. They needed a separate clocked
process/always block for the state registers. Anything modern is smart
enough not to need this, although some tool documentation seems to be
at least ten years out of date.

I always write my state machines using one clocked process. This
ensures that all outputs are registered. This also makes it quite
obvious what signals are changing when and why.

-a
 
Paul,

The style that you described is indeed a bad style. For crying out loud
please do not follow that style. Why?

1. It is a bad idea to mix combinational and sequential logic in one
always block. Outputs can be either combinational or sequential, and
state register is always sequential. If you want to write a sequential
logic block, put only the clock signal and optionally asynchronous
preset/reset signals in the sensitivity list. If you want to write a
combinational logic block, put either @* or a COMPLETE sensitivity list
after always.

2. Mixing next state logic and current state logic is also not good,
unless you have a very small state machine (<4 states). Otherwise, do
have a separate next state logic block, and make sure it's combinational
(no clocks in sensitivity list).

Cliff Cummings has written several papers on state machine styles which
I recommend you to read first: http://www.sunburst-design.com/papers/

hth,

jz

Paul Marciano wrote:
Hi, another dumb question:

Text books describe Mealy and Moore state machines and all academic
examples I've seen use explicit next_state registers with a construct
similar to:

always @(posedge clk)
state <= next_state;


However, all real verilog I've seen uses a single state register,
assigned in contexts such as:

reg [...] state;

always @(...)
case (state)
`STATE_1: begin
if (foo)
begin
outputs <= values;
state <= `STATE_2;
end
...
end

`STATE_2: begin
if (bar)
begin
outputs <= values;
state <= `STATE_3;
end
...
end

...
endcase


Is there a preferred real-world style to state machine coding, or is it
just down to the engineer?

(yes, this is a really really dumb question - please humor me)

Thanks,
Paul.
 
Jason Zheng wrote:
Paul,

1. It is a bad idea to mix combinational and sequential logic in one
always block.
Jason, my example was unclear - the always block was a sequential
block:

always @(posedge clk)
....


Thanks,
Paul.
 
Paul Marciano wrote:
Jason Zheng wrote:

Paul,

1. It is a bad idea to mix combinational and sequential logic in one
always block.


Jason, my example was unclear - the always block was a sequential
block:

always @(posedge clk)
...


Thanks,
Paul.

In that case, all the output signals will become registered. It may or
may not be what you really want. Even if that's what you want, there are
still reasons to separate output and state logic:

1. Though most synthesis tools today can produce the correct logic
structures, it is much easier to read and maintain the RTL code when you
have them separated.

2. The if/else statements imposes a PRIORITIZED logic, so what happens
if your output and state registers have different input priorities? For
example, consider the following verilog code:

always @ (posedge clk)
case (state)
...
stFoo: if (input1) state <= stBar;
else if (input2) state <= stErr;
...
endcase

always @ (posedge clk)
case (state)
...
stFoo: if (input2) output[1:0] <= 2'b01;
else if (input1) state[1:0] <= 2'b10;
...
endcase

There is no easy way to combine the two always blocks, is there? This is
just one simple example, and there are many many more if you consider
the different ways that you can combine case and if/else statements.

~jz
 
Jason,

That prioritzed conditional example is interesting, although I haven't
come across someting asymmetric like that before.

Jason Zheng wrote:
always @ (posedge clk)
case (state)
...
stFoo: if (input1) state <= stBar;
else if (input2) state <= stErr;
...
endcase
Do you agree that it's not necessary to have an explicit next_state
register?

It looks like the decision whether to include both the outputs and
state transitions in the same always block depends on the complexity of
the machine... which isn't a surprise.

Regards,
Paul.
 
Paul Marciano wrote:
Text books describe Mealy and Moore state machines and all academic
examples I've seen use explicit next_state registers with a construct
similar to:

always @(posedge clk)
state <= next_state;
This is my preference, just to make things readable. Just to be clear
"next_state" is a "reg" type, but (probably) not a flop. "Register" is an
ambiguous term in verilog.

However, all real verilog I've seen uses a single state register,
assigned in contexts such as:

reg [...] state;

always @(...)
case (state)
`STATE_1: begin
if (foo)
begin
outputs <= values;
state <= `STATE_2;
end
...
end

`STATE_2: begin
if (bar)
begin
outputs <= values;
state <= `STATE_3;
end
...
end

...
endcase
In the second example you have, of course, inferred extra flops for the
outputs. Clearly this is is timing advantage, but an area (and power)
disadvantage.

If power consumption is important to you, then the first example allows you
to make the clock gating term very explicit, like this:

always @(posedge clk)
begin : p_state_reg
if (en_state)
state <= nxt_state;
end // p_state_reg

always @*
begin : p_main_fsm
case (state)
ST_IDLE :
begin
case (start)
1'b1 :
begin
nxt_state = `ST_ACTIVE;
en_state = 1'b1;
end
1'b0 :
begin
nxt_state = `ST_IDLE;
en_state = 1'b0;
end
default :
begin
nxt_state = `ST_X;
en_state = 1'bx;
end
endcase
end
ST_ACTIVE :
begin
nxt_state = `ST_IDLE;
en_state = 1'b1;
end
...
endcase
end // p_main_fsm

--
John Penton, posting as an individual unless specifically indicated
otherwise.
 
Paul,

Paul Marciano wrote:
Jason,

That prioritzed conditional example is interesting, although I haven't
come across someting asymmetric like that before.
Sometimes these conflicts are subtle, and hard to catch when you have a
complex input list and large number of states. However, I believe that
mistakes can be reduced if you break up big always blocks into smaller
ones. Synthesis tools like it too.

<snip>

Do you agree that it's not necessary to have an explicit next_state
register?
My opinion is that unless you have a small state machine, and compelling
reasons to reduce the number of always blocks (e.g. line number
limitations in simulator/synthesis tool), do write a separate next_state
block. Having separate next_state and cur_state blocks really sets up a
structure that is reminiscent to the textbook FSM picture.

It looks like the decision whether to include both the outputs and
state transitions in the same always block depends on the complexity of
the machine... which isn't a surprise.
Same arguements as above, but in general I agree.

-jz
 
John Penton wrote:
always @(posedge clk)
begin : p_state_reg
if (en_state)
state <= nxt_state;
end // p_state_reg

always @*
begin : p_main_fsm
case (state)
ST_IDLE :
...
Thanks John. A followup if I may...

begin : p_state_reg
begin : p_main_fsm
I've not seen this syntax before. Are you naming the blocks somehow?
If so, are these names visible in simulation/synthesis, or are they
used for something else?


always @*
... combinatorial stuff...
Is @* preferable to an explicit sensitivity list? Is there any value
in explicit sensitivity lists beyond commenting the code? Are
simulators/synthesis tools sophisticated enough nowadays to not need
explicit sensitivity lists? Or is it just being lazy ;-) ?

Thanks,
Paul.
 
Paul Marciano wrote:

Is there a preferred real-world style to state machine coding, or is it
just down to the engineer?
It's down to you.
Which do you think is easier
to write, understand and maintain?

Much of the textbook description methods
have been made irrelevant by HDLs
and synthesis software.

Synthesis software is happy with
modules composed of large always
blocks or many small ones.
It is happy with non-blocking assignments
everywhere or non-blocking assignments
only for block to block communication.

Experiment and see what works best for you.

-- Mike Treseler
 
Paul Marciano wrote:
John Penton wrote:.

begin : p_state_reg
begin : p_main_fsm

I've not seen this syntax before. Are you naming the blocks somehow?
If so, are these names visible in simulation/synthesis, or are they
used for something else?
He is naming the blocks. In this case, I believe he is just doing it
for documentation, and a comment would have been adequate. Perhaps
some synthesis tools might use them to provide useful warnings. There
are two real uses for named blocks in the language. They allow
declaring variables local to the named block (which then use the
enclosing block name(s) in the hierarchical name of the variable). And
they allow the disable statement to be used on the block.

Is @* preferable to an explicit sensitivity list?
It has advantages in convenience and avoiding mistakes, in
combinational always blocks.

Is there any value
in explicit sensitivity lists beyond commenting the code?
Well, if it isn't a combinational always block, then you will need an
explicit event control. Also, the rules for @* may include some things
that you didn't really want to be sensitive to in some cases. But for
most combinational logic, @* is probably a good idea.

Are
simulators/synthesis tools sophisticated enough nowadays to not need
explicit sensitivity lists?
Umm, @* is the way you tell the simulator that you want it to create an
implicit sensitivity list, assuming that the always block is for
combinational logic. So a simulator that supports @* is "sophisticated
enough to not need explicit sensitivity lists." A simulator that
creates an implicit event control in an always block in any other
situation is not sophisticated, it is simply broken. The simulator's
job is to simulate the Verilog that you gave it, not make up its own.
If you tell it to execute something that doesn't match combinational
logic, or any real-world logic at all, its job is to do exactly what
you told it to do, not make something up.

Synthesis tools are different. They can't always produce logic that
matches the behavior of your Verilog code. When that happens,
sometimes they will produce an error. Other times they will apply
heuristics to guess what you meant, and produce logic that approximates
the behavior of your Verilog code. If they decide that your logic was
intended to be combinational, they may produce combinational logic,
even if your sensitivity list wasn't complete. The behavior of the
result may not match the original Verilog code, though it may match
what the designer intended.

The @* construct lets you tell both tools that you intend combinational
logic with a complete sensitivity list, and helps avoid differences in
the behavior before and after synthesis.

Or is it just being lazy ;-) ?
You can call it lazy, or efficient.
 
Mike Treseler wrote:
It's down to you.
Which do you think is easier
to write, understand and maintain?
Thanks Mike.

As an aside, I'm asking these questions as I'm learning verilog without
access to a mentor. In the past I've been able to read production RTL,
and have done so out of interest, but now I find myself wanting to
write it... only I'm no longer surrounded by ASIC engineers to hound
with newbie questions.

There are many ways to fix a flat. Some say it's good to practice
swapping out the spare as soon as get a new car. Some say it's better
to carry your own jack as opposed to using the crappy one supplied with
the car... but experience tells us that when it's dark and raining, it
better to stay warm and dry and call AAA.


I'm looking for the gentle nudges of wisdom you'd give to a junior guy,
just starting out.


Regards,
Paul.
 
Paul Marciano wrote:
John Penton wrote:
always @(posedge clk)
begin : p_state_reg
if (en_state)
state <= nxt_state;
end // p_state_reg

always @*
begin : p_main_fsm
case (state)
ST_IDLE :
...

Thanks John. A followup if I may...

begin : p_state_reg
begin : p_main_fsm

I've not seen this syntax before. Are you naming the blocks somehow?
If so, are these names visible in simulation/synthesis, or are they
used for something else?
Yes I am naming blocks. As to why, I'm not sure I can give a great answer.
Firstly, it has been recommended where I work (I don't know why, but I'm
sure there's a reason - it might aid translation to VHDL), secondly, I quite
like it as a way of commenting. Some tools (MTI for example) show you the
names, but again, I don't know what use it is.

always @*
... combinatorial stuff...

Is @* preferable to an explicit sensitivity list?
As has been said, for a combinatorial block, then yes, almost always. In my
experience, incomplete sensitivity lists cause a significant (maybe 2%)
number of bugs in code.

Is there any value
in explicit sensitivity lists beyond commenting the code? Are
simulators/synthesis tools sophisticated enough nowadays to not need
explicit sensitivity lists?
I believe the always @* construct is a Verilog-2001 construct. It does not
exist in Verilog-1995, but all the tools that I have used will support 2001
if you ask them (increasingly this is the default).

Or is it just being lazy ;-) ?
Yes, that too. I write Verilog-1995 at work, so I normally put:

always @(/*AUTOSENSE*/)

and then use the Emacs verilog mode to expand the list (from VIM as it
happens). This just highlights the redundancy problem in Verilog (the other
example is the module arguments list). Since a tool can compute the
sensitivity list automatically, it is actually rather redundant - hence the
Verilog-2001 syntax.

John

--
John Penton, posting as an individual unless specifically indicated
otherwise.
 
Paul Marciano wrote:

I'm looking for the gentle nudges of wisdom you'd give to a junior guy,
just starting out.
0.Learn your simulator inside and out.
1.Simulate lots of examples.
2.Once in a while do a trial synthesis and look at the rtl schematic.
3.Read books, papers, groups.google.
4.Repeat.

-- Mike Treseler
 
It can be up to the Coding Guidelines of the company or customer that
you work for... so be prepared to see both :)
 

Welcome to EDABoard.com

Sponsor

Back
Top