Synthesizable FSM

Y

yiannis

Guest
Hi everybody!I am trying to write a synthesizable fsm but i have this
problem.The coding style i use,has two always blocks,one sequential and
one combinational.But there are some registers,which are calculated
only once or twice in the combinational block,and in the other cases i
want to keep the previous value (which is not standard,so i cannot load
this value in every case).But this thing,infers a latch in the
design.Can i do something to avoid the latch in the combinational
logic,but remember a value in a register?You can imagine the register
as a pointer,which is only incremented when an event happens,but in all
the other cases has to keep the same value.

Thanks in advance,
Yiannis
 
yiannis wrote:
Hi everybody!I am trying to write a synthesizable fsm but i have this
problem.The coding style i use,has two always blocks,one sequential and
one combinational.But there are some registers,which are calculated
only once or twice in the combinational block,and in the other cases i
want to keep the previous value (which is not standard,so i cannot load
this value in every case).But this thing,infers a latch in the
design.Can i do something to avoid the latch in the combinational
logic,but remember a value in a register?You can imagine the register
as a pointer,which is only incremented when an event happens,but in all
the other cases has to keep the same value.
Write the whole thing as a single sequential always block. There is no
reason to have two separate blocks.

-a
 
Two blocks is the best style, as you may want combinational outputs,
having one sequential block forces the outputs to be flopped.

So here would be an example for you

always @(*) begin

// default assign
next_state = state;
next_ptr = ptr;

case (state)
...
WOOF: begin
if (a) begin
next_state = MEOW;
next_ptr = ptr + 1;
end
end
...
endcase
end


In this example the combinational output next_state and next_ptr hold
their previous value by default, and only change in state WOOF with a==1.

Regards, ~&

yiannis wrote:
Hi everybody!I am trying to write a synthesizable fsm but i have this
problem.The coding style i use,has two always blocks,one sequential and
one combinational.But there are some registers,which are calculated
only once or twice in the combinational block,and in the other cases i
want to keep the previous value (which is not standard,so i cannot load
this value in every case).But this thing,infers a latch in the
design.Can i do something to avoid the latch in the combinational
logic,but remember a value in a register?You can imagine the register
as a pointer,which is only incremented when an event happens,but in all
the other cases has to keep the same value.

Thanks in advance,
Yiannis
 
there are very good reasons to have two blocks, namely latency, having
one sequential block forces the outputs to be flopped.

Regards, ~&

Andy Peters wrote:

yiannis wrote:

Hi everybody!I am trying to write a synthesizable fsm but i have this
problem.The coding style i use,has two always blocks,one sequential and
one combinational.But there are some registers,which are calculated
only once or twice in the combinational block,and in the other cases i
want to keep the previous value (which is not standard,so i cannot load
this value in every case).But this thing,infers a latch in the
design.Can i do something to avoid the latch in the combinational
logic,but remember a value in a register?You can imagine the register
as a pointer,which is only incremented when an event happens,but in all
the other cases has to keep the same value.


Write the whole thing as a single sequential always block. There is no
reason to have two separate blocks.

-a
 
I find the simplest style is to separate the register component from
the next state logic. That is write a function that calculates next
state, and use it in a simple procedural block .

always @(posedge clk)
current_state = next_state ( current_state, a,b,c ) ;

/// Finite state machine documentations goes here
function [2:0] next_state ;
input [2:0] current_state ;
input a ;
input b ;
input c ;
begin
next_state = 'bx ; // In case you miss a default statement
case ( current_state)
`FOO: case ({a,b,c})
3'bxx1 : next_state = `BAR ;
3'bx10 : next_state = `CAT ;
3'bx11 : next_state = `DOG ;
default: next_state = 'bx ;
endcase
...
default: next_state = 'bx ;
endcase
end
endfunction

The benefit in this is that you won't be tempted to do stupid things
within your always block. It is just as synthesizable as other
constructs. You can't do any # delays, and you won't improperly infer
latches, or other nasty behavior because you missed an else statement
like some other peoples suggestions. This also make auditing state
machines easier, and makes it easier to point out this state machine to
a coverage analysis tool.

