How to define multi-cycle timing constraints in Lattice iCEcube2 (synplify)

In a design, I have a number of counters that have an enable that is only active every N periods of the clock signal. With only a clock of

200MHz in the timing constraints, the counters are assumed to run at 200MHz and timing fails. As these counters actually run at much lower speed, I know they will work. But how to convince the tools (Lattice iCEcube2) that all is OK?

I am trying to add multi-cycle constraints, but cannot get them to work. The standard iCEcube timing constraints editor can only create multi-cycle from input pin to output pin, and that does not even work. I need to add a multi-cycle constraint on an internal counter. Preferrably with some wildcard, as I have an array of counters, each with a number of bits. Specifying each separtely would require a lot of lines.

One example of a failed path (from the iCEcube timing analyzer) Start protection_inst.filter_array_3_filter_inst.filter_count_1_LC_5_5_1/lcout End protection_inst.filter_array_3_filter_inst.filter_count_5_LC_5_5_5/in3 Reference gen_pll_wc_lattice_pll_inst.wc_lattice_pll_inst_pll/PLLOUTCORE Setup Constraint 5262(p) Path Slack -762(p)

Simply adding this does not work: set_multicycle_path -to [get_cells {protection_inst.filter_array_3_filter_inst.filter_count_5_LC_5_5_5/in3}] 8

Synplify output: protection_inst.filter_array_3_filter_inst.filter_count_5_LC_5_5_5/in3]) (multi path 8) was not applied to the design because none of the '-to' objects specified by the constraint exist in the design

I've tried get_nets and get_pins instead of get_cells, same result. Also tried other parts of the instance names with wildcards, nothing found.

How to specify multi-cycle paths for the feedback of these internal counters?

Reply to
Stef
Loading thread data ...

On 2023-07-11 Stef wrote in comp.arch.fpga:

After some rewriting of the counter code, they now meet timing when running at 200MHz. So all timing even single cycle okay, no immediate need for multi-cycle constraints.

But the question remains valid: how to define multi-cycle constraints? It is a bit absurd to require passing timing for a 200MHz clock when some of these counters only run at a few kHz.

Reply to
Stef

The OP said that it was a counter with enable, and the enable only occured every N cycles, so your statement isn't true.

The enable -> counter-ff needs to meet the requirement, but that signal will tend to feed the last part of the logic, so shouldn't be a problem, the timing limitation being the carry chain from a low bit to a high bit.

Reply to
Richard Damon

Okay, you're both right. :-)

In the counter design I had an enable signal for the clock and since the Lattice hardware has DFFs with an enable input, I _assumed_ this would be used. And as always: Assumption is the mother of all f*ckups.

When examining the P&R result, I found the enable was included in the feedback logic and not as a direct enable signal to the DFF. :-(

The counters need to count up and down and stop at the end points (0 and max). And there is an output signal that switches only at the end points. This was the original counter code:

process(clk, reset) begin if reset = '1' then filter_count <= 0; sig_out <= '0'; elsif rising_edge(clk) and clk_enable = '1' then if sig_in = '1' then if filter_count < count_max then filter_count <= filter_count + 1; else sig_out <= '1'; end if; else if filter_count > 0 then filter_count <= filter_count - 1; else sig_out <= '0'; end if; end if; end if; end process;

This resulted in logic with a DFF with no enable signal and the enable included in the counter feedback logic.

Changing the counter part to this:

if sig_in = '1' then if filter_count = count_max then sig_out <= '1'; else filter_count <= filter_count + 1; end if; else if filter_count = 0 then sig_out <= '0'; else filter_count <= filter_count - 1; end if; end if;

Resulted in using DFFs with an enable signal, which connects to the clk_enable in the code. And as the enable is removed from the feedback logic, this logic is simpler and can now meet the single cycle 200MHz timing as an added bonus.

This shows you indeed have to be very carefull when wanting to use multi-cycle constraints. Make sure the logic is indeed implemented with an actual clock enable on the DFF. But if this is the case and timing of the enable is okay (don't set multi-cycle on that one), this counter could probably handle an even faster clock. If only the tools understood the multi-cycle nature of the counter.

And that brings us to this point:

The lattice tools use synplify, which is used by multiple vendors. So I would expect this syntax not to be vendor specific. Although the signal name mangling after synthesis may vary between vendors?

Al my searches so far turned up only very simple examples like: set_multicycle_path -end -setup -to [get_cells regb] 2

Which I haven't been able to translate to something that will work in my design.

And when I look at the code again, this is just as well. :-)

The sig_in signal can change on every 200MHz clock cycle, so logic handling that signal should pass 200MHz timing. And this is in the counter feedback logic. For the counter to be truly multicycle, sig_in should be passed through a DFF with the same clock enable as well. So be very carefull if I ever figure out how to do multi-cycle constaints. Just keeping everything on max speed timing is at least a safe aproach.

Reply to
Stef

Yes, it is possible to generate code that the enable signal doesn't end up on the fast path, but any compiler that does that without being forced into is very bad, as the natural equations would become a mux on the enable selecting between the current results and the incremented value.

The one way that I can think of to put the enable on the slow path is to make the equations D <= Q + enable, and if that is how you wrote it, you deserve the slowness.

Reply to
Richard Damon

No, his clk_enable will end up at the last block of logic for the flip-flop, (either using an actual enable pin, or the last LUT feeding the flip-flop. My comment was strictly about the timing of the ENABLE signal.

The change improved the logic for the COUNTER part of the logic (since equal to a constant is much easier to compute than a less than comparison).

Its possible that this simplification allowed the compiler to recognize that the enable signal was a simple enable and could use that operation of the Logic Element, and thus be faster (and allowing more counter logic in that last LUT of the Logic Element).

Reply to
Richard Damon

On 2023-07-15 KJ wrote in comp.arch.fpga: ...

...

Thanks for those suggestions. I'll give them a try when I get back in a few weeks.

Reply to
Stef

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.