How a state machine is constructed using latches?

W

Weng Tianxiang

Hi,
Sometimes, when an if statement misses a "else" statement part in a
two-process
method for a state machine, a latch-type state machine would be built.

I always wondering how the state machine is built: using all latches
for the state machine
or using only one latch for the state which misses a "else" statement
part.

Here is the code.

Process_1 : process(RESET, CLK)
begin
if RESET = '1' then
State_A <= S0;
elsif CLK'event and CLK = '1' then
State_A <= State_NS;
end if;
end process;

Process_2 : process(...)
begin
case State_A is
when S0 =>
if C01 = '1' then
State_NS <= S1;
elsif C02 = '1' then
State_NS <= S2; -- missing a "else" part
-- a latch is generated
end if;
when S1 => -- the followings are normal coding
...;

when others =>
...;
end case;
end process

I ask how the state latch S0 is generated.

Here is latch logic equation:
Latch_S0_Data <= '1';
Latch_S0_E <=

Weng
 
A

Andy

Hi,
Sometimes, when an if statement misses a "else" statement part in a
two-process
method for a state machine, a latch-type state machine would be built.

I always wondering how the state machine is built: using all latches
for the state machine
or using only one latch for the state which misses a "else" statement
part.

A latch type state machine is not built; the latch is only inserted
into the next state logic. A flip-flop still holds the current state.

I know the following is not the point of your post, but your example
implies that missing "else" statements generate latches.

This is not true.

Missing assignments generate latches. If a driven signal in a
combinatorial process is not assigned a value in a given execution of
the process, then the simulator has to remember what the last
assignment was. The synthesis tool generates a latch to create that
memory.

Similarly for a variable in a combinatorial process, if the variable
is read before it has been written in any given execution of that
process, a latch is created to remember the last assignment.

If I use a combinatorial process (extremely rarely in RTL), I make a
default assignment to every signal & variable driven by the process,
right up front, where it is always executed (and before any variables
are read). In the case of the next state logic, it would simply be
"state_ns <= state_a;". That way there is no need to code useless else
statements everywhere (and all the assignments that must otherwise be
included in them).

Andy
 
W

Weng Tianxiang

A latch type state machine is not built; the latch is only inserted
into the next state logic. A flip-flop still holds the current state.

I know the following is not the point of your post, but your example
implies that missing "else" statements generate latches.

This is not true.

Missing assignments generate latches. If a driven signal in a
combinatorial process is not assigned a value in a given execution of
the process, then the simulator has to remember what the last
assignment was. The synthesis tool generates a latch to create that
memory.

Similarly for a variable in a combinatorial process, if the variable
is read before it has been written in any given execution of that
process, a latch is created to remember the last assignment.

If I use a combinatorial process (extremely rarely in RTL), I make a
default assignment to every signal & variable driven by the process,
right up front, where it is always executed (and before any variables
are read). In the case of the next state logic, it would simply be
"state_ns <= state_a;". That way there is no need to code useless else
statements everywhere (and all the assignments that must otherwise be
included in them).

Andy

Andy,
Good point !

Now I ask how the next state latch is generated.

Weng
 
A

Andy

Now I ask how the next state latch is generated.

The latch is not just for S0, it is for the entire state. S0 is a
value for the state register, not a register or latch itself (unless
the FSM is one-hot encoded, but even then, the other state bits would
have a corresponding latch, with the same control, but with their
normal logic as the input).

It is only latched when in S0 (with other conditions: CO1 = '0' and
CO2 = '0').
The input to the latch is the all the normal next state logic.

Andy
 
W

Weng Tianxiang

A latch type state machine is not built; the latch is only inserted
into the next state logic. A flip-flop still holds the current state.

I know the following is not the point of your post, but your example
implies that missing "else" statements generate latches.

This is not true.

Missing assignments generate latches. If a driven signal in a
combinatorial process is not assigned a value in a given execution of
the process, then the simulator has to remember what the last
assignment was. The synthesis tool generates a latch to create that
memory.

Similarly for a variable in a combinatorial process, if the variable
is read before it has been written in any given execution of that
process, a latch is created to remember the last assignment.

If I use a combinatorial process (extremely rarely in RTL), I make a
default assignment to every signal & variable driven by the process,
right up front, where it is always executed (and before any variables
are read). In the case of the next state logic, it would simply be
"state_ns <= state_a;". That way there is no need to code useless else
statements everywhere (and all the assignments that must otherwise be
included in them).