The above describes a Moore machine of course. If you want to add Mealy
type behavior to this machine, do that in a seperate block.

wire meely_stuff = current_state | ( a & b ) | c ;

or

reg meely_stuff
always @* begin
meely_stuff = current_state | ( a & b ) | c ;
end

Generally, independent readable smaller portions of code are easier to
debug, and easier for the next person to maintain.

my 2c.

-Art
 
Argh!

I mean :

always @(posedge clk)
current_state <= next_state ( current_state, a,b,c ) ;

Always use non-blocking assignments for sequential elements.

-Art
 
Mr Nand wrote:
there are very good reasons to have two blocks, namely latency, having
one sequential block forces the outputs to be flopped.
I find that in virtually every case, you want registered state-machine
outputs. You DO want to avoid glitching, right?

In the instances where you need combinatorial state-machine outputs
(perhaps because the outputs will be combined and registered with some
other logic elsewhere), you have to be careful. Some synthesis tools
have a hard time optimizing across entity/modules.

I'm still trying to think of an instance where I've needed to use a
combinatorial output of a state machine ...

-a
 
Andy,

I have used both comb. and registered output signals. While sometimes it
is desirable to have registered FSM outputs, esp. when the signal is
going off-chip somewhere, there are occassions that you need to have
comb. outputs due to latency requirements.

Glitch is not a big issue if you are using the signal within one clock
domain, since all the flip-flops only sample the data on clock edges,
and the place-n-route report gives you timing guarantees.

Finally, having separate blocks for one FSM does NOT force you to use
comb. outputs, it only gives you MORE flexibility. You can mix some
combinational and some sequential outputs if you like, and there's
nothing there to stop you from using just registered outputs. It is more
lines of code, but I sincerely believe that having separate blocks gives
a clearer picture of what you are designing, and it helps with
maintainence in the long run.

-jz

Andy Peters wrote:
Mr Nand wrote:

there are very good reasons to have two blocks, namely latency, having
one sequential block forces the outputs to be flopped.


I find that in virtually every case, you want registered state-machine
outputs. You DO want to avoid glitching, right?

In the instances where you need combinatorial state-machine outputs
(perhaps because the outputs will be combined and registered with some
other logic elsewhere), you have to be careful. Some synthesis tools
have a hard time optimizing across entity/modules.

I'm still trying to think of an instance where I've needed to use a
combinatorial output of a state machine ...

-a
 
Mr Nand wrote:
there are very good reasons to have two blocks, namely latency, having
one sequential block forces the outputs to be flopped.
In a synchronous design, all outputs get "flopped" eventually.
I prefer to handle all outputs using a particular combinational
node in the same block, using blocking (variable) assignments
right up to the module output non-blocking (signal) assignments.

Andy Peters wrote:
In the instances where you need combinatorial state-machine outputs
(perhaps because the outputs will be combined and registered with some
other logic elsewhere), you have to be careful.
Covering all the outputs in the same block is one way to do this.
It does make for large blocks, but the tools handle it and I
think it's easier to read sequential descriptions than
it is to read a netlist.

I'm still trying to think of an instance where I've needed to use a
combinatorial output of a state machine ...
There are a few legitimate asynchronous "glue" logic applications
for small devices where the programmable logic is part of an
external synchronous or handshake circuit. However, most
FPGAs are used to do very complex logic functions
and this usually means at least few ticks of latency.

-- Mike Treseler
 
Mike,

I'm particularly concerned about this piece of advice that you gave,

Mike Treseler wrote:
Covering all the outputs in the same block is one way to do this.
It does make for large blocks, but the tools handle it and I
think it's easier to read sequential descriptions than
it is to read a netlist.
Quite often the complexity of the FSM lgoic forces you to use multiple
blocks to describe output, as it would be difficult/impossible to do
them all in one block. I'll give you the example that I gave others befores:

always @*
if (condA) outA[1:0] = 2'b01;
else if (condB) outA[1:0] = 2'b10;
else if (condC) outA[1:0] = 2'b00;
else outA[1:0] = 2'b11;

