4
\$\begingroup\$

I have a current design where the input clock is 54MHz, but for some part of the design, I can do with a much slower clock.

Is it better design to clock all the "slow" logic (state-machines ect.) with a divided clock?

I was thinking this would achieve lower power consumption, and more relaxed timing constraints, since the period is bigger.

\$\endgroup\$
6
\$\begingroup\$

You can create as many clocks as you want, and you can use PLLs or DCMs to create arbitrary clocks. The question is whether you need to, or if you should be doing it a different way.

I find that I end up running as much logic at a common or "core" clock frequency, say the 54MHz that you are using, but I need to trigger certain processes to run periodically. Say a 100ms debounce, a 10kHz PWM update, a 1s timer tick for wall clock, you get the idea. Instead of generating these clocks, I instead run everything at the core clock frequency and generate arbitrary clock enable signals.

You generally don't want to create divided clocks for several reasons. Logic-generated clocks are jittery, the tools may end up routing these "clock" signals along routing paths intended for logic (since they're generated from logic) and as mentioned above and by others, PLLs and DCMs are much better options if you really need to generate a different clock.

Clock gating is what you want. The device primitives have an additional clock enable signal which "gates" the clock signal, allowing to propagate into the primitive or not. When the clock enable is negated, the FF doesn't see the clock and effectively holds its state as if the clock pulse never occurred. When the clock enable signal is asserted the FF sees the clock normally and things proceed as expected. Clock enables are designed specifically to control an FF's access to its clock and as such don't have issues with generating runt clocks. They also don't take up any additional resources, so use them.

e.g. generating a clock in logic. This is bad, don't do this:

process gen_100ms_clk (clk, rst)
variable ctr: integer range 0 to 5399999;

begin
    if rst = '1' then
        ctr := 0;
        out <= '0';
    elsif rising_edge(clk) then
        if ctr = ctr'high then
            out <= not out;
            ctr := 0;
        else
            ctr := ctr + 1;
        end if;
    end if;
end process gen_100ms_clk;

This code has the out signal toggle state every 100ms; This signal would be a poor choice to use as the clock signal of a new process, such as here:

process do_100ms(out, rst)
begin
    if rising_edge(out) then
        ...
    end if;
end process do_100ms;

This is bad because the FFs in the do_100ms() process are using a signal created through the logic in the gen_100ms_clk() process.

Instead, use a clock enable, as shown here:

process gen_100ms_ce (clk, rst)
variable ctr: integer range 0 to 5399999;

begin
    if rst = '1' then
        ctr := 0;
        out <= '0';
    elsif rising_edge(clk) then
        if ctr = ctr'high then
            out <= '1';
            ctr := 0;
        else
            out <= '0';
            ctr := ctr + 1;
        end if;
    end if;
end process gen_100ms_clk;

Now gen_100ms_ce() creates an out signal that is high for 1T every 100ms. This is a great way to signal to your code that it's time to do something:

process do_100ms(clk, rst)
begin
    if rising_edge(clk) then
        if out = '1' then
            ...
        end if;
    end if;
end process do_100ms;

Now your do_100ms() process is running at the same 54MHz clock as everything else and it uses a proper clock enable to trigger whatever you want to happen every 100ms.

Take a look at the RTL output of your toolset; you'll see that the primitive used in your do_100ms() process will use its clock enable signal.

This method also achieves power savings since there will be large swaths of logic that stay "static" for long amounts of time even though the global clock net is wiggling away at 54MHz in your case. Once every 100ms in my example above, all the clocks which are gated with the 100ms enable become active for 1T and then are static again for another 99.9999815ms. :-) CMOS consumes very little power when it's not changing state, so the only power consumption in the logic with the gated-off clock is in the leakage currents of its logic.

You can extend this into a full-out means of power management. You create clock enables for all the subsystems and your power manager negates the clock enable for whichever subsections you dont' want powered.

\$\endgroup\$
6
  • \$\begingroup\$ Async resets are evil in most digital logic. So are global resets. xilinx.com/support/documentation/white_papers/wp272.pdf \$\endgroup\$
    – user3624
    Jun 17 '13 at 4:44
  • \$\begingroup\$ Async assert, sync clear is a perfectly valid strategy and has served me well over the years. See sunburst-design.com/papers/CummingsSNUG2003Boston_Resets.pdf. Also, most FPGAs have a global reset net which is designed for this kind of task, although I did not talk about a specific global reset in my implementation. \$\endgroup\$
    – akohlsmith
    Jun 17 '13 at 13:57
  • \$\begingroup\$ Some modern FPGAs have gone away from the global reset net. Also, it is possible that with an async reset that you can put state machines into an invalid state when some state bits get reset one clock earlier/later than other bits due to the relatively slow propagation delay/skew of the reset signal. Xilinx/Altera both advise against that. I have this posted on my conf room wall: despair.com/tradition.html (Note: I am NOT calling you stupid. I am saying that "I've always done it that way" is not a valid point.) \$\endgroup\$
    – user3624
    Jun 17 '13 at 14:33
  • \$\begingroup\$ No offense taken. I'm always up to learning better ways, but I am not sure I understand the risks you're describing. Async reset clear is bad, I understand that and don't design for that. Async reset assertion I don't understand the concern over. \$\endgroup\$
    – akohlsmith
    Jun 17 '13 at 15:36
  • \$\begingroup\$ (addendum to my comment) -- minimum reset assertion times are something I did not talk about... perhaps that is what you're referring to when you talk about invalid states due to skew/delays in propagating the reset? \$\endgroup\$
    – akohlsmith
    Jun 17 '13 at 15:37
