Why Learn Clock Generation? Every sequential design needs a clock, and every testbench has to create one. A modern chip often has many clocks at different frequencies, with different duty cycles and phase relationships, and its testbench must reproduce all of them to check how the design behaves. In this tutorial, you'll learn the properties that describe a clock and build a configurable clock generator for simulation.

Clocks keep the different blocks of a digital design in step with each other. A Verilog clock generator for simulation is a block of code that toggles a signal with a chosen period, duty cycle and phase, using delays. It is a testbench model, not synthesizable hardware: on a real chip, clocks come from oscillators, PLLs and clock dividers.

12 min read | Beginner Level

What You'll Learn

  • The three properties of a clock: period, duty cycle and phase
  • Generate simple clocks in a testbench with always and delays
  • Build a parameterized clock generator with frequency, phase, duty cycle and an enable
  • How `timescale precision affects generated clock periods

Properties of a clock

A clock is described by three properties: its frequency, which sets its period; its duty cycle; and its phase relative to other clocks.

Clock Period

The frequency of a clock is the number of cycles it completes per second, and the period is the time one cycle takes. They are reciprocals: period = 1 / frequency. A 100 MHz clock has a period of 10 ns, and a 400 MHz clock a period of 2.5 ns.

Clock waveform with one full period marked from one rising edge to the next

Clock Duty Cycle

The duty cycle is the fraction of the period during which the clock is high. A 50% duty cycle clock is high for half the period and low for the other half. A 10 ns clock with a 25% duty cycle is high for 2.5 ns and low for 7.5 ns.

Clock waveforms with different duty cycles, showing the high time as a fraction of the period

Clock Phase

Phase describes how far one clock is shifted in time relative to another clock with the same period. One full period is treated as 360 degrees, so a clock shifted by a quarter of its period is 90 degrees out of phase, and one shifted by half a period is 180 degrees out of phase, which is the same as its inverse for a 50% duty cycle.

Two clocks with the same period, the second shifted by a quarter period, showing a 90 degree phase difference
PhaseShift (fraction of period)Shift for a 10 ns clock
0 degrees00 ns
90 degrees1/42.5 ns
180 degrees1/25 ns
270 degrees3/47.5 ns

Simple Clock Generation

Most testbenches need just one or two plain 50% duty cycle clocks. These are generated by toggling a reg after every half period:


`timescale 1ns/1ps

module tb;
  reg clk;

  // Style 1: initialize, then toggle every half period
  initial clk = 0;
  always #5 clk = ~clk;              // 10 ns period, 100 MHz

  // Style 2: the same clock in a single initial block
  // initial begin
  //   clk = 0;
  //   forever #5 clk = ~clk;
  // end
endmodule

The delay is the half period, so a 10 ns clock uses #5. See Verilog Timescale for how the delay units are set.

Verilog Clock Generator

When a testbench needs several clocks with different frequencies, phases or duty cycles, a reusable module is more convenient than separate always blocks. The module below takes three parameters:

  • FREQ - Frequency in kHz
  • PHASE - Phase shift in degrees
  • DUTY - Duty cycle in percent

An enable input starts and stops the clock. When several clock generators share the same enable, they all start from the same moment, which makes their phase relationships easy to control.

Delays in simulation are limited by the precision of the `timescale directive. With `timescale 1ns/1ps, every delay is rounded to the nearest picosecond. A 640000 kHz (640 MHz) clock has a period of exactly 1.5625 ns, which cannot be represented with 1 ps precision, so the generated clock is slightly off frequency. For such clocks, use a finer precision, such as `timescale 1ns/100fs.


`timescale 1ns/1ps

module clock_gen (	input      enable,
  					output reg clk);

  parameter FREQ = 100000;  // in kHZ
  parameter PHASE = 0; 		// in degrees
  parameter DUTY = 50;  	// in percentage

  // Real arithmetic: 1.0 forces floating point, so no precision is lost to integer division
  real clk_pd  		= 1.0/(FREQ * 1e3) * 1e9; 	// convert to ns
  real clk_on  		= DUTY/100.0 * clk_pd;
  real clk_off 		= (100.0 - DUTY)/100.0 * clk_pd;
  real quarter 		= clk_pd/4;
  real start_dly     = quarter * PHASE/90;

  reg start_clk;

  initial begin
    $display("FREQ      = %0d kHz", FREQ);
    $display("PHASE     = %0d deg", PHASE);
    $display("DUTY      = %0d %%",  DUTY);

    $display("PERIOD    = %0.3f ns", clk_pd);
    $display("CLK_ON    = %0.3f ns", clk_on);
    $display("CLK_OFF   = %0.3f ns", clk_off);
    $display("QUARTER   = %0.3f ns", quarter);
    $display("START_DLY = %0.3f ns", start_dly);
  end

  // Initialize variables to zero
  initial begin
    clk <= 0;
    start_clk <= 0;
  end

  // When clock is enabled, delay driving the clock to one in order
  // to achieve the phase effect. start_dly is configured to the
  // correct delay for the configured phase. When enable is 0,
  // allow enough time to complete the current clock period
  always @ (posedge enable or negedge enable) begin
    if (enable) begin
      #(start_dly) start_clk = 1;
    end else begin
      #(start_dly) start_clk = 0;
    end
  end

  // Achieve duty cycle by a skewed clock on/off time and let this
  // run as long as the clocks are turned on.
  always @(posedge start_clk) begin
    if (start_clk) begin
      	clk = 1;

      	while (start_clk) begin
      		#(clk_on)  clk = 0;
    		#(clk_off) clk = 1;
        end

      	clk = 0;
    end
  end
