Electronic – Handling inferred clocks during RTL Synthesis

clockfpgasynthesisvhdl

I am trying to synthesize a design in VHDL into a ProASIC3 FPGA using the Synplify Pro tool. The synthesis report gives me the following warning on inferred clocks.

@W:MT420 :  | Found inferred clock counter_unit| pstate_inferred_clock[1] with period 10.00ns. Please declare a user-defined clock on object "n:bcu_ins.ctr_ins.pstate[1]"

I traced back to the part of the code where the warning is being generated and the same is reproduced here for reference.

p_fsm_clk : process(reset_n_in, clk_25mhz_in)
begin
    if (reset_n_in = '0') then
        pstate <= s0;
    elsif rising_edge(clk_25mhz_in) then
        pstate <= nstate;
    end if;
end process p_fsm_clk;

p_fsm : process(pstate,restart_ctr,enable_ctr2,sys_fail)
begin
    start_ctr1 <= '0';
    start_ctr2 <= '0';

    case pstate is
        when s0 =>
        --Reset state. All counters are reset
            if (sys_fail = '0' and restart_ctr = '1') then
                nstate <= s1;   --move to start counter1
            else
                nstate <= s0;
            end if;

        when s1 =>
            start_ctr1 <= '1';  --Initiate counter1
            if (restart_ctr = '1') then
            --restart the counters
                start_ctr1 <= '0';  --reset counter1
                nstate <= s1;
            elsif (enable_ctr2 = '1') then
            --move to start counter2
                nstate <= s2;
            else
                nstate <= s1;
            end if;

        when s2 =>
        --Save the counter1 value and start counter2
            start_ctr2 <= '1';  --assert flag to start counter2
            if (restart_ctr = '1') then
            --restart the counters
                nstate <= s1;
            else
                nstate <= s3;
            end if;

        when s3 =>
            start_ctr2 <= '1';
            if (sys_fail = '1') then
                nstate <= s0;
            elsif (restart_ctr = '1') then
            --restart the counters
                nstate <= s1;
            else
                nstate <= s3;
            end if;

        when others =>
            nstate <= s0;

    end case;
end process p_fsm;

--counter1
p_ctr1 : process(reset_n_in, clk_25mhz_in)
begin
    if (reset_n_in = '0') then
        ctr1 <= 0;  --value on reset
    elsif rising_edge(clk_25mhz_in) then
        if (start_ctr1 = '1') then
        --flag is asserted to start counter1
            ctr1 <= ctr1 + 1;   --increment counter
        else
        --flag de-asserted
            ctr1 <= 0;  --reset the counter
        end if;
    end if;
end process p_offset_cnt;

--save the value of counter1
offset_val <= ctr1 when pstate = s2;

The logic contains two counters – ctr1 and ctr2. The counters are run when there are no system failures. In the first phase ctr1 is run, which is then followed by ctr2. ctr1 stops counting when ctr2 is enabled. The value of ctr1 determines how much later is ctr2 started (in terms of 25MHz clock period), referred to as the offset. This offset value is stored to a signal vector, as can be seen in the last line of the code. The state s2 is used for capturing the value of ctr1 before it resets to 0.

offset_val <= ctr1 when pstate = s2;

I realised that this assignment statement is causing the inferred clock in the design (but don’t know why). When I put the same statement inside a clocked process, the inferred clock warning disappears. However, my logic doesn’t work correctly.

I am looking for a few clarifications in this regard.

  1. Why is there an inferred clock on pstate[1] in this design?
  2. Is it alright to have such statements in the design? Does the presence of inferred clocks indicate a bad design practice?
  3. If it not ok to have inferred clocks in the design, how can I fix this by coding the logic differently?
  4. If it is ok to have inferred clocks, how can I let the tool know of it? What period constrain can I provide for such inferred clocks? How can I determine a meaningful period for such inferred clocks?

Best Answer

You have added an FPGA tag, so I will answer from an FPGA perspective. If you are creating an ASIC or using some other flow, a different answer might apply.

1. Why is there an inferred clock on pstate[1] in this design?

offset_val <= ctr1 when pstate = s2;

This line does not describe anything happening when pstate is not s2. This constitutes a gated latch. In any FPGA I have used, this will be implemented by activating a 'latch' mode in a normal flip flop, using the 'clock' pin as the 'gate'. Your gate signal at that point is using clock resource, but ultimately it is derived from another 'data' signal, as opposed to a 'real' clock.

2. Is it alright to have such statements in the design? Does the presence of inferred clocks indicate a bad design practice?

Latches in general should be avoided unless there is a strong reason to have them, because they usually provide poor timing performance, and can more easily result in hazards and races in the design. One example where latches must be used would be if some external interface had to use a level sensitive input of some kind. In your case it looks like it should be quite easy to avoid a latch.

3. If it not ok to have inferred clocks in the design, how can I fix this by coding the logic differently?

Use a clocked process that contains the assignment. This will infer a flip-flop for offset_val. You would have to simulate your design or probe it on board to make sure that the function is equivalent in your particular case, but the basic philosophy in the FPGA should be that any assignment other than simple a <= b and c; or some_vec <= smaller_vec & another_bit; uses a clocked process. Doing this will give you predictable timing results and make it easier to write constraints. There are exceptions, but this should be the starting point.

4. If it is ok to have inferred clocks, how can I let the tool know of it? What period constrain can I provide for such inferred clocks? How can I determine a meaningful period for such inferred clocks?

For the case of an external interface, the level-sensitive input will have some minimum pulse width, and you can use this to create a period constraint that constitutes the worst possible case of how that signal might toggle. For any internal interfaces, I would work to avoid the latch existing at all, but the same technique might apply. By avoiding latches altogether, you avoid having to think about this sort of problem.


In addition to these, the two-process state machine design shown in your code is not necessary. You can put the whole machine and the state transitions into one clocked process. The resulting process would look very similar to your second process above, with everything wrapped in an if (rising_edge(clk)) then, and every occurence of nstate replaced with pstate. You should be able to find existing answers regarding state machine design either here on EE, or over on Stack Overflow's VHDL tag.