Tutorials‎ > ‎Mojo FPGA Tutorials‎ > ‎

Mojo Clock Generation

**Work In Progress**


Here is my code so far. Looking for feedback as to how to make it better!

Known problems:

Generates warnings for ratios of <5:1 for the clock rate.
Phase shifting generates warnings.



// 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

Comments