Module for Clock Generation

Projects you are planning or working on with the Mojo
fusedlightning
Posts: 13
Joined: August 4th, 2013, 5:22 pm

Module for Clock Generation

Post by fusedlightning » August 9th, 2013, 9:35 pm

Hey all,

I'm still just getting started with all of this, and am starting to play around with clock frequency generation. I'm in the process of writing a module to generate a sub-frequency, based off of the initial system frequency and a phase term.

This is real rough around the edges, but I thought I would post it to attempt to get feedback and learn something! So please, feel free to pick apart.

People also talk a lot about DLL and PLL units (Delay Locked Loop, Phase Locked Loop?) that might allow non-integer scales, but I wouldn't begin to know how to implement one.

I have an ongoing webpage here documenting my progress on this module. However, I will also include the code in this post:

How I'm calling the module:

Code: Select all

     clock_gen gen_2(.sys_clk(clk), .out_clk(LINE_OUT));
     defparam gen_2.sys_freq = 50000000;
     defparam gen_2.out_freq = 100000;
     defparam gen_2.phase = 90;
The module:

Code: Select all

// Module to generate a clock based off of the system clock and a desired frequency.
// Note: only frequencies that are factors of 2n of the system clock can be generated.
module clock_gen(
    input sys_clk,  // System clock input
     output out_clk  // Generated clock output
    );

    // A register to hold the output value
    reg out_signal;
    assign out_clk = out_signal; // Continuous assignment to the module output
     
    // User-settable parameters to control functionality of the clock
    parameter sys_freq = 0;
    parameter out_freq = 0;
    parameter phase    = 0; // 0->360: Undefined behavior out of this range.
   
    // Internal parameter (Do not set outside of the module!)
    // The frequency scale is the ratio of the input and output frequencies.
    // The scale is divided by two, because each count changes the edge, and
    // two edge changes make a single clock cycle.
    // In order to round to the nearest integer instead of truncating, the value is
    // bitshifted left, scaled, and bitshifted right. The second bitshift
    // right is the /2.
    parameter _internal_freq_scale =
           ((((sys_freq/out_freq) << 1) + 2) >> 2);
   
    // Create a register the proper width to hold a prescale counter
    // NOTE: The use of $clog2 requires that sys_freq and out_freq be
    // determined at compile time.
    reg[($clog2(_internal_freq_scale)-1):0] prescale;
   
    // Initial setup for the clock
    initial begin
        // To set the phase, start the frequency at some fraction of the
        // period.
        // However, as one full count 0->_internal_freq_scale is a half
        //period, we have to
        // do some extra work to get the phase right.
        if (phase < 180) begin
            prescale = _internal_freq_scale -
                        (_internal_freq_scale * phase)/360;
            out_signal = 0;
        end else begin
            prescale = _internal_freq_scale -
                         (_internal_freq_scale * phase)/360;
            out_signal = 1;
        end
    end
   
    // Every edge of the system clock, increment the prescalar. When it hits
    // the proper value, flip the
    always @(posedge sys_clk) begin
        prescale = prescale + 1'b1;
        if (prescale == _internal_freq_scale) begin
            out_signal = ~out_signal;
            prescale = 0;
        end
    end
   
endmodule

MacAttak
Posts: 72
Joined: April 28th, 2013, 1:27 am
Location: Atlanta, GA
Contact:

Re: Module for Clock Generation

Post by MacAttak » August 10th, 2013, 11:53 pm

I think you want to use a DCM/PLL for this. Our chips (LX9) have support for 4 DCMs and 2 PLLs.

When you use these features of the chip, you will get significantly better fan-out characteristics of the derived clock signal. You can also do a lot more things with a DCM or PLL, like phase-shifting the clock / etc. Given any input clock, you can produce a new clock at A/B frequency, where A and B are any number from 1 to 31.

There is a lot of common functionality that both offer - but PLLs support up to six outputs (each with its own frequency) and DCMs support more fine-grained control over phase shifts including dynamic phase shift.

Lots of details here: http://www.xilinx.com/support/documenta ... /ug382.pdf

I haven't tried doing it yet, but I think that is the route that you want to be exploring.

fusedlightning
Posts: 13
Joined: August 4th, 2013, 5:22 pm

Re: Module for Clock Generation

