10
\$\begingroup\$

I want to design a block of combinational logic using VHDL, but occasionally the synthesized result contains an unintentional latch.

What coding guidelines do I need to follow in order to avoid the synthesizer from inferring latches?

Example : in small segment of code, should I use if-else statements?

\$\endgroup\$
1
  • \$\begingroup\$ I wasn't sure what you meant from your example. Please check to make sure the rewording matches your original intent. \$\endgroup\$
    – W5VO
    Aug 11, 2011 at 14:30

4 Answers 4

13
\$\begingroup\$

To avoid latches, you need to make sure all of your outputs are assigned at all possible branches of the code.

for example,

if a = '1' then
   b(0) <= '1';
else
   b(1 downto 0) <= "00";
end if;

would generate a latch, because in the first condition, the value of b(1) is not specified, so the compiler decided you wanted to keep the previous value of b(1) there. One way to write this that would not generate a latch is:

if a = '1' then
   b <= prev_b;
   b(0) <= '1';
else
   b(1 downto 0) <= "00";
end if;

...

if rising_edge (clk)
    prev_b <= b;
end if;

Here you explicitly state that b should retain it's old value, and then overwrite b(0) with the new value.

Another way is to give b a default value, as in @TomiJ's answer.

If you post the code you are getting a latch on, we could help you find the specific reason.

\$\endgroup\$
2
  • \$\begingroup\$ I don't think your approach of b <= b will avoid a latch, as it still requires preserving the state of the signal. \$\endgroup\$ Aug 11, 2011 at 15:36
  • \$\begingroup\$ You may be right; I am too used to clocked logic. I will edit. \$\endgroup\$
    – fbo
    Aug 11, 2011 at 18:12
7
\$\begingroup\$

Four rules to avoid latches:

  • Don't read from the signals to which you write.
  • Have a correct sensitivity list (all signals that you read should be in the sensitivity list)
  • Make sure that all signals to which your write are assigned in every path. (for example: in each branch of an if-else-statement)
  • For processes which use variable, make sure every variable is initialized a default value before reading it (in another variable or signal ).

Additionally, if you have several combinational processes, make sure you don't create a loop.

Several coding styles can help you stick to these rules, for example the style in @TomiJ's answer. As @Martin Thompson points out, it may be better to avoid combinational logic all together. Put everything in a clocked process instead.

\$\endgroup\$
3
  • \$\begingroup\$ +1 Nice set of rules. Would you agree that your rule #2 (about the sensitivity list) is actually important for ensuring consistent results between synthesis and simulations, but does not really make a difference about the inference of latches? \$\endgroup\$
    – rick
    Nov 3, 2014 at 6:57
  • \$\begingroup\$ @rick AFAIK, there is no guarantee of what a synthesis tool will do with incomplete sensitivity lists. The IEEE standard for VHDL Synthesis (1076.6-1999) states that: "The process sensitivity list shall contain all signals read within the process statement. Processes with incomplete sensitivity lists are not supported." That said, I know that certain synthesis tools (perhaps all?) accept incomplete sensitivity lists, but simply ignore the sensitivity list all together. If you would rely on that behavior instead of the stricter IEEE standard, I guess your statement would be correct. \$\endgroup\$
    – Philippe
    Nov 4, 2014 at 19:25
  • \$\begingroup\$ Thanks, that sounds right, it would make my model non-compliant with that standard. It just got my curiosity because all synthesis tools I've seen so far ignore the sensitivity list, but I've heard rumors that some could infer latches. \$\endgroup\$
    – rick
    Nov 5, 2014 at 6:32
6
\$\begingroup\$

If you are using processes for combinational logic (and I advise against it for just this reason) then make sure every path through the process assigns something to every signal that the process drives. None of the outputs can be dependent on any of the outputs from "last time" the process ran.

Otherwise you infer a latch because the next time the process is scheduled it has to keep the value of the signal which didn't get a new value last time around.

I prefer to keep purely combinational logic as continuous assignments, and use processes for clocked logic, then I don't get latches.

\$\endgroup\$
4
\$\begingroup\$

As has been pointed out by @fbo and @Martin Thompson, you need to ensure every signal driven by the process is assigned some value in every branch of the process, and that value must not be dependent on the previous state of any of the outputs of the process.

The easiest way to ensure this is to assign some default value to each output at the very beginning of the process, for example (co-opting fbo's example):

COMBO: process(a)
begin
    b <= (others => '0'); -- Assign default value to b
    if a = '1' then
        b(0) <= '1';
    else
        b(1 downto 0) <= "00";
    end if;
end process COMBO;
\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is a good method that I often use. Sometimes though, a latch warning can indicate to you that you forgot to assign some bits, whereas this method might make the bug harder to find. For example, if you were assigning all the bits of a wide signal separately, and accidently miscounted. \$\endgroup\$
    – fbo
    Aug 11, 2011 at 18:20
  • 2
    \$\begingroup\$ Only in a combinatorial process. In a clocked process, you infer a flipflop, which may be exactly what you want. \$\endgroup\$ Aug 16, 2011 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy