Verilog Examples - Clock Divide by 4.5


It is possible to generate a clock divided by 4.5 or for that matter any number like N+1/2. It involves some math. In this example we will use a ring counter that counts on the positive edge of clock.

We then use some counters at negative edges. The counters that we need is dictated by Math.

One advantage of the method we present below is that it does not create multilexers and hence is free from glithes. It however does not have 50% duty cycle.

Problem - Write verilog code that has a clock and a reset as input. It has an output that can be called clk_out. The clk_out is also a clock that has a frequency 4.5 times the frequency of the input clock. It has a negative reset input.

Solution -

This is the main code clock.v



  1. module clk_divn (clk,reset, clk_out);
  2.  
  3. input clk;
  4. input reset;
  5. output clk_out;
  6.  
  7. reg [8:0] count;
  8. reg ps_count1,ps_count5,ps_count6 ;
  9.  
  10. /* Counter reset value : 9b000000001 */
  11. /* count is a ring counter */
  12.  
  13. always @( posedge clk or negedge reset)
  14. if (!reset)
  15. count[8:0] <= 9'b000000001;
  16. else
  17. begin
  18. count <= count << 1;
  19. count[0] <= count[8];
  20. end
  21. always @(negedge clk or negedge reset)
  22. if (!reset)
  23. begin
  24. ps_count1 <= 1'b0;
  25. ps_count5 <= 1'b0;
  26. ps_count6 <= 1'b0;
  27. end
  28. else
  29. begin
  30. ps_count1 <= count[0];
  31. ps_count5 <= count[4];
  32. ps_count6 <= count[5];
  33. end
  34.  
  35. // Use this Math to generate an this odd clock divider.
  36.  
  37. assign clk_out = (ps_count5 | ps_count6| count[5])|
  38. (count[0] | count[1] | ps_count1);
  39.  
  40.  
  41. endmodule




Here is the test bench clocktb.v

  1. `timescale 1ns/100ps
  2. module clkdiv3_tb;
  3. reg clk,reset;
  4. wire clk_out;
  5.  
  6. clk_divn t1(clk,reset,clk_out);
  7. initial
  8. clk= 1'b0;
  9. always
  10. #5 clk=~clk;
  11. initial
  12. begin
  13. #6 reset=1'b1;
  14. #6 reset=1'b0;
  15. #6 reset=1'b1;
  16. #500 $finish;
  17. end
  18.  
  19. initial
  20. $monitor("clk=%b,reset=%b,clk_out=%b",clk,reset,clk_out);
  21.  
  22. initial
  23. begin
  24. $dumpfile("clkdiv45_tb.vcd");
  25. $dumpvars(0,clkdiv3_tb);
  26. end
  27. endmodule


Here is the result of the simulation count of the number of positive and negative pulses. for N=7.


Explanation 1. A ring counter is implemmented using

begin
count <= count << 1;
count[0] <= count[8];
end
 


If you look at the counters in the code, you need to check the time periods of the OR of the followin two sets
count[0] | count[1] | ps_count1
and
ps_count5 | ps_count6| count[5]);