FPGARelated.com
Forums

When is it to generate transparent latch or usual combinational logic?

Started by Weng Tianxiang May 25, 2009
Hi,
Through discussions of last problem title "Are all these claims in
VHDL correct?" I understand how to recognize a transparent latch from
a register.

Here I gave an example to show what I am puzzled.

State1_A : process(CLK)
begin
   if CLK'event and CLK = '1' then
      if SINI = '1' then
         State1 <= Idle_S;
      else
         State1 <= State1_NS;
      end if;
   end if;
end if;

State1_B : process(State1, A1, A2)
begin
   case State1 is
      when Idle_S =>
         if A1 = '1' then
            State1_NS <= X_S;
         else
            State1_NS <= Idle_S;
         end if;

      when X_S =>
         if A2 = '1' then
            State1_NS <= Idle_S;
         else
            State1_NS <= X_S;
         end if;
   end case;
end process;

State2_A : process(SINI, CLK)
begin
   if CLK'event and CLK = '1' then
      if SINI = '1' then
         State2 <= Idle_S;
      else
         State2 <= State2_NS;
      end if;
   end if;
end if;

State2_B : process(State2, A1, A2)
begin
   case State2 is
      when Idle_S =>
         if A1 = '1' then
            State2_NS <= X_S;
--         else                     <-- key difference
--            State2_NS <= Idle_S;
         end if;

      when X_S =>
         if A2 = '1' then
            State2_NS <= Idle_S;
         else
            State2_NS <= X_S;
         end if;
   end case;
end process;

From my experiences with state machine, VHDL compiler would generate
warning for state2: "state machine state2 will be implemented as
latches".

Once It took me one week to have found the similar situation with the
above state2 in my a long state machine.

I don't know why VHDL compiler generate latches for state2.

Thank you.

Weng
On May 25, 3:52=A0pm, Weng Tianxiang <wtx...@gmail.com> wrote:
> Hi, > Through discussions of last problem title "Are all these claims in > VHDL correct?" I understand how to recognize a transparent latch from > a register. > > Here I gave an example to show what I am puzzled. > > State1_A : process(CLK) > begin > =A0 =A0if CLK'event and CLK =3D '1' then > =A0 =A0 =A0 if SINI =3D '1' then > =A0 =A0 =A0 =A0 =A0State1 <=3D Idle_S; > =A0 =A0 =A0 else > =A0 =A0 =A0 =A0 =A0State1 <=3D State1_NS; > =A0 =A0 =A0 end if; > =A0 =A0end if; > end if; > > State1_B : process(State1, A1, A2) > begin > =A0 =A0case State1 is > =A0 =A0 =A0 when Idle_S =3D> > =A0 =A0 =A0 =A0 =A0if A1 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State1_NS <=3D X_S; > =A0 =A0 =A0 =A0 =A0else > =A0 =A0 =A0 =A0 =A0 =A0 State1_NS <=3D Idle_S; > =A0 =A0 =A0 =A0 =A0end if; > > =A0 =A0 =A0 when X_S =3D> > =A0 =A0 =A0 =A0 =A0if A2 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State1_NS <=3D Idle_S; > =A0 =A0 =A0 =A0 =A0else > =A0 =A0 =A0 =A0 =A0 =A0 State1_NS <=3D X_S; > =A0 =A0 =A0 =A0 =A0end if; > =A0 =A0end case; > end process; > > State2_A : process(SINI, CLK) > begin > =A0 =A0if CLK'event and CLK =3D '1' then > =A0 =A0 =A0 if SINI =3D '1' then > =A0 =A0 =A0 =A0 =A0State2 <=3D Idle_S; > =A0 =A0 =A0 else > =A0 =A0 =A0 =A0 =A0State2 <=3D State2_NS; > =A0 =A0 =A0 end if; > =A0 =A0end if; > end if; > > State2_B : process(State2, A1, A2) > begin > =A0 =A0case State2 is > =A0 =A0 =A0 when Idle_S =3D> > =A0 =A0 =A0 =A0 =A0if A1 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State2_NS <=3D X_S; > -- =A0 =A0 =A0 =A0 else =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 <-- key d=
ifference
> -- =A0 =A0 =A0 =A0 =A0 =A0State2_NS <=3D Idle_S; > =A0 =A0 =A0 =A0 =A0end if; > > =A0 =A0 =A0 when X_S =3D> > =A0 =A0 =A0 =A0 =A0if A2 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State2_NS <=3D Idle_S; > =A0 =A0 =A0 =A0 =A0else > =A0 =A0 =A0 =A0 =A0 =A0 State2_NS <=3D X_S; > =A0 =A0 =A0 =A0 =A0end if; > =A0 =A0end case; > end process; > > From my experiences with state machine, VHDL compiler would generate > warning for state2: "state machine state2 will be implemented as > latches". > > Once It took me one week to have found the similar situation with the > above state2 in my a long state machine. > > I don't know why VHDL compiler generate latches for state2. > > Thank you. > > Weng
Are you sure the latch isn't being created for State2_NS? You may want to put a "when others =3D>" clause at the end of the case statement to make sure State2_NS gets assigned something en every case. A default assignment at the top of the process would give similar effects. Also, SINI doesn't need to be in the sensitivity list for the State2 process, but it shouldn't hurt anything other than simulation time. Dave
Weng,