endmodule

How the module works:

  • Timing values: the period is computed in ns from FREQ, then split into on and off times by DUTY. The phase delay is the quarter period scaled by PHASE / 90, so 90 degrees gives one quarter period.
  • Phase: when enable rises, start_clk goes high only after start_dly, so the clock starts late by exactly its phase shift.
  • Duty cycle: the while loop drives the clock high for clk_on and low for clk_off on each pass.
  • Stopping: start_clk is checked once per period, so when enable falls, the clock finishes its current period before stopping, without a shortened pulse.

Synthesis result: None. This module uses # delays and real variables, which synthesis tools ignore or reject. It exists only to drive simulations. In hardware, clocks with specific frequencies and phases are produced by PLLs or clock management blocks, and slower clocks by dividers built from flip-flops.

Quick Check

Q: What are clk_pd, clk_on, clk_off and start_dly for FREQ = 250000, DUTY = 40 and PHASE = 180?

Show Answer

250000 kHz is 250 MHz, so clk_pd = 4 ns. clk_on = 40% of 4 ns = 1.6 ns and clk_off = 2.4 ns. The quarter period is 1 ns, so start_dly = 1 ns x 180 / 90 = 2 ns.

Where are Clock Generators Used?

An SoC testbench typically drives several unrelated clocks at once: a CPU clock, a memory interface clock, peripheral bus clocks and slow real-time clocks. Configurable clock generator models let one testbench run each domain at its real frequency, which is essential for verifying the clock-domain-crossing logic between them.

Testbench with different clock frequencies

Four clock generators run at 100, 200, 400 and 800 MHz, all sharing one enable, which the testbench toggles after random delays.


module tb;
  wire clk1;
  wire clk2;
  wire clk3;
  wire clk4;
  reg  enable;
  reg [7:0] dly;
  integer i;

  clock_gen u0(enable, clk1);                   // Default: 100000 kHz
  clock_gen #(.FREQ(200000)) u1(enable, clk2);
  clock_gen #(.FREQ(400000)) u2(enable, clk3);
  clock_gen #(.FREQ(800000)) u3(enable, clk4);

  initial begin
    enable <= 0;

    for (i = 0; i < 10; i= i+1) begin
      dly = $random;
      #(dly) enable <= ~enable;
      $display("i=%0d dly=%0d", i, dly);
      #50;
    end

    #50 $finish;
  end
endmodule
Waveform of four clocks at 100, 200, 400 and 800 MHz started and stopped by a shared enable
Output
xcelium> run
FREQ      = 100000 kHz
PHASE     = 0 deg
DUTY      = 50 %
PERIOD    = 10.000 ns
CLK_ON    = 5.000 ns
CLK_OFF   = 5.000 ns
QUARTER   = 2.500 ns
START_DLY = 0.000 ns
FREQ      = 200000 kHz
PHASE     = 0 deg
DUTY      = 50 %
PERIOD    = 5.000 ns
CLK_ON    = 2.500 ns
CLK_OFF   = 2.500 ns
QUARTER   = 1.250 ns
START_DLY = 0.000 ns
FREQ      = 400000 kHz
PHASE     = 0 deg
DUTY      = 50 %
PERIOD    = 2.500 ns
CLK_ON    = 1.250 ns
CLK_OFF   = 1.250 ns
QUARTER   = 0.625 ns
START_DLY = 0.000 ns
FREQ      = 800000 kHz
PHASE     = 0 deg
DUTY      = 50 %
PERIOD    = 1.250 ns
CLK_ON    = 0.625 ns
CLK_OFF   = 0.625 ns
QUARTER   = 0.312 ns
START_DLY = 0.000 ns
i=0 dly=36
i=1 dly=129
i=2 dly=9
i=3 dly=99
i=4 dly=13
i=5 dly=141
i=6 dly=101
i=7 dly=18
i=8 dly=1
i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

