一、偶數分頻電路
偶數倍分頻是最簡單的一種分頻模式,完全可通過計數器計數實現。
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