You've told the synthesizer that state2_ns (the combinatorial signal,
not the register) has to remember its previous value under certain
circumstances, so it generates a latch to remember the value.

Your choices to avoid the latch include a) avoiding combinatorial
processes, b) including a default assignment (perhaps from the output
of the associated register) in combinatorial processes, or c) making
sure every possible execution path through the process results in all
driven signals being assigned a value (and not just to themselves).

I always choose (a). If you just have to use a combinatorial process,
then (b) is much easier to read/write/verify/review than is(c).

Andy
On May 25, 2:28=A0pm, Andy <jonesa...@comcast.net> wrote:
> Weng, > > You've told the synthesizer that state2_ns (the combinatorial signal, > not the register) has to remember its previous value under certain > circumstances, so it generates a latch to remember the value. > > Your choices to avoid the latch include a) avoiding combinatorial > processes, b) including a default assignment (perhaps from the output > of the associated register) in combinatorial processes, or c) making > sure every possible execution path through the process results in all > driven signals being assigned a value (and not just to themselves). > > I always choose (a). If you just have to use a combinatorial process, > then (b) is much easier to read/write/verify/review than is(c). > > Andy
Hi Andy, "You've told the synthesizer that state2_ns (the combinatorial signal, not the register) has to remember its previous value under certain circumstances, so it generates a latch to remember the value." You are right and I understand it. I am interested in your method a. Could you give me an example on how to use your method a. in the above situation. Thank you. Weng
On Mon, 25 May 2009 16:44:28 -0700 (PDT), Weng Tianxiang <wtxwtx@gmail.com>
wrote:

>On May 25, 2:28&#4294967295;pm, Andy <jonesa...@comcast.net> wrote: >> Weng, >> >> You've told the synthesizer that state2_ns (the combinatorial signal, >> not the register) has to remember its previous value under certain >> circumstances, so it generates a latch to remember the value. >> >> Your choices to avoid the latch include a) avoiding combinatorial >> processes,
>Hi Andy,
>You are right and I understand it. I am interested in your method a. >Could you give me an example on how to use your method a. in the above >situation.
Search for "Single Process State Machine" - it has been described many times on this group and it is the usual way to avoid combinatorial processes in your example - to avoid precisely the problem that you took a week to find. - Brian
Here ya go...

State2 : process(CLK)
begin
   if rising_edge(CLK) then
      if SINI = '1' then
        State2 <= Idle_S;
      else
        case State2 is
        when Idle_S =>
          if A1 = '1' then
            State2 <= X_S;
          end if;
        when X_S =>
          if A2 = '1' then
            State2 <= Idle_S;
          end if;
        end case;
      end if; -- sini
   end if; -- clk
end process;


Unless you know that SINI is initially asserted (to initialize the
state machine), you will need a reset for the state machine too.