Each doubling of the frequency halves the period and the on and off times. The simulation ends at 1110 ns: the ten random delays add up to 560 ns, the ten #50 waits to 500 ns, and the final #50 to another 50 ns.

Testbench with different clock phases

Four 100 MHz clocks share the same enable, with phase shifts of 0, 90, 180 and 270 degrees.


module tb;
  wire clk1;
  wire clk2;
  wire clk3;
  wire clk4;
  reg  enable;
  reg [7:0] dly;
  integer i;

  clock_gen u0(enable, clk1);                   // 0 degrees
  clock_gen #(.PHASE(90))  u1(enable, clk2);
  clock_gen #(.PHASE(180)) u2(enable, clk3);
  clock_gen #(.PHASE(270)) u3(enable, clk4);

  initial begin
    enable <= 0;

    for (i = 0; i < 10; i=i+1) begin
      dly = $random;
      #(dly) enable <= ~enable;
      $display("i=%0d dly=%0d", i, dly);
      #50;
    end

    #50 $finish;
  end

endmodule
Waveform of four 100 MHz clocks shifted by 0, 90, 180 and 270 degrees
Output
xcelium> run
FREQ      = 100000 kHz
PHASE     = 0 deg
DUTY      = 50 %
PERIOD    = 10.000 ns
CLK_ON    = 5.000 ns
CLK_OFF   = 5.000 ns
QUARTER   = 2.500 ns
START_DLY = 0.000 ns
FREQ      = 100000 kHz
PHASE     = 90 deg
DUTY      = 50 %
PERIOD    = 10.000 ns
CLK_ON    = 5.000 ns
CLK_OFF   = 5.000 ns
QUARTER   = 2.500 ns
START_DLY = 2.500 ns
FREQ      = 100000 kHz
PHASE     = 180 deg
DUTY      = 50 %
PERIOD    = 10.000 ns
CLK_ON    = 5.000 ns
CLK_OFF   = 5.000 ns
QUARTER   = 2.500 ns
START_DLY = 5.000 ns
FREQ      = 100000 kHz
PHASE     = 270 deg
DUTY      = 50 %
PERIOD    = 10.000 ns
CLK_ON    = 5.000 ns
CLK_OFF   = 5.000 ns
QUARTER   = 2.500 ns
START_DLY = 7.500 ns
i=0 dly=36
i=1 dly=129
i=2 dly=9
i=3 dly=99
i=4 dly=13
i=5 dly=141
i=6 dly=101
i=7 dly=18
i=8 dly=1
i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

The start delays are 0, 2.5, 5 and 7.5 ns, one quarter period apart, matching the phase table above. The 180 degree clock is the inverse of the 0 degree clock.

Phase-Shifted Clocks in Memory Interfaces

Double data rate memory interfaces transfer data on both clock edges, and the receiver samples each bit in the middle of its valid window. To do that, the interface uses a strobe or clock shifted by 90 degrees relative to the data. Testbenches for these interfaces use phase-shifted clock models like this one to check the timing of the capture logic.

Testbench with different duty cycles

Four 100 MHz clocks share the same enable, with duty cycles of 50, 25, 75 and 90 percent.


module tb;
  wire clk1;
  wire clk2;
  wire clk3;
  wire clk4;
  reg  enable;
  reg [7:0] dly;
  integer i;

  clock_gen u0(enable, clk1);                   // Default: 50%
  clock_gen #(.DUTY(25)) u1(enable, clk2);
  clock_gen #(.DUTY(75)) u2(enable, clk3);
  clock_gen #(.DUTY(90)) u3(enable, clk4);

  initial begin
    enable <= 0;

    for (i = 0; i < 10; i= i+1) begin
      dly = $random;
      #(dly) enable <= ~enable;
      $display("i=%0d dly=%0d", i, dly);
      #50;
    end

    #50 $finish;
  end
endmodule
Waveform of four 100 MHz clocks with 50, 25, 75 and 90 percent duty cycles
Output
xcelium> run
FREQ      = 100000 kHz
PHASE     = 0 deg
DUTY      = 50 %
PERIOD    = 10.000 ns
CLK_ON    = 5.000 ns
CLK_OFF   = 5.000 ns
QUARTER   = 2.500 ns
START_DLY = 0.000 ns
FREQ      = 100000 kHz
PHASE     = 0 deg
DUTY      = 25 %
PERIOD    = 10.000 ns
CLK_ON    = 2.500 ns
CLK_OFF   = 7.500 ns
QUARTER   = 2.500 ns
START_DLY = 0.000 ns
FREQ      = 100000 kHz
PHASE     = 0 deg
DUTY      = 75 %
PERIOD    = 10.000 ns
CLK_ON    = 7.500 ns
CLK_OFF   = 2.500 ns
QUARTER   = 2.500 ns
START_DLY = 0.000 ns
FREQ      = 100000 kHz
PHASE     = 0 deg
DUTY      = 90 %
PERIOD    = 10.000 ns
CLK_ON    = 9.000 ns
CLK_OFF   = 1.000 ns
QUARTER   = 2.500 ns
START_DLY = 0.000 ns
i=0 dly=36
i=1 dly=129
i=2 dly=9
i=3 dly=99
i=4 dly=13
i=5 dly=141
i=6 dly=101
i=7 dly=18
i=8 dly=1
i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

