website statistics

Making an arbitrary frequency clock in VHDL and VerilogΒΆ

Sometimes I need to generate a clock at a lower frequency than the main clock driving the FPGA. If the ratio of the frequencies is a power of 2, the logic is easy. If the ratio is an integer N, then a divide-by-N counter is only a little harder. But if the ratio isn’t an integer, a little (and I mean a little) math is required.

Note that the new clock will have lots of jitter: there’s no escaping that. But it will have no drift, and for some applications that’s what counts.

If you have a clock A at frequency a, and want to make a clock B at some lower frequency b (that is, b < a). Start with a counter d that accumulates (b / a) for every tick of A. As soon as d crosses 1, make a tick on clock B:

d = 0;
forever {
  Wait for clock A.
  if (d < 1) {
    d += (b/a);
  } else {
    d += (b/a) - 1;             /* getting here means tick for clock B */
  }
}

but comparison against zero is easier, so subtract 1 from d:

d = 0;
forever {
  Wait for clock A.
  if (d < 0) {
    d += (b/a);
  } else {
    d += (b/a) - 1;             /* getting here means tick for clock B */
  }
}

Up until now, the loop has been assuming that the variable d and fraction (b/a) are being held at infinite precision. To represent them as integers instead, multiply everything by a:

d = 0;
forever {
  Wait for clock A.
  if (d < 0) {
    d += b;
  } else {
    d += b - a;                 /* getting here means tick for clock B */
  }
}

For example: your system is running off a 14.1523MHz clock, and you need to generate a 24Hz clock.

So a=14152300 and b=24:

d = 0;
forever {
  Wait for clock A.
  if (d < 0) {
    d += 24;
  } else {
    d += 24 - 14152300;                 /* getting here means tick for clock B */
  }
}

For a hardware implementation I need to know how many bits are needed for d: here it’s 24 bits to hold the largest value (-14152300) plus one more bit for the sign. In VHDL this looks like:

signal d, dInc, dN : std_logic_vector(24 downto 0);

process (d)
begin
  if (d(24) = '1') then
    dInc <= "0000000000000000000011000";    --  (24)
  else
    dInc <= "1001010000000110110101100";    --  (24 - 14152300)
  end if;
end process;

dN <= d + dInc;

process
begin
  wait until A'event and A = '1';
  d <= dN;
  -- clock B tick whenever d(24) is zero
end process;

And in Verilog:

reg [24:0] d;
wire [24:0] dInc = d[24] ? (24) : (24 - 14152300);
wire [24:0] dN = d + dInc;
always @(posedge sys_clk_i)
begin
  d = dN;
end
wire b_clk = ~d[24];  // clock B tick whenever d[24] is zero

For another example of the clock divider in use, see Simple transmit-only UART in Verilog.

Note

Neal Galbo points out that by reducing the fractions you can save some bits in the counter.

Taking the above example of 24Hz from 14.1523 MHz. Since

\frac{24}{14152300} = \frac{6}{3538075}

you can use these numbers and have a 23 bit counter:

reg [22:0] d;
wire [22:0] dInc = d[22] ? (6) : (6 - 3538075);
wire b_clk = ~d[22];

Doing the same with the UART means that it only needs 15 bits for the divider, instead of 29.

A handy way of reducing fractions is to use the Python fractions module, e.g.:

>>> from fractions import Fraction
>>> Fraction(24, 14152300)
Fraction(6, 3538075)

More VHDL, Verilog and FPGA notes.