Post by fusedlightning » August 11th, 2013, 8:07 am

Great, thanks.

I'm still trying to find good documentation on the chip functionality, and more importantly how to use them!

Thanks for the pointer, I'll keep looking!

fusedlightning
Posts: 13
Joined: August 4th, 2013, 5:22 pm

Re: Module for Clock Generation

Post by fusedlightning » August 11th, 2013, 8:55 am

Looks like the PLL also has a frequency synthesis module (page 100 of what you linked).

These datasheets are frustrating for me. I'm not sure if I'm not reading them properly, but it's hard for me to get useful information out of them on how to USE a tool like the DLL or PLL!

-Glenn

fusedlightning
Posts: 13
Joined: August 4th, 2013, 5:22 pm

Re: Module for Clock Generation

Post by fusedlightning » August 11th, 2013, 8:57 am


MacAttak
Posts: 72
Joined: April 28th, 2013, 1:27 am
Location: Atlanta, GA
Contact:

Re: Module for Clock Generation

Post by MacAttak » August 11th, 2013, 8:49 pm

Yeah there is tons of information out there, but really hard to sort through it to find an answer (because often you don't even know the right question to be asking in the first place).

And from what I can tell the xilinx forums are very hostile to beginner questions. We pretty much have to stumble around in the dark for a while until we get comfortable enough with the platform. At least people are helpful here (even if this isn't very high-traffic).

fusedlightning
Posts: 13
Joined: August 4th, 2013, 5:22 pm

Re: Module for Clock Generation

Post by fusedlightning » August 12th, 2013, 10:23 pm

Yeah. I'm just glad there's a few other active members.

I'm gonna be moving around for the next few weeks, so I'm not gonna have much time to look at the DLL/PLL situation. I'll report back when I know more though.

I'm also trying to push the Sparkfun forums to get an FPGA section going - if they do, it might be worth moving there for the higher foot traffic.

MacAttak
Posts: 72
Joined: April 28th, 2013, 1:27 am
Location: Atlanta, GA
Contact:

Re: Module for Clock Generation

Post by MacAttak » August 12th, 2013, 11:27 pm

eevblog forums has a LOT of traffic and it is mostly (guessing 90%+) very experienced professional engineers. They have a subforum area for microcontrollers and FPGA's that sees quite a bit of activity, and are usually very quick (and thorough) when answering questions.

http://www.eevblog.com/forum/microcontrollers/

I'd probably look around there before trying to grow something on Sparkfun - which tends to draw a "less than professional" crowd at times.

fusedlightning
Posts: 13
Joined: August 4th, 2013, 5:22 pm

Re: Module for Clock Generation

Post by fusedlightning » August 13th, 2013, 1:37 pm

Great, sounds good. I'll go check them out.

My co-worker keeps telling me I need to keep up with the EEVBlog. Apparently it's good stuff.

MacAttak
Posts: 72
Joined: April 28th, 2013, 1:27 am
Location: Atlanta, GA
Contact:

Re: Module for Clock Generation

Post by MacAttak » August 14th, 2013, 5:40 pm

I was curious so I dug around a little bit, and it seems like this is actually not very difficult at all (and doesn't burn up all those LU's).

In ISE, under the Tools menu, run the Core Generator tool. Create a new Core Generator project (first toolbar button). In the project options, be sure to set the Design Entry / Preferred language to Verilog, the Flow Vendor to ISE, and tell it that you have a Spartan 6 LX9 in TQG144 package with -2 speed grade.

Expand the treeview node named "FPGA Features and Design" and then "Clocking" under that. Click on "Clocking Wizard", and then in the Information pane click the link for "Customize and Generate". This will launch the clocking wizard where you can access all of the DCM/PLL features. Just change the input clock to 50MHz (defaults to 100MHz), and then on the second page of the wizard you can configure up to six output clocks to be derived from that input clock. It won't give you every single arbitrary frequency, and it won't let you divide down into KHz range or lower, but it's pretty handy and easy to use.

Once you finish that wizard it will generate a Verilog file under the ipcore_dir folder - just add this to your design in ISE. It defines a simple module that you can instantiate.

If you want to still have the original clock (dual clocks), then just configure the clocking wizard to output a second clock at the same frequency as the input - this will allow it to ensure that they are phase-aligned with each other.

Post Reply