一、偶数分频电路

  偶数倍分频是最简单的一种分频模式,完全可通过计数器计数实现。

 1 //////////////////////////////////////////////////////////////////////////////////
 2 // 偶数分频电路
 3 // 这个分频模块适用于待分频时钟和目标时钟的频率呈整倍数关系
 4 // 通过改变cnt_values确定是N分频,cnt_values应该等于N/2-1,以16分频为例,cnt_values=7;
 5 
 6 module clk_div_even(
 7     clk_in,
 8     reset,
 9     clk_out
10     );
11     
12 input       clk_in;
13 input       reset;
14 output      clk_out;
15 
16 reg             clk_out;
17 reg    [15:0]   cnt;
18 
19 parameter       cnt_values = 'd7;
20 
21 always @ ( posedge clk_in ) begin
22     if ( reset ) begin
23         cnt <= 16'b0;
24         clk_out <= 1'b0;
25         end
26     else if ( cnt == cnt_values ) begin
27         cnt <= 16'b0;
28         clk_out <= ~clk_out;
29         end
30     else begin
31         cnt <= cnt + 1'b1;
32         clk_out <= clk_out;
33         end
34     end
35         
36 endmodule

 

二、奇数分频电路

  相较于偶数倍分频,奇数倍分频要复杂一些。奇数倍分频有多种方法,下面介绍错位“异或”法。

 1 //////////////////////////////////////////////////////////////////////////////////
 2 // 奇数分频电路
 3 // 这个分频模块适用于待分频时钟和目标时钟的频率呈整倍奇数关系
 4 // 通过相或运算实现50%占空比的奇数N分频,N=cnt_values;
 5 
 6 module clk_div_odd(
 7     clk_in,
 8     reset,
 9     clk_out
10     );
11     
12 input       clk_in;
13 input       reset;
14 output      clk_out;
15 
16 reg    [15:0]   cnt_p, cnt_n;
17 reg    [15:0]   cnt_values = 'd3;
18 reg             clk_p, clk_n;
19 
20 always @ ( posedge clk_in ) begin
21     if ( reset ) begin
22         cnt_p <= 16'b0;
23         clk_p <= 1'b0;
24         end
25     else if ( cnt_p == 16'b0 ) begin
26         cnt_p <= cnt_p + 16'b1;
27         //cnt_p <= 16'b0;
28         clk_p <= ~clk_p;
29         end
30         
31     else if ( cnt_p == (cnt_values - 16'b1)/2 ) begin
32         cnt_p <= cnt_p + 16'b1;
33         //cnt_p <= 16'b0;
34         clk_p <= ~clk_p;
35         end
36     else if ( cnt_p == (cnt_values - 16'b1))begin
37         cnt_p <= 16'b0;
38         //cnt_p <= cnt_p + 16'b1;
39         clk_p <= clk_p;
40         end
41     else begin
42         cnt_p <= cnt_p + 16'b1;
43         clk_p <= clk_p;
44         end
45     end
46         
47 
48 always @ ( negedge clk_in ) begin
49     if ( reset ) begin
50         cnt_n <= 16'b0;
51         clk_n <= 1'b0;
52         end
53     else if ( cnt_n == 16'b0 ) begin
54         cnt_n <= cnt_n + 16'b1;
55         //cnt_p <= 16'b0;
56         clk_n <= ~clk_n;
57         end
58     else if ( cnt_n == (cnt_values - 16'b1)/2 ) begin
59         cnt_n <= cnt_n + 16'b1;
60         //cnt_p <= 16'b0;
61         clk_n <= ~clk_n;
62         end
63     else if ( cnt_n == (cnt_values - 16'b1))begin
64         cnt_n <= 16'b0;
65         //cnt_p <= cnt_p + 16'b1;
66         clk_n <= clk_n;
67         end
68     else begin
69         cnt_n <= cnt_n + 16'b1;
70         clk_n <= clk_n;
71         end
72     end
73 
74 
75 assign clk_out = clk_p | clk_n;         //两个占空比非50%的时钟相或之后,得到占空比50%的时钟
76     
77 endmodule

 

三、仿真

附上tb文件

 1 module odd_sim;
 2 
 3 
 4 reg     clk_in;
 5 reg     reset;
 6 wire    clk_out;
 7 
 8 initial
 9 begin
10     clk_in = 1'b0;
11     reset = 1'b1;
12     
13     #1000
14     reset = 1'b0;
15     
16 end
17 
18 always #50 clk_in = ~clk_in;       //给时钟激励,即50ns翻转一次,10MHz
19 
20 clk_div_odd        odd_sim(
21     .clk_in         (clk_in),
22     .reset          (reset),
23     .clk_out        (clk_out)          
24 );
25 endmodule