Andy

Andy,
I read your post carefully and found my point stands:
"your example implies that missing "else" statements generate
latches.
This is not true. "

This is true !!! Based on your claim: Missing assignments (in a
combinational process) generate latches .

If one misses "else" (in a combinational process), it misses an
assignment statement.

Weng
 
W

Weng Tianxiang

The latch is not just for S0, it is for the entire state. S0 is a
value for the state register, not a register or latch itself (unless
the FSM is one-hot encoded, but even then, the other state bits would
have a corresponding latch, with the same control, but with their
normal logic as the input).

It is only latched when in S0 (with other conditions: CO1 = '0' and
CO2 = '0').
The input to the latch is the all the normal next state logic.

Andy

Andy,
I disagree with your point.

In the situation, at most only one latch is needed to resolve the
problem. Why full state machine?

We can safely assume the state machine is one-hot encoded.

Weng
 
W

whygee

hi,

Weng said:
In the situation, at most only one latch is needed to resolve the
problem. Why full state machine?
We can safely assume the state machine is one-hot encoded.
if you have troubles infering latches,
then you can implement them directly
with a specific entity ?
it's not looking as "smart" but
removes any ambiguity from your code.
yg
 
A

Andy Peters

Andy,
I read your post carefully and found my point stands:
"your example implies that missing "else" statements generate
latches.
This is not true. "

This is true !!! Based on your claim: Missing assignments (in a
combinational process) generate latches .

If one misses "else" (in a combinational process), it misses an
assignment statement.

Weng

I think the other Andy's point is that missing an "else" clause in a
combinatorial process is a special case of the more general "missing
an assignment."

-a
 
W

Weng Tianxiang

I think the other Andy's point is that missing an "else" clause in a
combinatorial process is a special case of the more general "missing
an assignment."

-a

No.

Here is another example showing Andy's point is not correct:

Here is the code.
Process_1 : process(RESET, CLK)
begin
if RESET = '1' then
State_A <= S0;
elsif CLK'event and CLK = '1' then
State_A <= State_NS;
end if;
end process;

Process_2 : process(...)
begin
case State_A is
when S0 =>
if C01 = '1' then
State_NS <= S1;
elsif C02 = '1' then
State_NS <= S2;
else
-- here an assignment statement is missing, but it doesn't
generate latch version !!!
-- it is treated as a null statement.
end if;
when S1 => -- the followings are normal coding
...;
when others =>
...;
end case;
end process;

If you have a compiler of VHDL, try to compile it to see what happens
with "else" and without "else".

Weng
 
S

sharp

I agree with Andy. The important thing is whether there is a path
through the code that does not assign one of the outputs. This is
often due to a missing else, but it is the assignment that matters.

You can have a missing else without a missing assignment, and there is
no latch. All that is required is that you have an unconditional
assignment to the outputs also.

You can have a missing assignment without a missing else, and there is
a latch. The else may be present, but assign only a subset of the
outputs.
 
S

sharp

Here is another example showing Andy's point is not correct:
....
         else
           -- here an assignment statement is missing, but it doesn't
generate latch version !!!
           -- it is treated as a null statement.

It may recognize that the latch for State_A already provides the
necessary latch to hold the state, and that it doesn't need an
additional latch for State_NS. Recognizing that it can re-use the
value from an existing latch is different from not needing a latch at
all.
 
K

KJ

   case State_A is
      when S0 =>
         if C01 = '1' then
           State_NS <= S1;
         elsif C02 = '1' then
           State_NS <= S2;
         else
           -- here an assignment statement is missing, but it doesn't
generate latch version !!!
           -- it is treated as a null statement.

A 'null statement' in this particular instance means that State_NS
will not change. If it doesn't change, this obviously implies it must
hold it's current value. So if C01 and C02 are both not equal to '1'
then whatever value State_NS has, it will keep. This implies that a
hardware implementation will have to implement the following
combinatorial logic as part of the logic for State_NS

State_NS <= ... (logic that handles the C01=1 and the C02=1
conditions)
or not(C01) and not(C02) and State_NS;

The last 'or' term is what implements the 'missing else branch'.

When you have a condition where you have
- A combinatorial assignment (we do, State_NS)
- The assigned to signal is also on the right hand side (we do)

This situation is commonly referred to as a 'latch'. Maybe it
shouldn't be but many times it is. A better term, in my opinion,
would be a combinatorial loop, which is to say that the generating
logic for some signal depends on the value of that signal itself. In
FPGA designs, it is typically a flag that you may have a design error.