3
\$\begingroup\$

Let me quote Donald Knuth (his target was software developement but it applies in FPGA too):

Premature optimization is the root of all evil

I wouldn't really pay too much attention to lowering clock until there is a real need. I don't know what FPGA you use, but in case of Xilinx devices, 54 MHz is not very high frequency and XST shouldn't have problem with timing.

I think that in case of very big projects, you could save a lot of synthesis time by optimizing clocking. If it's not the case, don't do it. The same applies to power consumption.

\$\endgroup\$
5
  • \$\begingroup\$ Not to imply anything specific to your answer... but I really hate that phrase. The vast majority of times I hear it are from weak software people who say premature optimization but mean thinking through your problem. It's used as a HUGE excuse for lazy design from people who end up in trouble and have to redesign later. Yes, there's truth in it... but it's really kind of assuming a basic level of competence on the part of the recipients. Not only does it encourage laziness... it's usually delivered with a smug "Donald Knuth > you" attitude. \$\endgroup\$
    – darron
    Jun 17 '13 at 4:32
  • \$\begingroup\$ Yes, I've heard that phrase before, but IMHO I don't think that applies when designing hardware. \$\endgroup\$
    – JakobJ
    Jun 17 '13 at 13:05
  • \$\begingroup\$ @JakobJ I think that it absolutely applies to HW, especially FPGAs and VHDL/Verilog. See my other comment, below. \$\endgroup\$
    – user3624
    Jun 17 '13 at 14:28
  • \$\begingroup\$ @darron There is a huge difference between laziness and what Knuth talked about. You can be smart about your laziness! A lot of that with FPGA's is in knowing what you can and cannot rely on the compiler doing for you. In the OP's Q, not worrying about power consumption and the faster clock speed is a valid approach in the interest of not complicating the design unnecessarily. \$\endgroup\$
    – user3624
    Jun 17 '13 at 14:32
  • \$\begingroup\$ @DavidKessner that's why I put in the "not to imply..." bit. My point is not that the advice isn't valid... it's that in my opinion this quote does more harm than good. It's become one of the most commonly uttered quotes in software, and rarely for the right reasons. \$\endgroup\$
    – darron
    Jun 17 '13 at 14:54
2
\$\begingroup\$

I would say generally no, don't do that. However, only you know what your design constraints and goals are.

The upsides are that PERHAPS you save power and your design's timing constraints may get easier to meet/faster to process. However, this may not be that much different than nearly equivalently designed clock enable logic.

There are big downsides:

  • you're splitting your design into different clock domains. If you're not VERY careful, crossing clock domains can be a real problem. The design may seem to work, but occasionally glitch strangely in exceptionally hard to debug ways. In fact, understanding clock domains and how to manage them is probably the hardest big concept for newcomers to master.

  • using user logic as a clock can cause a lot of skew issues in your design and cause a lot more effort on the part of the synthesis tool. This is because logic routes through the routing fabric (many interconnects -> slow and more variable) instead of dedicated clock lines (few/no interconnects -> fast and less variable). You should either route a generated clock to a clock buffer if possible (to get on a proper clock net BEFORE anything uses it) or use a dedicated clock management block.

  • using a dedicated clock management block would waste a valuable resource and very possibly cost more power than you're saving.

Suggestion:

If you really care about power, design your clock-dividing logic... but use that output as a clock enable for your slow logic. Instead of running a wide counter at full speed, advance a smaller counter using your slower clock enable.

If it's just an idle thought with no real driving need behind it, then don't bother until/unless it becomes a problem. HOWEVER... don't turn this into a blind "best practice". Always leave it in the toolbox as an option.

...

This sounds like a best practices fishing question (which is good, nothing wrong with that)... however, I'd really like to say that generally best practices need to be bound by understanding when they should or should not be applied.

WAY too often, people take a best practice and make it nearly absolute. Should you wear a scuba mask when removing a bolt from a flange? Sounds silly, everyone would say no. Now say the flange is 50 feet underwater. This physical example is super obvious and more than a little ridiculous (Unless it's an XY problem and you should get a sub or an ROV), but the conditions that make something a good or bad idea are often not obvious (especially in engineering).

If you later on find yourself over some power budget or perhaps much more commonly that your synthesis tool can't meet timing... consider splitting logic that doesn't need to be fast off to slower clocks. Don't just beat your head against the wall trying to solve it with a single clock because some people on the internet told you a general answer to your general case question.

\$\endgroup\$
1
\$\begingroup\$

It's certainly possible to use multiple clocks in any current FPGA.

Most have a "digital clock manager" or similar hard-ip block available to generate multiple frequencies from a single input frequency. If this is a relatively straightforward design, it would be a good opportunity to learn how to use the clock management features in your FPGA.

However

  • If you need to have signals connected between the fast clock domain and the slow domain (in either direction) you'll need to be very careful about how you do it.

  • You probably won't gain much in power consumption compared to the alternative case where you use the fast clock everywhere, but some signals just don't switch very often.

An alternative technique instead of routing two clocks, is to have a "phase" signal tied to the ENable pin of the flip-flops in the "slow" section, so that they only operate on every n-th edge of the fast clock. This slows down some of the logic, allows for deeper combinatorial blocks between registers (if you can figure out how to explain to the analysis tool what you're doing), but cleans up most issues with connecting between the fast and slow blocks.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.