Andy
On May 26, 5:58=A0am, Andy <jonesa...@comcast.net> wrote:
> Here ya go... > > State2 : process(CLK) > begin > =A0 =A0if rising_edge(CLK) then > =A0 =A0 =A0 if SINI =3D '1' then > =A0 =A0 =A0 =A0 State2 <=3D Idle_S; > =A0 =A0 =A0 else > =A0 =A0 =A0 =A0 case State2 is > =A0 =A0 =A0 =A0 when Idle_S =3D> > =A0 =A0 =A0 =A0 =A0 if A1 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State2 <=3D X_S; > =A0 =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 =A0 when X_S =3D> > =A0 =A0 =A0 =A0 =A0 if A2 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State2 <=3D Idle_S; > =A0 =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 =A0 end case; > =A0 =A0 =A0 end if; -- sini > =A0 =A0end if; -- clk > end process; > > Unless you know that SINI is initially asserted (to initialize the > state machine), you will need a reset for the state machine too. > > Andy
Hi Andy and Brian, 1. Good point: use one process state machine. 2. How do you handle turn-on signals in a state machine? State2_B : process(State2, A1, A2) begin Turn_On <=3D '0'; case State2 is when Idle_S =3D> if A1 =3D '1' then Turn_On <=3D '1'; State2_NS <=3D X_S; -- else <-- key difference -- State2_NS <=3D Idle_S; end if; when X_S =3D> if A2 =3D '1' then State2_NS <=3D Idle_S; else State2_NS <=3D X_S; end if; end case; end process; 3. I don't like one process state machine writing type and Xilinx and Altera all recommend using 2 process method. I have a state machine that has 3000 lines and 30 turn-on signals. One process method is hard to handle my situation. 4. I say VHDL synthesizer should be SMARTER to avoid generating transparent latch in the exact my situations: Locally State2_NS is described as transparent latches, but globally, they are only used in one statement: State2 <=3D State2_NS; or they are assigned to registers: State2 which is the case signal in the case process so that generating transparent latches for State2_NS is OVER-REACTING and State2_NS should be generated as a combinational logic !!! That is what I want to say and highlight !!! Global optimization rule for VHDL synthesizers: if a type signal (as State2_NS) is specified in a case process (case process is a process that contains only one case statement as State2_B shows) as a latch type, and it is only used to be assigned to the case signal in the case process, the latch signal can be reduced to combinational logic without any harm, because the case register keeps the data unchanged for the latch signal. Weng
Andy wrote:
> Here ya go... > > State2 : process(CLK) > begin > if rising_edge(CLK) then > if SINI = '1' then > State2 <= Idle_S; > else > case State2 is > when Idle_S => > if A1 = '1' then > State2 <= X_S; > end if; > when X_S => > if A2 = '1' then > State2 <= Idle_S; > end if; > end case; > end if; -- sini > end if; -- clk > end process;
Thanks for taking the time to post this simplified solution. This thread demonstrates the clarity provided by minimizing the number of processes in a design entity. More importantly, it shows the downside of using an asynchronous process for synthesis. -- Mike Treseler
This example shows one way to handle outputs, but inserts a one clock
delay on the output.

State2 : process(CLK)
begin
   if rising_edge(CLK) then
      turn_on <= '0';
      if SINI = '1' then
        State2 <= Idle_S;
      else
        case State2 is
        when Idle_S =>
          if A1 = '1' then
            turn_on <= '1';
            State2 <= X_S;
          end if;
        when X_S =>
          if A2 = '1' then
            State2 <= Idle_S;
          end if;
        end case;
      end if; -- sini
   end if; -- clk
end process;

If you want to avoid the delay, just assert the output when you
transition into the states in which you want it on. I think it was
Jonathan Bromley that demonstrated a method, using variables, to
describe state machine outputs more easily in a single clocked
process.

It's not that hard to do, and you don't get latches, ever!

If you really prefer dual-process state machines, there are proven,
easy ways to avoid latches in them (like default "State <= State_NS"
assignments). Quite frankly, I'd prefer the synthesis vendors work on
other optimizations that are more important to quality of results,
than avoiding inferring latches from poorly written RTL code.

Andy
On May 26, 3:21=A0pm, Andy <jonesa...@comcast.net> wrote:
> This example shows one way to handle outputs, but inserts a one clock > delay on the output. > > State2 : process(CLK) > begin > =A0 =A0if rising_edge(CLK) then > =A0 =A0 =A0 turn_on <=3D '0'; > =A0 =A0 =A0 if SINI =3D '1' then > =A0 =A0 =A0 =A0 State2 <=3D Idle_S; > =A0 =A0 =A0 else > =A0 =A0 =A0 =A0 case State2 is > =A0 =A0 =A0 =A0 when Idle_S =3D> > =A0 =A0 =A0 =A0 =A0 if A1 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 turn_on <=3D '1'; > =A0 =A0 =A0 =A0 =A0 =A0 State2 <=3D X_S; > =A0 =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 =A0 when X_S =3D> > =A0 =A0 =A0 =A0 =A0 if A2 =3D '1' then > =A0 =A0 =A0 =A0 =A0 =A0 State2 <=3D Idle_S; > =A0 =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 =A0 end case; > =A0 =A0 =A0 end if; -- sini > =A0 =A0end if; -- clk > end process; > > If you want to avoid the delay, just assert the output when you > transition into the states in which you want it on. I think it was > Jonathan Bromley that demonstrated a method, using variables, to > describe state machine outputs more easily in a single clocked > process. > > It's not that hard to do, and you don't get latches, ever! > > If you really prefer dual-process state machines, there are proven, > easy ways to avoid latches in them (like default "State <=3D State_NS" > assignments). Quite frankly, I'd prefer the synthesis vendors work on > other optimizations that are more important to quality of results, > than avoiding inferring latches from poorly written RTL code. > > Andy
Hi Andy, "If you really prefer dual-process state machines, there are proven, easy ways to avoid latches in them (like default "State <=3D State_NS" assignments)." Very good suggestions !!! I will follow it in all my designs starting today. Actually I give a default value at head of each of important states, not for full state machine. But your method of one process with turn-on signal delayed by 1 clock is not acceptable to me. That is the fatal fault of one process and the main reason for me to use dual-process method. One may like vegetables and others may like beef and pork. There is no need to compare between two methods, I know, it is a long crusade in VHDL industry. Weng