OpenCores
no use no use 1/1 no use no use
VHDL: Issues With Asynchronous Signals and Inferred Laches
by Jason63 on Nov 17, 2011
Jason63
Posts: 2
Joined: Apr 7, 2011
Last seen: Jun 30, 2016
Hi,

I've written some code for a CPLD to perform the functions of a frequency counter. The code is working fine, but I'm getting some warnings about inferred latches. I understand what is going on, but I'm not sure if there is a better way to do it. Here is the relevant code snippet:

-- port ( fin : in STD_LOGIC );				-- signal to be measured
-- signal clk_gate STD_LOGIC;				-- gate clock
-- signal count_shadow_l UNSIGNED(15 downto 0);		-- holds last full value of count
-- signal count_shadow_h UNSIGNED(15 downto 0);

process(fin,clk_gate)
    variable clk_edge : STD_LOGIC := '1';               -- edge detection
    variable count_l : UNSIGNED(15 downto 0);
    variable count_h : UNSIGNED(15 downto 0);
        begin
        if (clk_gate='1' and clk_edge='1') then
            clk_edge :='0';                     -- only reset once per gate period
            count_shadow_l  '0');         -- reset counter
            count_h := (others => '0');
        elsif (clk_gate='0' and clk_edge='0') then
            clk_edge := '1';                    -- enable edge detection
        elsif rising_edge(fin) then
            if count /= 65536 then
                count_l := count_l + 1;         -- increment low word
            else
                count_l := 0;
                count_h := count_h + 1;         -- increment high word
            end if;
        end if;
end process;

The compiler warns me that clk_edge and count_shadow_* have inferred latches associated with them, but I actually want this behavior. The problem stems from the fact that I'm dealing with two asynchronous inputs and I need to change one output in response to one input, but not the other. Otherwise I would just split it apart into two separate processes.

I initially tried to write the code to be synchronous with the input fin like this:

process
        variable clk_edge : STD_LOGIC := '1';
        variable count_l : UNSIGNED(15 downto 0);
        variable count_h : UNSIGNED(15 downto 0);	
        begin
            wait until rising_edge(fin);
                if (clk_gate='1' and clk_edge='1') then
                    clk_edge := '0';
                    count_shadow_l  '0');
                    count_h := (others => '0');
                else
                    if count /= 65536 then
                        count_l := count_l + 1;
                    else
                        count_l := 0;
                        count_h := count_h + 1;
                    end if;
                    if (clk_gate='0' and clk_edge='0') then
                        clk_edge := '1';
                    end if;
                end if;
end process;

But when I did this, I noticed that occasionally count_h would not be reset in initial if statement. I discovered this by hooking up a logic analyzer to the output and could see that every now and then count would fail to reset to zeros at the same time clk_edge was set to '0' (clk_edge was always set to '0' successfully).

I realize that the original (synchronous) code also has a the same inferred latches in it and that perhaps this is related to the above not always working correctly, but it's not clear to me how to eliminate them because I can't change count_shadow_* in the outermost else statement and count_h should only change when count_l rolls over.

Now the first piece of code works fine with the inferred latches -- I've run it for extended periods of time with the logic analyzer set to trigger on any failures and I never noticed any problems. However, I would love to know how to get rid of the inferred latches which everyone tells me are evidence of bad design. I'm even more curious as to what is going on in the second piece of code that is causing the glitches I describe above and how it might be fixed.

--
Jason
RE: VHDL: Issues With Asynchronous Signals and Inferred Laches
by Jason63 on Nov 18, 2011
Jason63
Posts: 2
Joined: Apr 7, 2011
Last seen: Jun 30, 2016

My apologies for the errors in formatting in the above code. The forum software here doesn't support [code] tags so I attempted to format the code using HTML, and I see that is has messed up portions of the code as a result.

In particular, the first if statement in both code snippets should look like this:

        if (clk_gate='1' and clk_edge='1') then
            clk_edge :='0';				-- only reset once per gate period
            count_shadow_l  {= count_l;			-- save current count
            count_shadow_h {= count_h;
            count_l := (others => '0');			-- reset counter
            count_h := (others => '0');

Where I've replace the signal assignment characters with {= so that they are not mis-interpreted as HTML.

Also, the constant 65536 should be 65535 -- that was a typo on my part.

Sorry for any confusion I may have cause from this.

-- Jason
no use no use 1/1 no use no use
© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.