Loading header...

Clocks, Resets, and PLLs

Clocking discipline is one of the strongest predictors of FPGA design quality. Most mysterious beginner failures come from treating clocks like ordinary signals.

Learning Objectives

You will learn to:

  • use clock enables instead of fabric-generated clocks;
  • choose reset strategies intentionally;
  • understand what PLLs and MMCMs do;
  • recognize generated-clock and reset-release hazards.

Clocks Are Special

FPGAs have dedicated clock routing networks. These networks reduce skew and distribute clocks reliably. Ordinary LUT routing is not a substitute.

Bad beginner pattern:

assign slow_clk = counter[23];
always @(posedge slow_clk) begin
    led <= ~led;
end

Better pattern:

always @(posedge clk) begin
    if (tick_1hz)
        led <= ~led;
end

Use a clock enable pulse while keeping all registers on the real clock.

Clock Enables

reg [26:0] div;
wire tick_1hz = (div == 27'd99_999_999);

always @(posedge clk) begin
    if (tick_1hz)
        div <= 27'd0;
    else
        div <= div + 1'b1;
end

Every register still uses clk. Only the update condition changes.

PLLs and MMCMs

PLL/MMCM blocks generate related clocks from an input clock. They can:

  • multiply frequency;
  • divide frequency;
  • shift phase;
  • reduce jitter in supported modes;
  • provide a locked signal.

Do not release dependent logic until the clock generator is locked and reset synchronization is handled.

Reset Release

Asserting reset asynchronously is often acceptable. Releasing reset asynchronously can cause different registers to leave reset on different clock edges. A common pattern is asynchronous assert, synchronous release.

flowchart LR A["External reset"] --> B["Reset synchronizer"] C["PLL locked"] --> B B --> D["Clean reset inside clock domain"]

Worked Example: Reset with PLL Lock

reg [1:0] rst_pipe = 2'b11;
wire rst_async = external_reset | ~pll_locked;

always @(posedge clk) begin
    if (rst_async)
        rst_pipe <= 2'b11;
    else
        rst_pipe <= {rst_pipe[0], 1'b0};
end

assign rst = rst_pipe[1];

This keeps reset active until the PLL is locked, then releases it synchronously to clk.

Common Mistakes

  • Creating clocks with LUT logic or counter bits.
  • Forgetting to constrain generated clocks.
  • Ignoring PLL locked.
  • Using one asynchronous reset release across multiple clock domains.
  • Resetting datapath registers unnecessarily and hurting routing/timing.

Summary

Use FPGA clock networks for clocks, clock enables for slower behavior, PLLs/MMCMs for real clock generation, and synchronized reset release for each clock domain. Clocking is architecture, not cleanup.

Next: Clock-Domain Crossing.

Further Reading

  • Vendor clocking resource user guides
  • FPGA reset strategy application notes
  • Timing constraints guides for generated clocks

Mind Map

mindmap root((Clocks Resets PLLs)) Core concept Clock drives registers Reset sets known state PLL creates clocks Applications Applications Clock generation Sequencing Checks Design checks Reset sync Lock signal Clock constraints Common mistakes Common mistakes Gated clocks Async reset release