always @*
if (condC) outB[1:0] = 2'b01;
else if (condB) outB[1:0] = 2'b11;
else if (condA) outB[1:0] = 2'b00;
else outB[1:0] = 2'b10;

I challenge you to combining outA and outB in one block in any elegant way.

~jz
 
Jason Zheng wrote:

I challenge you to combining outA and outB in one block in any elegant way.
My combined block would be a synchronous one
where outA and outB would become internal
combinational "regs" (local variables)
driving all of the registered module outputs
(not shown in your example) that need to use
these nodes. This might be a big block.

-- Mike Treseler
 
Jason Zheng wrote:
Mike,



Quite often the complexity of the FSM lgoic forces you to use multiple
blocks to describe output, as it would be difficult/impossible to do
them all in one block. I'll give you the example that I gave others
befores:

always @*
if (condA) outA[1:0] = 2'b01;
else if (condB) outA[1:0] = 2'b10;
else if (condC) outA[1:0] = 2'b00;
else outA[1:0] = 2'b11;

always @*
if (condC) outB[1:0] = 2'b01;
else if (condB) outB[1:0] = 2'b11;
else if (condA) outB[1:0] = 2'b00;
else outB[1:0] = 2'b10;

I challenge you to combining outA and outB in one block in any elegant way.


how about:

always @*
case({condA,condB,condC})
0: {outA,outB} = 4'b0010;
1: {outA,outB} = 4'b1101;
2: {outA,outB} = 4'b1011;
3: {outA,outB} = 4'b1001;
4: {outA,outB} = 4'b0100;
5: {outA,outB} = 4'b0101;
6: {outA,outB} = 4'b0111;
7: {outA,outB} = 4'b0101;
endcase
 
Mike Treseler wrote:
Jason Zheng wrote:

I challenge you to combining outA and outB in one block in any elegant
way.


My combined block would be a synchronous one
where outA and outB would become internal
combinational "regs" (local variables)
driving all of the registered module outputs
(not shown in your example) that need to use
these nodes. This might be a big block.

-- Mike Treseler
Mike,

Care to show an example? I'm a little confused here.

-jz
 
J o h n _ E a t o n (at) hp . com (no spaces) wrote:
Jason Zheng wrote:

Mike,




Quite often the complexity of the FSM lgoic forces you to use multiple
blocks to describe output, as it would be difficult/impossible to do
them all in one block. I'll give you the example that I gave others
befores:

always @*
if (condA) outA[1:0] = 2'b01;
else if (condB) outA[1:0] = 2'b10;
else if (condC) outA[1:0] = 2'b00;
else outA[1:0] = 2'b11;

always @*
if (condC) outB[1:0] = 2'b01;
else if (condB) outB[1:0] = 2'b11;
else if (condA) outB[1:0] = 2'b00;
else outB[1:0] = 2'b10;

I challenge you to combining outA and outB in one block in any elegant
way.


how about:

always @*
case({condA,condB,condC})
0: {outA,outB} = 4'b0010;
1: {outA,outB} = 4'b1101;
2: {outA,outB} = 4'b1011;
3: {outA,outB} = 4'b1001;
4: {outA,outB} = 4'b0100;
5: {outA,outB} = 4'b0101;
6: {outA,outB} = 4'b0111;
7: {outA,outB} = 4'b0101;
endcase
John,

I'm not gonna argue about the funtional equivalence between the priority
logic and parallel logic constructs, but the two blocks of block really
represent two distinct way of looking at a problem. Sometimes it is much
easier to solve the problem if you use priority logic, and sometimes it
is not.

Suppose I change the the problem a little bit, so that outA is sensitve
to condA, condB, and condC, but outB is sensitive to condB, condC, and
condD. Simple change, isn't it? It doesn't take much to change my
priority logic to accomandate it, but your solution would require a much
bigger (twice as long) case statement.

My pick? if the problem lends itself to priority logic, a priority logic
solution is usually more elegant in solving it.

-jz
 
Jason Zheng wrote:

