How to infer which features of a state machine dominate timing? - Page 1
Forum section: electronics / general

author: jbb
author_rank: Super Contributor
timestamp: April 26, 2025, 10:21:31 am
content: Hi allI'm doing an FPGA design for work, and am having trouble making timing closure. I'm starting my project with the most fiddly logic, and have already:started with a big complicated all-in-one finite state machinesplit the big state machine into smaller parts: a medium sized state machine and a number of smaller state machinesremoved some nice-to-have featured from the main FSM - they can be done using C code in the soft core microprocessorBut I'm still not meeting timing. Before I go adding pipelining everywhere, I'd like to know...Does anyone have some guidelines for estimating which parts of a finite state machine contribute to the longest time delays?

author: tggzzz
author_rank: Super Contributor
timestamp: April 26, 2025, 10:31:59 am
content: How are you coding your state machine?Firstly, always start with all external inputs having been synchronised to the FSM's clock.The traditional technique is to have two processes. One process is very simplesynchronousprocess with only the FSM state register. The other is anasynchronousprocess containing only the logic that determines what the next state will be, based on the current FSM state and the inputs.With that it is easy to determine which path is causing the worst case timing.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 26, 2025, 01:41:19 pm
content: It's hard to say what you mean by "splitting" it into "smaller parts". If the number of logic levels is the same, then it may be easier to read but it won't change anything in terms of timing.Your only bet to meet timing is to reduce the number of logic levels.Have you looked at the timing analysis? That's what it's made for. While not always easy to parse, it will show you which paths don't meet timing and the corresponding number of logic levels. If you don't use timing analysis, you're shooting in the dark.

author: jbb
author_rank: Super Contributor
timestamp: April 26, 2025, 07:48:10 pm
content: ThanksQuote from: tggzzz on April 26, 2025, 10:31:59 amAlready done that.Quote from: tggzzz on April 26, 2025, 10:31:59 amRight now it’s all-in one: the logic and assignments are all done in analways @(posedge clk)block. I find it easier to prototype this way but the code’s a bit messy in places.Quote from: SiliconWizard on April 26, 2025, 01:41:19 pmThat’s fair. In brief, I have made 3 smaller state machines which wait in IDLE for a something_go signal from the main state machine. They then assert something_busy while working on their job (for example, loading a shift register with a preset value). The main state machine waits for the something_busy signal to clear before resuming operation. …… on further thought, the something_busy signal is combinatorial so that could be part of my problem.Quote from: SiliconWizard on April 26, 2025, 01:41:19 pmI haven’t looked in detail yet.I guess my next steps are first to dig into the timing report and second to convert my state machine into the traditional (separate combinatorial logic block and synchronous register block) state machine form. As it happens, that’s my bosses preferred style, so I won’t get any argument from that quarter.Once I’ve got the state machine into the traditional form, is it a matter of looking for the longest and most complex logic expressions?Edit: I’ve got some interface signals (registered) which are only relevant in some states. I’ve been assigning them to X (unknown) when they aren’t valid. Does anyone know if that helps ease the difficulty for the synthesiser?

author: glenenglish
author_rank: Frequent Contributor
timestamp: April 26, 2025, 10:01:04 pm
content: take a look at the timing report and the synthesised schematic.They will tell you what you need to optimize or change.Can you slow the clock ? can you use a multicycle timing constraint ? Multicycles are a way out of complex logic corners....When you are relatviely inexperienced with an archtecture, it's not always clear as you write how much each decision is costing you in logic levels.After some experience, you get to know what is hard...

author: jbb
author_rank: Super Contributor
timestamp: April 27, 2025, 03:23:12 am
content: I’ll take a look at the detailed timing report when I get back to work.On clock rate: I need to hit some precise clock ratios, so the only clock reduction I could pursue is a full halving of the clock rate which I’d rather not do.On multiclock: that’s a good idea to keep in my back pocket.

author: glenenglish
author_rank: Frequent Contributor
timestamp: April 27, 2025, 03:34:30 am
content: post the timing report here if you feel like it.

author: jbb
author_rank: Super Contributor
timestamp: April 29, 2025, 07:48:04 am
content: The following is more ‘my notes and progress’ than a question; feel free to skip it.So, I have improved my situation a bit. Unfortunately I now realise I should have documented how f_max changed for each step, but I forgot…I rewrote my main state machine to separate the asynchronous combinatorial logic from the synchronous register assignment. This revealed a really dense block of logic related to an intricate feature.After talking to the boss we decided (OK, he told me to) remove the intricate but ultimately undesirable feature, which let me both simplify the main state machine a little more and prune down the aforementioned dense block of logic.I also rewrote my driver a bit to explicitly push the final output registers all the way to the IO flip flops (which will be important for the PCBA-level timing later).This all netted me an improvement from “fails timing by 10%” to “fails timing by 5%”. I’m getting closer…Then I opened up the timing analyzer and, armed with a couple of YouTube training seminars and approximately 80% of a clue, got it to spit out the 10 worst timing paths. Of these, 4 are related to some address generation logic and 6 are related to a specific sub-task state machine.I can simplify the address generation logic a little or, if that fails, add a pipeline stage.It turns out the sub-task state machine has a long combinatorial chain I hadn’t thought about properly.I’m pretty confident I can break that chain up. And, thankfully, using a sub-task state machine means my modifications here won’t blow up the timing closure of the main state machine.

