state machine with asynchronous reset?

  • Thread starter glen herrmannsfeldt
  • Start date
G

glen herrmannsfeldt

Guest
I am trying to figure out how to write a synthesizable state
machine with async. reset. I have a fine synchronous reset,
which starte something like:

always @(posedge clk) begin
if(reset) state <= s0;
else case (state)

I have tried

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else case (state)

but it doesn't work, at least it doesn't synthesize an asynchronous
reset, and it doesn't seem to simulate right, either.

I have also tried separate always @(posedge clock) and
always @(posedge reset) blocks, which usually get complaints
about driving the same net two different places.

Is there a nice way to do this?

-- glen
 
On Mon, 04 Oct 2004 18:13:35 -0700, glen herrmannsfeldt
<gah@ugcs.caltech.edu> wrote:
I have tried

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else case (state)

but it doesn't work, at least it doesn't synthesize an asynchronous
reset, and it doesn't seem to simulate right, either.
That's the definition of not working all right :) The problem is that
it should because it seems to be the right way of inferring an async
reset. What is the synthesis report saying ? What result are you
getting from the simulation ? One issue which may complicate the
things is the definition of s0. Is it constant resolvable at compile
time ?
 
glen herrmannsfeldt wrote:
I am trying to figure out how to write a synthesizable state
machine with async. reset. I have a fine synchronous reset,
which starte something like:

always @(posedge clk) begin
if(reset) state <= s0;
else case (state)

I have tried

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else case (state)

but it doesn't work, at least it doesn't synthesize an asynchronous
reset, and it doesn't seem to simulate right, either.

I have also tried separate always @(posedge clock) and
always @(posedge reset) blocks, which usually get complaints
about driving the same net two different places.

Is there a nice way to do this?

-- glen
Try replacing if(reset) state <= 'b0; to see if that works.
It has to be known at compile time or you will get some really
gross logic.


Why do you want to use an asynchronous reset? You have to filter
the leading edge or have the first runt pulse on your reset_pad
send your SM off to la-la land. You also have to filter the
trailing edge to guarentee your setup/hold on reset to clk.
You'll wind up with a sync reset anyway.


The only flops that really NEED an async reset are those that
directly drive an output pad and those should also have an
additional sync reset to prevent clk reset setup issues.



John Eaton
 
J o h n _ E a t o n (at) hp . com (no spaces) wrote:

glen herrmannsfeldt wrote:

I am trying to figure out how to write a synthesizable state
machine with async. reset.
(snip)

I have tried

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else case (state)

but it doesn't work, at least it doesn't synthesize an asynchronous
reset, and it doesn't seem to simulate right, either.

I have also tried separate always @(posedge clock) and
always @(posedge reset) blocks, which usually get complaints
about driving the same net two different places.
(snip)

Try replacing if(reset) state <= 'b0; to see if that works.
It has to be known at compile time or you will get some really
gross logic.
I should have included that before. The states are described
in parameter statements. This is compiled by Quartus II, where
Altera recommends parameter statements for state machine states.

I believe the compiler is supposed to recognize that it is a
state machine and compile it appropriately.

Why do you want to use an asynchronous reset? You have to filter
the leading edge or have the first runt pulse on your reset_pad
send your SM off to la-la land. You also have to filter the
trailing edge to guarentee your setup/hold on reset to clk.
You'll wind up with a sync reset anyway.
Well, I probably don't need it. Since all the FF's have
reset inputs it seemed nice to use them. I am adding this
to an existing design which does have async. resets (for
logic that is not a state machine).

The only flops that really NEED an async reset are those that
directly drive an output pad and those should also have an
additional sync reset to prevent clk reset setup issues.
I will stick with the synchronous reset for now. At some point
it would be nice just to understand why it didn't work, though.

thanks,

-- glen
 
Chris Alexander wrote:

