Thursday, April 30, 2020

Clock Divider Verilog Code

In this post, we will be implementing a Clock Divider circuit in Verilog. This is one of the most important circuits in VLSI as we can generate one reference clock, and then divide that clock to obtain a number of other slower clocks.

Design Problem:
Clock divider is a circuit which can reduce the frequency of a reference clock by any number N.
Example: If I do clock divide by 2, it means frequency of the clock has been reduced by half.
Another way to look at it is that clock divide by 2 means one period of the new clock will fit two periods of the reference clock.

General Logic:
Let us deal with the case where N is even.
Clock divide by N means N posedges of the reference clock must fit in one period of the reference clock. This means the new clock should toggle at the (N/2 + 1)th posedge of the reference clock.
Example:
Let's say divide by 4. So 4 posedges of reference clock will be available in one period of the new clk. This means the new clock toggles at the 3rd posedge of the reference clock.

For N odd, we must also toggle the clock at a negedge, we will not deal with this case here as it is not usually preferred in practical designs.

Verilog Logic:
To count the posedges, we need a counter which after coming out of reset, is initialized to 1. It increments after every posedge. At every cnt = N/2 (or N>>1 as shifter is realized in hardware), the new clock has to toggle and the counter must be reset.

Verilog Code:

module clkdiveven (
 clk,    //reference clk
 rst,
 N,      //divide by N
 out_clk //generated clk
 );

input clk;
input rst;
input [2:0] N;
output out_clk;

reg out_clk, next_out_clk;
reg [2:0] cnt;
reg [2:0] next_cnt;

always @ (posedge clk or negedge rst)
begin
  if(!rst)
  begin
    out_clk <= 1'b0;
    cnt     <= 1'b0;
  end
  else
  begin
    out_clk <= next_out_clk;
    cnt     <= next_cnt;
  end
end

always @ (*)
begin
  if(cnt==(N>>1))
  begin
    next_out_clk = ~out_clk;
    next_cnt     = 1'b1;
  end
  else
  begin
    next_out_clk = out_clk;
    next_cnt     = cnt+1;
  end
end

endmodule

Testbench:

module clkdiveven_tb;
reg clk;
reg rst;
reg [2:0] N;
wire out_clk;

clkdiveven c0(clk,rst,N,out_clk);

always #5 clk=~clk;

initial 
  begin
  clk=1'b1; rst=1'b0; N=3'b010;
  #30 rst=1'b1;
  #70 N=3'b100;
  #500 $finish;
  end
  
endmodule

Simulation Result:

Clock divider simulation waveform
Here, when N = 2 the output frequency is reduced by 2 times and when N = 4, the output frequency is reduced by 4 times.

Here is a clock divider design which works for any integral N (odd and even):
A gating logic is used in this design for power saving.

No comments:

Post a Comment