1
\$\begingroup\$

I'm trying to generate an 40MHz clock on an 100Mhz FPGA kind of strugle with the Verilog CODE, I rediredted the Clock to a pin to check the 100Mhz:

assign pin1= clock; //gives me an 100MHz clock
assign pin2= ~clock;  //gives me an 100MHz inverse clock

always block

reg clock1;
reg [4:0] prescaler1;

always @(posedge clk) begin
    if(reset==1'b1)begin
        clock1=1'b0;
        prescaler1=2'b0;
    end else begin
        if(prescaler1==2'b01) begin
            clock1=~clock1;
            prescaler1=1'b0;
        end else begin
            prescaler1=prescaler1+1'b1;
            clock1=clock1;
        end
    end
end

gives me 50, 25, 16.66, 12.5MHz depending on the prescaler set to 0, 1, 2, 3

Is there an trick to do it?

Its an Zedboard Zynq-7000 Z-7020 XPS lets you assign 4 PL Fabric Clocks but I believe they have to be multiple of 33MHz.

Whats the difference of ARM_PLL IO_PLL and DRR_PLL

\$\endgroup\$
  • \$\begingroup\$ Does the FPGA have a clock phase locked loop inside \$\endgroup\$ – Andy aka May 28 '15 at 9:07
  • \$\begingroup\$ If there's a PLL, x4 with the PLL to get 400MHz, divide-10 with the prescaler or an external component to get 40MHz? \$\endgroup\$ – Polynomial May 28 '15 at 10:45
  • 1
    \$\begingroup\$ Please give us the FPGA device name. FPGAs have Clock Modifying Blocks (CMBs) like DCMs, PLLs, MMCMs to do this job. All vendors provide IP Core generators to generate a CMB component for your requirements: ClockIn = 100 MHz, ClockOut0 = 40 MHz. \$\endgroup\$ – Paebbels May 28 '15 at 10:56
3
\$\begingroup\$

The simple prescaler you've implemented follows the formula $$ fout = fMaster \div (2 * (1 + prescalerN)) $$ where fMaster is the 100MHz master clock input and prescalerN is the prescaler reload value. There's not a whole-number divisor of (100MHz/2) that produces 40MHz. This is a limitation of implementing the prescaler in general-purpose programmable logic.

Many FPGA include specialized clock generation blocks such as PLL (Phase-Locked Loop). This is a specialized analog circuit implemented in FPGA silicon, which can be configured to run at a faster internal clock than the applied master clock. So the external 100MHz clock might be doubled to 200MHz or maybe up to 400MHz. The PLL uses a control loop principlie similar to what an op amp uses, to accomplish generating a stable higher internal frequency, from a stable lower frequency external reference.

Some Xilinx FPGA have DCM (Digital Clock Manager). Altera calls this kind of thing a "megafunction" if I remember correctly, there should be a megafunction for PLL. Depends on exactly what FPGA you are using. Consult the FPGA's main data sheet.

\$\endgroup\$
3
\$\begingroup\$

If you don't have a PLL, you need a divide by 5 counter (to 20 MHz), a 1.5 cycle delayed version of the same, (use the opposite clock edge for 0.5 cycles) and an XOR gate (with the corrected version, an OR gate will suffice as both signals are never '1' at the same time)

This will give you a 40MHz signal with consistent 40% (but not 50% ... edited!) mark-space ratio.

NB the OR gate will add some skew w.r.t a straight clock division. If your FPGA features DDR registers you can clean that up.

process(clk)
variable count : natural range 0 to 4;
begin
  if rising_edge(clk) then
    if count = 4 then
      count  := 0;
      clk_20 <= '1';
    else
      count  := count + 1;
      clk_20 <= '0';
    end if;
    clk_20d1 <= clk_20;   -- delay, thanks to signal assignment semantics
  end if;
end process;

process(clk)
begin
  if falling_edge(clk) then
    clk_20d15 <= clk_20d1; -- +0.5 cycle delay
  end if;
end process;

clk_40 <= clk20 or clk_20d15;

Should be straightforward to translate into Verilog.

\$\endgroup\$
2
\$\begingroup\$

Yes, there is a trick to do this. It's called fractional clock division and it's often done with a dual modulus pre-scaler.

Here is a web page that gives example code in VHDL (sorry, no verilog): fractional-clock-division-dual-modulus

Using these techniques you'll be able to get a 40Mhz signal out of your 100Mhz clock, but be aware that the jitter will increase and you may end up with a signal that does not has a 50% duty cycle.

Since you're working on a FPGA: Check if your FPGA contains a digital clock manager. These are hardware blocks that can generate a wide range of frequencies out of an existing clock by first multiplying the frequency, then dividing it. You'll get better performance out of a digital clock manager than a hand-written dual modulus prescaler.

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

The best way would be a PLL as mentioned by the other answers - multiply by 4, then divide by 10. You could do x2,/5 but that doesn't get you 50% duty cycle (may not be an issue).


But to add to those, there is a second option if no PLL is available, which is not recommended as it relies on asynchronous logic. It would go something like this:

wire clock2x;
wire clock2xDelay;
assign clock2x = clock100M ^ clock2xDelay;
assign clock2xDelay = ...; //I need to be clock2x delayed by about 5ns

reg [2:0] divider;
always @ (posedge clock2x or posedge reset) begin
  if (reset) begin
    divider <= 3'b0;
  end else if (divider == 3'd4) begin
    divider <= 3'b0;
  end else begin
    divider <= divider + 3'b1
  end
end
assign clock50M = divider[1]; // 40% Duty cycle, 50MHz clock

The above code isn't quite complete - you'll notice the clock2xDelay isn't finished. Basically this is where the interesting bit needs to happen and it will depend on your device. You basically need to add enough delay (through carry chain delay, LUT delays, etc) that the XOR produces a pulse wide enough to not cause minimum pulse width timing errors. The synthesizer also needs to be told not to optimise the delay chain away.

This code is not recommended as the asynchronous delay will vary with temperature and device characteristics and as such will result in a jittery clock.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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