The simplest form of this is type of condition is an oscillator x <=
not(x);
If you have a compiler of VHDL, try to compile it to see what happens
with "else" and without "else".
Which tool are you using?

KJ
 
R

rickman

Like Andy said, it is not the missing else that causes the latch to be
generated, it is the lack of an assignment in some path of the
process. The else is a control flow structure and has nothing to do
with assignments. Andy even gave you an example of when a missing
else will not generate a latch... when an assignment has been made
before or after the missing else...

I am pretty sure your example below *will* generate a latch.

No.

Here is another example showing Andy's point is not correct:

Here is the code.
Process_1 : process(RESET, CLK)
begin
   if RESET = '1' then
      State_A <= S0;
   elsif CLK'event and CLK = '1' then
      State_A <= State_NS;
   end if;
end process;

Process_2 : process(...)
begin
   case State_A is
      when S0 =>
         if C01 = '1' then
           State_NS <= S1;
         elsif C02 = '1' then
           State_NS <= S2;
         else
           -- here an assignment statement is missing, but it doesn't
generate latch version !!!
           -- it is treated as a null statement.
-- it does not matter if it is a null statement. The
process has to *remember* the last value of State_NS since it is not
assigned, so a latch is generated. See below
         end if;
      when S1 =>  -- the followings are normal coding
         ...;
      when others =>
         ...;
   end case;
end process;

If you have a compiler of VHDL, try to compile it to see what happens
with "else" and without "else".

Weng

case State_A is
when S0 =>
State_NS <= S0;
if C01 = '1' then
State_NS <= S1;
elsif C02 = '1' then
State_NS <= S2;
else
-- here an assignment statement is missing, but it doesn't
generate latch version !!!
-- it is treated as a null statement.
end if;
Here the state is explicitly assigned, so it can still be calculated
from the inputs, in this case State_A, C01 and C02.

This is an HDL (Hardware Description Language). Don't try to come up
with a set of rules of how hardware will be generated based on control
flow constructs. The only thing that matters is what operations of
the hardware are being described and therefore what hardware is being
described.

Rick
 
R

rickman

No.

Here is another example showing Andy's point is not correct:

Here is the code.
Process_1 : process(RESET, CLK)
begin
   if RESET = '1' then
      State_A <= S0;
   elsif CLK'event and CLK = '1' then
      State_A <= State_NS;
   end if;
end process;

Process_2 : process(...)
begin
   case State_A is
      when S0 =>
         if C01 = '1' then
           State_NS <= S1;
         elsif C02 = '1' then
           State_NS <= S2;
         else
           -- here an assignment statement is missing, but it doesn't
generate latch version !!!
           -- it is treated as a null statement.
         end if;
      when S1 =>  -- the followings are normal coding
         ...;
      when others =>
         ...;
   end case;
end process;

If you have a compiler of VHDL, try to compile it to see what happens
with "else" and without "else".

Weng

Fight fire with fire! The two reports below show that both the
missing else and the missing assignment (which is also missing in the
missing else case) produce latches.

@W: CL117 :"C:\arius\boards\tdc_upgrade\tests\latchsynthtest.vhd":
57:4:57:7|Latch generated from process for signal Latch, probably
caused by a missing assignment in an if or case stmt
@W: CL117 :"C:\arius\boards\tdc_upgrade\tests\latchsynthtest.vhd":
40:4:40:7|Latch generated from process for signal Comb, probably
caused by a missing assignment in an if or case stmt

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity LatchSynthTest is
port(
CLK : in std_logic ;
RESET : in std_logic ;
C01 : in std_logic ;
C02 : in std_logic ;
LatchOutput : out std_logic ;
CombOutput : out std_logic
);
end LatchSynthTest ;

architecture behavior of LatchSynthTest is
SIGNAL Latch : std_logic;
SIGNAL Comb : std_logic;
SIGNAL LatchReg : std_logic;
SIGNAL CombReg : std_logic;

begin

CombOutput <= CombReg;
LatchOutput <= LatchReg;

Process_1 : process(RESET, CLK)
begin
if (RESET = '1') then
LatchReg <= '0';
CombReg <= '0';
elsif (rising_edge(CLK)) then
LatchReg <= Latch;
CombReg <= Comb;
end if;
end process;

CombProc : process(CombReg, C01, C02)
begin
case CombReg is
when '0' =>
if (C01 = '1') then
Comb <= '0';
elsif (C02 = '1') then
Comb <= '1';
else
-- Here an assignment statement is missing, but it doesn't
-- generate latch. It is treated as a null statement. -
Weng
end if;
when others =>
Comb <= '1';
end case;
end process;

LatchProc : process(LatchReg, C01, C02)
begin
case LatchReg is
when '0' =>
if C01 = '1' then
Latch <= '0';
elsif C02 = '1' then
Latch <= '1';
-- Here the else is missing, and it does
-- generate latch. It is treated as a null statement.
end if;
when others =>
Latch <= '1';
end case;
end process;

end behavior;
 
W

Weng Tianxiang

Fight fire with fire!  The two reports below show that both the
missing else and the missing assignment (which is also missing in the
missing else case) produce latches.

@W: CL117 :"C:\arius\boards\tdc_upgrade\tests\latchsynthtest.vhd":
57:4:57:7|Latch generated from process for signal Latch, probably
caused by a missing assignment in an if or case stmt
@W: CL117 :"C:\arius\boards\tdc_upgrade\tests\latchsynthtest.vhd":
40:4:40:7|Latch generated from process for signal Comb, probably
caused by a missing assignment in an if or case stmt

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity LatchSynthTest is
  port(
          CLK                   : in    std_logic ;
          RESET                 : in    std_logic ;
          C01                   : in    std_logic ;
          C02                   : in    std_logic ;
          LatchOutput   : out   std_logic ;
          CombOutput    : out   std_logic
          );
end LatchSynthTest ;

architecture behavior of LatchSynthTest is
  SIGNAL Latch          : std_logic;
  SIGNAL Comb           : std_logic;
  SIGNAL LatchReg       : std_logic;
  SIGNAL CombReg        : std_logic;

begin

  CombOutput    <= CombReg;
  LatchOutput   <= LatchReg;

  Process_1 : process(RESET, CLK)
  begin
    if (RESET = '1') then
      LatchReg  <= '0';
      CombReg   <= '0';
    elsif (rising_edge(CLK)) then
      LatchReg  <= Latch;
      CombReg   <= Comb;
    end if;
  end process;

  CombProc : process(CombReg, C01, C02)
  begin
    case CombReg is
      when '0' =>
        if (C01 = '1') then
          Comb <= '0';
        elsif (C02 = '1') then
          Comb <= '1';
        else
          -- Here an assignment statement is missing, but it doesn't
          -- generate latch.  It is treated as a null statement. -
Weng
        end if;
      when others =>
        Comb <= '1';
    end case;
  end process;

  LatchProc : process(LatchReg, C01, C02)
  begin
    case LatchReg is
      when '0' =>
        if C01 = '1' then
          Latch <= '0';
        elsif C02 = '1' then
          Latch <= '1';
          -- Here the else is missing, and it does
          -- generate latch.  It is treated as a null statement.
        end if;
      when others =>
        Latch <= '1';
    end case;
  end process;

end behavior;

Hi,
Thank you, Andy, Rick and everyone, I am wrong in the second point:
missing "else" or missing an assignment statement.

But my first point is how to generate a latch for a compiler. Rick,
can you see the floor plan to show how the latch is generated: for the
state only or for full states?

Weng
 
R

rickman

Hi,
Thank you, Andy, Rick and everyone, I am wrong in the second point:
missing "else" or missing an assignment statement.

But my first point is how to generate a latch for a compiler. Rick,
can you see the floor plan to show how the latch is generated: for the
state only or for full states?

Weng

I'm not clear what you mean by "how". Are you asking about the detail
of how it is implemented in the FPGA? In the Lattice part they used a
FF as a latch. A register is between the latch and the output. They
drive the latch oddly driving both the clock and the async reset
inputs with logic, but then if you look at the code what would you
think is the clock? I don't see why they did it the way they did, but
it works correctly according to the VHDL. With only four inputs I
would expect they could have just used a single LUT4 and the latch
with the clock always enabled.

Din == '1'
Latch Enable == CombReg + C02
Async Clear == ~CombReg * C01

Is this what you are asking?

Rick
 
W

Weng Tianxiang

I'm not clear what you mean by "how".  Are you asking about the detail
of how it is implemented in the FPGA?  In the Lattice part they used a
FF as a latch.  A register is between the latch and the output.  They
drive the latch oddly driving both the clock and the async reset
inputs with logic, but then if you look at the code what would you
think is the clock?  I don't see why they did it the way they did, but
it works correctly according to the VHDL.  With only four inputs I
would expect they could have just used a single LUT4 and the latch
with the clock always enabled.