author: zapta
author_rank: Super Contributor
timestamp: April 29, 2025, 05:29:09 pm
content: Is it safe to achieve exactly the target clock speed or is there a rule of thumb of having a safety margin of X percents?

author: hamster_nz
author_rank: Super Contributor
timestamp: April 30, 2025, 04:01:29 am
content: Quote from: zapta on April 29, 2025, 05:29:09 pmIf it passes timing, then all is good. A 0.000 ns slack is as good as 1.0ns (i.e. guaranteed to work across the part's specified voltage/temperature range).FWIW, I regularly use test images that have failed timing by a small margin during development (e.g. failed by 100ps or less in a 2.5ns clock domain) and they work just fine - they never go out into the field though.Oh, and every tight timing early in development is a bad sign. Things only get worse as more logic gets added.

author: jbb
author_rank: Super Contributor
timestamp: April 30, 2025, 06:51:56 am
content: Quote from: hamster_nz on April 30, 2025, 04:01:29 amYes, I’m feeling a little nervous about that…I guess that means I should be trying to meet timing easily; maybe I should do both the pipelining and state machine re-jigging I mentioned in a prior post.Thankfully, most of the design will run in a slower clock domain (which does mean I’ll need clock domain crossing stuff).

author: glenenglish
author_rank: Frequent Contributor
timestamp: April 30, 2025, 08:21:32 am
content: Hamster said"Oh, and every tight timing early in development is a bad sign. Things only get worse as more logic gets added."AMEN ! That is very good advice.

author: AndyC_772
author_rank: Super Contributor
timestamp: April 30, 2025, 08:35:14 am
content: Since you're already close in terms of timing, it might be worth checking your synthesis tool to see if it has options to trade speed for area or compilation time. Look for "fitter effort" or similar wording.As an aside, I used to find that Quartus (Altera) gave up too easily. If I said I needed a clock to be, say, 100 MHz, then it would fail and say it only achieved 96. But if I then changed the .sdc file to make the clock speed 110 MHz, then it would achieve over 100. It still said this was a timing fail, of course, but the computed fmax was greater than it actually needed to be, so that's OK. It just needed a little incentive to try harder!

author: tggzzz
author_rank: Super Contributor
timestamp: April 30, 2025, 10:54:09 am
content: Quote from: jbb on April 30, 2025, 06:51:56 amNot necessarily. A good design will be specified in a way so that if there is "nothing to do" or "no change required" in one or more clock cycles, then nothing will change.No, that doesn't mean a gated clock!The main potential benefit of significantly slower clocks is reduced power dissipation, but that's usually an optimisation.

author: nctnico
author_rank: Super Contributor
timestamp: April 30, 2025, 04:38:49 pm
content: A few generic remarks:- Let the synthesizer work out which encoding to use (one hot or multiple bits)- Make sure to have signals the state machine state changes depend on use as least signals as possible. What can help is to combine signals into a single signal on which a state change depends. Ofcourse this means the state change will happen one cycle later but this can reduce the amount of logic levels. It is a form of pipelining.

author: zapta
author_rank: Super Contributor
timestamp: April 30, 2025, 05:05:35 pm
content: Quote from: tggzzz on April 30, 2025, 10:54:09 amThis may result in false timing errors, right? Since the tool chain computes timing to the next high speed clock.

author: nctnico
author_rank: Super Contributor
timestamp: April 30, 2025, 05:55:17 pm
content: Quote from: zapta on April 30, 2025, 05:05:35 pmIndeed. Even though it is possible to tell the analyser some signals do not change every clock cycle, doing this is extremely tedious and error prone. I'd strongly advise against doing this. A better solution is to run big chunks of logic at lower clock rates.

author: glenenglish
author_rank: Frequent Contributor
timestamp: April 30, 2025, 09:00:10 pm
content: For algorithms executed with slow clocks, like, 20 MHz, I've seen HLS generate 50 LUTs deep.... Got the job done...

author: jbb
author_rank: Super Contributor
timestamp: May 01, 2025, 03:35:28 am
content: So I rewrote the smaller state machine which was wrecking my timing. It now has some more states (6 instead of 3) but the logic for each individual state is much simpler.I’m now getting f_max 14% higher than my requirement.Thanks for the help everyone.

author: tggzzz
author_rank: Super Contributor
timestamp: May 01, 2025, 09:54:30 am
content: Quote from: jbb on May 01, 2025, 03:35:28 amNext question...When a new requirement arrives or a bug is found, which FSM would be easier to quickly andcorrectlychange?

author: jbb
author_rank: Super Contributor
timestamp: May 01, 2025, 07:25:18 pm
content: Oh, definitely the new one. The logic is much clearer.

author: tggzzz
author_rank: Super Contributor
timestamp: May 01, 2025, 08:21:09 pm
content: Quote from: jbb on May 01, 2025, 07:25:18 pmThat is what I hoped and expected."A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."Antoine de Saint-Exupery