All four clocks have the same 10 ns period, but their on and off times differ: the high time is the duty cycle percentage of the period, and the low time is the rest.

Toggle enable to start/stop clocks

The waveform below shows the effect of the shared enable: all clocks stop while it is low and restart when it goes high again. Each clock finishes its current period before stopping, so no clock produces a shortened high or low pulse.

Waveform showing all generated clocks stopping while enable is low and restarting when it goes high

Quick Check

Q: A testbench uses `timescale 1ns/1ns and always #2.5 clk = ~clk; for a 200 MHz clock. What period does it actually produce?

Show Answer

With 1 ns precision, #2.5 is rounded to a whole nanosecond, which most simulators do by rounding to 3, so each half period is 3 ns and the clock runs at 6 ns, about 167 MHz, instead of 5 ns. The precision must be fine enough to represent the half period, for example `timescale 1ns/1ps.

Common Beginner Mistakes

Mistake #1: Toggling an uninitialized clock

Wrong: reg clk; always #5 clk = ~clk;
Right: reg clk; initial clk = 0; always #5 clk = ~clk;

Why? A reg starts as x, and ~x is still x, so the clock never toggles and no clocked logic ever runs. The simulation finishes without errors, but nothing in the design changes.

Mistake #2: Calculating the period with integer division

Wrong: real clk_pd = 1/(FREQ * 1000) * 1e9;
Right: real clk_pd = 1.0/(FREQ * 1e3) * 1e9;

Why? If both operands of the division are integers, Verilog performs integer division, and 1 divided by any number larger than 1 is 0. The period becomes 0 and the clock either never toggles or hangs the simulation. Writing 1.0 forces real arithmetic.

Mistake #3: Timescale precision too coarse for the clock

Wrong: `timescale 1ns/1ns with half periods like 2.5 ns or 0.625 ns
Right: Choose a precision at least as fine as the smallest delay, such as `timescale 1ns/1ps, or finer for clocks like 640 MHz

Why? Delays are rounded to the precision, so the clock runs at the wrong frequency, and on and off times can become unequal. Multiple clocks that should stay aligned drift apart over a long simulation.

Mistake #4: Using a delay-based clock generator in RTL

Wrong: Instantiating clock_gen inside the design to produce an internal clock
Right: Keep delay-based generators in the testbench; in the design, use a PLL or clock management block, or a divider such as a T flip-flop or Mod-N counter

Why? Synthesis ignores # delays and cannot implement real arithmetic, so the module either fails to synthesize or produces logic with no clock at all.

Practice Exercise

Challenge: Two 125 MHz Clocks, 90 Degrees Apart

Without using the clock_gen module, write a testbench that produces two 125 MHz clocks, clk_a and clk_b, with 50% duty cycle, where clk_b lags clk_a by 90 degrees. Use `timescale 1ns/1ps.

Hint

125 MHz has an 8 ns period, so the half period is 4 ns and 90 degrees is a quarter period, 2 ns. Start clk_b's toggling 2 ns later than clk_a's.

Solution

`timescale 1ns/1ps

module tb;
  reg clk_a, clk_b;

  // clk_a: starts at 0 and toggles every 4 ns (8 ns period)
  initial begin
    clk_a = 0;
    forever #4 clk_a = ~clk_a;
  end

  // clk_b: same period, but its toggling starts 2 ns later (90 degrees)
  initial begin
    clk_b = 0;
    #2;
    forever #4 clk_b = ~clk_b;
  end

  initial #100 $finish;
endmodule

clk_a rises at 4, 12, 20 ns and so on, and clk_b rises at 6, 14, 22 ns, always 2 ns later, which is a quarter of the 8 ns period. Changing the initial delay to 4 ns would give 180 degrees, which is simply the inverted clock.

Summary

In this tutorial, you learned:

  • A clock is described by its period (the inverse of its frequency), its duty cycle and its phase
  • One period equals 360 degrees, so 90 degrees of phase is a delay of a quarter period
  • Simple testbench clocks are made with an initialized reg and always #half_period clk = ~clk
  • A parameterized clock generator computes on time, off time and start delay from FREQ, DUTY and PHASE
  • Period calculations need real arithmetic, and the timescale precision must be fine enough for every delay
  • Delay-based clock generators are for simulation only; hardware clocks come from PLLs and dividers
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5
Cron Job Starts