Din == '1'
Latch Enable == CombReg + C02
Async Clear  == ~CombReg * C01

Is this what you are asking?

Rick

Rick,
Yes, that is what I want.

Could you please send the code and a window screen frame using
Window's Paint so that I can see the full picture.

Thank you.

Weng
 
R

rickman

Rick,
Yes, that is what I want.

Could you please send the code and a window screen frame using
Window's Paint so that I can see the full picture.

Thank you.

Weng

I'm not clear on what you want. I posted the full code a couple of
posts back. What is it that you want a screen shot of? The text I
quoted was from the Synthesis report. If you want an image of the
chip editor, the latch only shows in the logic block editor dialog
box. It is just a check box on a schematic of the functional elements
in the logic block. Is that of any value to you?

Rick
 
W

Weng Tianxiang

I'm not clear on what you want.  I posted the full code a couple of
posts back.  What is it that you want a screen shot of?  The text I
quoted was from the Synthesis report.  If you want an image of the
chip editor, the latch only shows in the logic block editor dialog
box.  It is just a check box on a schematic of the functional elements
in the logic block.  Is that of any value to you?

Rick

Rick,
Thank you for your help.

This time I really understand what the Lattice does with your source
code in the previous poster.

Lattice generates a latch for the process of CombProc, paying no
attention to what is used.

And I think Lattice compiler does a very good job by generating the
following equations:

Din == '1'
Latch Enable == CombReg + C02
Async Clear == ~CombReg * C01

"With only four inputs I
would expect they could have just used a single LUT4 and the latch
with the clock always enabled. "

No. What you suggest may not work. Or it may work, but is not as
simple as the Lattice equations show.

I would like to see how you would write a LUT4 equation for a latch.

Weng
 
R

rickman

Rick,
Thank you for your help.

This time I really understand what the Lattice does with your source
code in the previous poster.

Lattice generates a latch for the process of CombProc, paying no
attention to what is used.

And I think Lattice compiler does a very good job by generating the
following equations:

Din == '1'
Latch Enable == CombReg + C02
Async Clear == ~CombReg * C01

"With only four inputs I
would expect they could have just used a single LUT4 and the latch
with the clock always enabled. "

No. What you suggest may not work. Or it may work, but is not as
simple as the Lattice equations show.

I would like to see how you would write a LUT4 equation for a latch.

Weng

Actually, I'm not certain the code you show (that I got from the
Lattice Logic Block Editor) is exactly the same as my VHDL
description. For them to match, the latch enable would have to have
priority over the reset and that is not a very normal feature in a
latch.

case CombReg is
when '0' =>
if (C01 = '1') then
Comb <= '0';
elsif (C02 = '1') then
Comb <= '1';
else
-- Here an assignment statement is missing, but it doesn't
-- generate latch. It is treated as a null statement. -Weng
end if;
when others =>
Comb <= '1';
end case;

Notice that once the latch is set to a '1' in the VHDL, there is no
way to clear it. When CombReg is a '1', the "others" clause of the
case is executed which only allows it to be a '1'. The async clear
can only be asserted when CombReg is a '0'. Of course, Comb and
CombReg are not the same signals, so there is a window between the
latch being set and the Register output going high where the latch can
be reset by C01.

There are only four inputs to this logic function "Comb". A LUT4 can
implement ***ANY*** logic function of 4 inputs. So there certainly is
a way to implement the above VHDL in a single LUT4. In fact, you
don't even need the latch.

Comb <= CombReg or (C02 and not C01) or (Comb and not C01);

If you want to use the built in Latch in the FPGA, then I guess you
have to use a LUT4 to generate the enable and another to generate the
data (or async clear).

Enable <= CombReg or C01 or C02;
DataIn <= CombReg or not C01;

There is no savings by only using 2 of the 4 inputs on a LUT4 but
there is some advantage to using the reset input to a Latch. I think
it may avoid potential race conditions when only one input switches.
My logic will have some problems, for example CombReg = 0, C02 = 0 and
C01 = 1. Bring C01 low and it will either stay clear or set the latch
depending on which of the two paths are faster. Hmmm, maybe the tools
aren't so stupid after all. In essence, they are using the enable as
a set and the async reset as a... well, a reset!

Rick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top