My combined block would be a synchronous one
where outA and outB would become internal
combinational "regs" (local variables)
driving all of the registered module outputs
(not shown in your example) that need to use
these nodes. This might be a big block.

-- Mike Treseler

Mike,
Care to show an example? I'm a little confused here.
// http://home.comcast.net/~mike_treseler/single_process.pdf
module single_block
(clk, a, b, c, q1, q2);
output q1, q2;
input clk, a, b, c;
reg comb_v; // combinational node
reg q1, q2; // registered outputs
always @(posedge clk) begin
comb_v = a & b;
q1 <= comb_v & c;
if (c) comb_v = ~comb_v;
q2 <= comb_v;
end
endmodule
 
Mike Treseler wrote:
Jason Zheng wrote:

My combined block would be a synchronous one
where outA and outB would become internal
combinational "regs" (local variables)
driving all of the registered module outputs
(not shown in your example) that need to use
these nodes. This might be a big block.

-- Mike Treseler


Mike,
Care to show an example? I'm a little confused here.


// http://home.comcast.net/~mike_treseler/single_process.pdf
module single_block
(clk, a, b, c, q1, q2);
output q1, q2;
input clk, a, b, c;
reg comb_v; // combinational node
reg q1, q2; // registered outputs
always @(posedge clk) begin
comb_v = a & b;
q1 <= comb_v & c;
if (c) comb_v = ~comb_v;
q2 <= comb_v;
end
endmodule
Mike,

I've never seen coding style like this before. Are you sure that comb_v
will be combinational? It also seems that you went against many people's
advice of NOT combining blocking and non-blocking statements in one
always block.

~jz
 
Jason Zheng wrote:

Mike,

I've never seen coding style like this before.
Now you have. See:
http://groups.google.com/groups?q=verilog+local+variable+golden+rule
for some history on this subject.

Are you sure that comb_v will be combinational?
Yes. See the synthesis pdf.

It also seems that you went against many people's
advice of NOT combining blocking and non-blocking statements in one
always block.
I think that advice is overly cautious
if the designer is using simulation on all modules.
With verilog, it is up to the designer
to use local regs only on the left side of the "=".
Simulation will point out any errors on this.
With vhdl this is enforced by the language.

-- Mike Treseler
 
Jason Zheng wrote:

I've never seen coding style like this before. Are you sure that comb_v
will be combinational?
Wrong question. The correct one is: What should a synthesis tool do to
match the RTL behavior?

It also seems that you went against many people's
advice of NOT combining blocking and non-blocking statements in one
always block.
I would suggest to change gurus. Forget Cummings, I can recommend
Treseler instead :)

BTW, some googling in this newsgroup (and comp.lang.vhdl), and with
the names you encounter, will reveal useful information on the subject.
It has all been said before, starting in the early nineties (!).

Regards,

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
Electronic design with Python:
http://myhdl.jandecaluwe.com
 
Interesting points, Jan.

Jan Decaluwe wrote:
Jason Zheng wrote:

I've never seen coding style like this before. Are you sure that comb_v
will be combinational?


Wrong question. The correct one is: What should a synthesis tool do to
match the RTL behavior?
But I'm not sure what the RTL behavior is to start with. Aside from
mixing the blocking and non-blocking assignments, I thought anything
assigned in clock-triggered always blocks are automatically sequential.
Show me a page in Verilog language manual that says blocking assignments
in sequential blocks gives you combinational logic?

It also seems that you went against many people's
advice of NOT combining blocking and non-blocking statements in one
always block.


I would suggest to change gurus. Forget Cummings, I can recommend
Treseler instead :)
I don't care whom I take advice from, as long as they are logical and
reasonable. So far, I've found most of advice from Cliff Cummings very
reasonable.

BTW, some googling in this newsgroup (and comp.lang.vhdl), and with
the names you encounter, will reveal useful information on the subject.
It has all been said before, starting in the early nineties (!).
Yah...forgive me for my youthness and ignorance, but topics like this
are forever interesting. I learn new things every day from decade-old
discussions like this.

~jz
 

Welcome to EDABoard.com

Sponsor

Back
Top