一、偶数分频电路
偶数倍分频是最简单的一种分频模式,完全可通过计数器计数实现。
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