Your code looks correct. Without seeing anything else, I would have
to assume it is either a synthesis problem or a problem with your
target technology (ie, the device _doesn't allow_ async resets.

I have some questions that maybe will help find the answer:

- What version of Quartus are your running?
4.0

- What happens if you target a different device, say a Cyclone EP1C3?
I haven't tried that. Good question.

- Can you try a different synthesis tool? Either Synplify or the
Xilinx XST tool from the webpack distribution will give you a second
data point / different wording of the error message.
(snip regarding async. reset on state machines)

One more question.

It seems that some Altera examples I see have two state
variables, where one is assigned to and the other is used
in the case statement. It seems that isn't ordinarily
necessary, clutters up the code, and otherwise doesn't
help.

Something like:

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else state <= next_state;
end

always @(state) case(state)
s0: if(something) next_state <= s1;



I suppose it is less confusing to some people
not to assign to the state variable, but, at least in
the synchronous reset case it seems to be fine.
(Putting the case statement inside an
always @(posedge clk) block seems enough for me.)

Under some conditions, I would get errors relating to
multiple assignments to the same net, even though I had
appropriate if statements, yet other times Quartus would not
complain about it.


Say, for example:

always @(posedge reset) state <- s0;

always @(posedge clk) case(state)
s0: state <= s1;

Now, theoretically posedge clk and posedge reset
could occur at the same time, and it would be
ambiguous, but then that is true of async. reset
in any case.

Well, I have started to get used to synchronous reset
now, though the FF's do still have a reset input.

-- glen
 
Hi Glen,

I dont think your problem has anything to do with async/sync reset.

You assign reg 'state' from two different always statements simultaneously.
That's two concurrent assignments, which is the cause of the synthesis error,
and the mismatch in simulation.

If you code up your state machine in two always statements (register in one,
and state-transition (case) statement in the other, you have to use two variables.
Use 'state' and 'next_state' just like Quartus's manual subscribes.

I am actually surprised that you did not get the error in the 'synchronous' case.

Cheers

Rob


"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message news:ck4m51$f4q$1@gnus01.u.washington.edu...
One more question.

It seems that some Altera examples I see have two state
variables, where one is assigned to and the other is used
in the case statement. It seems that isn't ordinarily
necessary, clutters up the code, and otherwise doesn't
help.

Something like:

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else state <= next_state;
end

always @(state) case(state)
s0: if(something) next_state <= s1;



I suppose it is less confusing to some people
not to assign to the state variable, but, at least in
the synchronous reset case it seems to be fine.
(Putting the case statement inside an
always @(posedge clk) block seems enough for me.)

Under some conditions, I would get errors relating to
multiple assignments to the same net, even though I had
appropriate if statements, yet other times Quartus would not
complain about it.


Say, for example:

always @(posedge reset) state <- s0;

always @(posedge clk) case(state)
s0: state <= s1;

Now, theoretically posedge clk and posedge reset
could occur at the same time, and it would be
ambiguous, but then that is true of async. reset
in any case.

Well, I have started to get used to synchronous reset
now, though the FF's do still have a reset input.

-- glen
 
Rob Dekker wrote:

I dont think your problem has anything to do with async/sync reset.

You assign reg 'state' from two different always statements simultaneously.
That's two concurrent assignments, which is the cause of the synthesis error,
and the mismatch in simulation.

If you code up your state machine in two always statements (register in one,
and state-transition (case) statement in the other, you have to use two variables.
Use 'state' and 'next_state' just like Quartus's manual subscribes.

I am actually surprised that you did not get the error in the 'synchronous' case.
(snip)

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else state <= next_state;
end

always @(state) case(state)
s0: if(something) next_state <= s1;
Well, in most cases there is an if to separate them.

The synchronous case is something like:

always @(posedge clk) begin
if(reset) state <= s0;
else case(state)

As only one branch of the if can be taken, only
one assignment applies, and the simulator seems
to figure that out. For the asynchronous case,
adding posedge reset to the always statement,
it doesn't figure it out. (That is, still with
one always statement.)

Depending on exactly the way I arrange it, sometimes
it would complain even though there was an if, and sometimes
not even without an if. (Some with one, some with two
always statements.)

I suppose it is less confusing to some people
not to assign to the state variable, but, at least in
the synchronous reset case it seems to be fine.
(Putting the case statement inside an
always @(posedge clk) block seems enough for me.)
Until recently, most of my verilog was structural model,
except for registers. Lately I have been doing state
machines and am becoming more comfortable with what the
synthesizer can do with behavioral code.

thanks,

-- glen
 
mk wrote:

On Mon, 04 Oct 2004 18:13:35 -0700, glen herrmannsfeldt
gah@ugcs.caltech.edu> wrote:

I have tried

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else case (state)

but it doesn't work, at least it doesn't synthesize an asynchronous
reset, and it doesn't seem to simulate right, either.

That's the definition of not working all right :) The problem is that
it should because it seems to be the right way of inferring an async
reset. What is the synthesis report saying ? What result are you
getting from the simulation ? One issue which may complicate the
things is the definition of s0. Is it constant resolvable at compile
time ?
parameter s0=3'b000;

Altera recommends parameters for state machine states.

Without posedge reset in the dependency list it seems to
simulate and synthesize a synchronous reset just fine.

Just adding posedge reset, and with the if(reset) still there,
the simulation doesn't seem to change state at all.
RTL viewer shows little blocks with sm_reset inputs, instead
of the normal FF's that were generated before. Also, inverted
reset is added as an enable input on all other FF's, such as
a counter used by the state machine.

If I do:

always @(posedge reset) state <= s0;

always @(posedge clk) begin
case (state)

I get:

Error: Can't resolve multiple constant drivers for net
state.s3 at output_state.v(84)
Error: Constant driver at output_state.v(155)

as it realized that both could happen at the same time.

(The line numbers are the end statement of the appropriate
always block.)

This is for ACEX 1K where all FF's have asynchronous reset
inputs, as in most FPGA's. Though probably synchronous
reset will work just fine.

-- glen
 
Your code looks correct. Without seeing anything else, I would have
to assume it is either a synthesis problem or a problem with your
target technology (ie, the device _doesn't allow_ async resets.

I have some questions that maybe will help find the answer:

- What version of Quartus are your running?
- What happens if you target a different device, say a Cyclone EP1C3?
- Can you try a different synthesis tool? Either Synplify or the
Xilinx XST tool from the webpack distribution will give you a second
data point / different wording of the error message.

Chris

glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote in message news:<cjss5i$ccf$1@gnus01.u.washington.edu>...
I am trying to figure out how to write a synthesizable state
machine with async. reset. I have a fine synchronous reset,
which starte something like:

always @(posedge clk) begin
if(reset) state <= s0;
else case (state)

I have tried

always @(posedge clk or posedge reset) begin
if(reset) state <= s0;
else case (state)

but it doesn't work, at least it doesn't synthesize an asynchronous
reset, and it doesn't seem to simulate right, either.

I have also tried separate always @(posedge clock) and
always @(posedge reset) blocks, which usually get complaints
about driving the same net two different places.

Is there a nice way to do this?

-- glen
 
Rob - I think you misread his post. The 2 always statements are
assigning different variables. The first is "state", the second is
"next_state"...

"Rob Dekker" <rob@verific.com> wrote in message news:<bi1bd.29256$QJ3.15952@newssvr21.news.prodigy.com>...
Hi Glen,

I dont think your problem has anything to do with async/sync reset.

You assign reg 'state' from two different always statements simultaneously.
That's two concurrent assignments, which is the cause of the synthesis error,
and the mismatch in simulation.

If you code up your state machine in two always statements (register in one,
and state-transition (case) statement in the other, you have to use two variables.
Use 'state' and 'next_state' just like Quartus's manual subscribes.
 
Chris Alexander wrote:
Rob - I think you misread his post. The 2 always statements are
assigning different variables. The first is "state", the second is
"next_state"...
I have done many different combinations of always
statements, if statements, and assignments.

My preference is one always statement and one state
variable, and it works fine for the synchronous case.

At one point I thought it was confused between the
clock and reset lines, so I tried two always blocks.

I have been just about convinced that synchronous reset
is better, though it would still be nice to know how to
do asynchronous reset.

always @(posedge clk or posedge reset) if(reset) out <= 0;
else if(enable) begin
if(up) out <= out+1;
else out <= out-1;
end

Does seem to generate a counter with asynchronous reset,
as I thought it should.

-- glen
 
"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message news:ckk45g$7e5$1@gnus01.u.washington.edu...
Chris Alexander wrote:
Rob - I think you misread his post. The 2 always statements are
assigning different variables. The first is "state", the second is
"next_state"...
You are right. I read the two alternatives as a single piece of code...

I have done many different combinations of always
statements, if statements, and assignments.

My preference is one always statement and one state
variable, and it works fine for the synchronous case.
The trouble with a FSM with async reset in a single always statement are the output assignments.

The outputs are automatically clocked (since they are in the single case statement), so they create registers.
But if you forgot to also async reset them in the same always statement, you get a tricky circuit
(with the state register asyncronously reset, but the output registers in 'hold' state (probably synchronous) when the reset
occurs.

That problem is not there if you use two always statements, since the outputs are not clocked.
You can still decide to clock them in a separate other always statement, where they will be clearly visible.

At one point I thought it was confused between the
clock and reset lines, so I tried two always blocks.

I have been just about convinced that synchronous reset
is better, though it would still be nice to know how to
do asynchronous reset.

always @(posedge clk or posedge reset) if(reset) out <= 0;
else if(enable) begin
if(up) out <= out+1;
else out <= out-1;
end

Does seem to generate a counter with asynchronous reset,
as I thought it should.
Glen, are you willing to share the entire single always statement with us ?

If you get a counter with async reset from the above example, you should get a FSM with async reset also...

 

Welcome to EDABoard.com

Sponsor

Back
Top