user13555519
user13555519

Reputation: 23

A simple clock divider module

I am asked to design simple clock divider circuit for different types of inputs.

I have a enabler [1:0] input and an input clock, and an output named clk_enable.

If enabler=01 then my input clock should be enabled once in 2 clock signals.If enabler=10 then my input should be divided by 4 etc.

I managed to divide my input clock for different cases with using case keyword but for enabler=00 my input clock should be equal to my output clk_enable which i could not manage to do it.

Here is what i tried. I am asking a help for the enabler=00 situation.

module project(input [1:0] enabler,
                            input clock,
                            output reg clk_enable);

reg  [3:0] count,c;
initial begin
count=4'b0000;
c=4'b0000;
end

always @( posedge clock)
    case(enabler)
    2'b00:clk_enable<=clock;
    2'b01:clk_enable<=~clk_enable;
    2'b10:begin
            if (count >= 4'b0100-1)      
                count<=4'b0000;
            else begin 
            count<=count + 4'b0001;
            clk_enable<=(count<(4'b0100 / 2));
            end
            end
    2'b11: begin
            if (count >= 4'b1000-1)      
                count<=4'b0000;
            else begin 
            count<=count + 4'b0001;
            clk_enable<=(count<(4'b1000 / 2));
            end
            end
    endcase                                             
endmodule

Upvotes: 2

Views: 3108

Answers (2)

Mika
Mika

Reputation: 31

This will generate gated pulsed clock with posedge rate matching the div_ratio input. div_ratio output 0 div1 clock (clk as it is) 1 div2 (pulse every 2 pulses of clk) 2 div3 3 div4

This is usually preferable when sampling at negedge of divided clock is not needed If you need 50% duty cycle I can give you another snippet

module clk_div_gated (
    input [1:0] div_ratio,
    input       clk,
    input       rst_n,    // async reset - a must for clock divider
    output      clk_div
);

reg [1:0] cnt;
reg clk_en;

always @(posedge clk or negedge rst_n)
    if (~rst_n)
        cnt    <= 2'h0;
    else
        cnt    <= (cnt == div_ratio)? 2'h0 : cnt + 1'b1;

// clk_en toggled at negedge to prevent glitches on output clock
// This is ok for FPGA, synthesizeable ASIC design must use latch + AND method
always @(negedge clk)
    clk_en <= (cnt == div_ratio);

assign clk_div <= clk & clk_en;

endmodule

Upvotes: 2

asti205
asti205

Reputation: 174

This looks like you have a strong background in software development? :)

My suggestion is that you always make a clean cut between combinational and sequential logic. This includes some thoughts on what part of the design actually has to be sequential and what can be combinational.

For your case, the clock division clearly has to be sequential, since you want to invert the generated CLK signal (frequency f/2, case 0'b01) at each positive edge of the incoming CLK signal (frequency f, case 0'b00). Same is valid for f/4 (case 0'b10). This part needs to be sequential, since you want to invert the previous CLK state...this would cause a cmobinational loop if realized in combinational logic. So triggering on a CLK edge is really necessary here. However, the actual selection of the correct CLK output signal can be combinational. You just want to assign the correct CLK signal to the output CLK.

An implementation of the sequential part could look like:

// frequency division from input CLK --> frequency: f/2
always @(posedge clk  or  negedge rst_neg) begin
    if (rst_neg = 1'b0) begin
        clk_2  <= 1'b0;
    end else begin
        clk_2  <= ~clk_2;
    end
end

// frequency division from first divided CLK --> frequency: f/4
always @(posedge clk_2  or  negedge rst_neg) begin
    if (rst_neg = 1'b0) begin
        clk_ 4 <= 1'b0;
    end else begin
        clk_4  <= ~clk_4;
    end
end

// frequency division from first divided CLK --> frequency: f/8
always @(posedge clk_4  or  negedge rst_neg) begin
    if (rst_neg = 1'b0) begin
        clk_ 8 <= 1'b0;
    end else begin
        clk_8  <= ~clk_8;
    end
end

So this plain sequential logic takes care of generating the divided CLK signals of f/2 and f/4 that you need. I also included reset signals on negative edge, which you usually need. And you spare the counter logic (increments and comparison).

Now we take care of the correct selection with plain combinational logic:

always @(*) begin
    case(enabler)
        2'b00:  clk_enable = clk;
        2'b01:  clk_enable = clk_2;
        2'b10:  clk_enable = clk_4;
        2'b11:  clk_enable = clk_8;
    endcase
end

This is quite close to your hardware description (clk_enable needs to be a reg here).

However, another way for the combinational part would be the following (declare clk_enable as wire):

assign clk_enable = (enabler == 2'b00)  ?  clk
                      : (enabler == 2'b01)  ?  clk_2
                          : (enabler == 2'b10)  ?  clk_4
                              : (enabler == 2'b11)  ?  clk_8;

Upvotes: 0

Related Questions