一 、占空比50%的任意奇數分頻
如果要實現占空比為50%的三分頻時鍾,可以通過待分頻時鍾下降沿觸發計數,和上升沿同樣的方法計數進行三分頻,然后下降沿產生的三分頻時鍾和上升沿產生的時鍾進行相或運算,即可得到占空比為50%的三分頻時鍾。這種方法可以實現任意的奇數分頻。歸類為一般的方法為:對於實現占空比為50%的N倍奇數分頻,首先進行上升沿觸發進行模N計數,計數選定到某一個值進行輸出時鍾翻轉,然后經過(N-1)/2再次進行翻轉得到一個占空比非50%奇數n分頻時鍾。再者同時進行下降沿觸發的模N計數,到和上升沿觸發輸出時鍾翻轉選定值相同值時,進行輸出時鍾時鍾翻轉,同樣經過(N-1)/2時,輸出時鍾再次翻轉生成占空比非50%的奇數n分頻時鍾。兩個占空比非50%的n分頻時鍾相或運算,得到占空比為50%的奇數n分頻時鍾。
1 /********************************************************************************* 2 * Company : 3 * Engineer : 空氣微涼 4 * 5 * Create Date : 00:00:00 22/03/2013 6 * Design Name : 7 * Module Name : 8 * Project Name : 9 * Target Devices : 10 * Tool versions : 11 * Description : 12 * http://www.cnblogs.com/kongqiweiliang/ 13 * Dependencies : 14 * 15 * Revision : 16 * Revision : 0.01 - File Created 17 * Additional Comments : 18 ********************************************************************************/ 19 `timescale 1ns/1ps 20 `define UD #1 21 /*******************************************************************************/ 22 module three 23 ( 24 //system interface 25 input iCLK_50 ,//50MHz 26 input iRESET ,//system interface 27 //Interface package 28 output oCLK_3 ,// 29 output oCLK_5 ,// 30 output oCLK_7 ,// 31 output oCLK_9 ,// 32 output oCLK_11 ,// 33 output oCLK_13 ,// 34 output oCLK_15 ,// 35 output oCLK_17 ,// 36 output oCLK_19 // 37 //hardware interface 38 ); 39 //------------------------------------------------------------------------------- 40 parameter N = 9; 41 42 reg [9:0] TIME_CNT1,TIME_CNT1_N; 43 reg [9:0] TIME_CNT2,TIME_CNT2_N; 44 45 always@(posedge iCLK_50 or negedge iRESET)begin 46 if(!iRESET) 47 TIME_CNT1 <= 10'h0; 48 else 49 TIME_CNT1 <= TIME_CNT1_N; 50 end 51 always@(*)begin 52 if(TIME_CNT1 == N - 1) 53 TIME_CNT1_N = 10'h0; 54 else 55 TIME_CNT1_N = TIME_CNT1 + 1'h1; 56 end 57 58 always@(negedge iCLK_50 or negedge iRESET)begin 59 if(!iRESET) 60 TIME_CNT2 <= 10'h0; 61 else 62 TIME_CNT2 <= TIME_CNT2_N; 63 end 64 always@(*)begin 65 if(TIME_CNT2 == N - 1) 66 TIME_CNT2_N = 10'h0; 67 else 68 TIME_CNT2_N = TIME_CNT2 + 1'h1; 69 end 70 71 assign oCLK_3 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 72 assign oCLK_5 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 73 assign oCLK_7 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 74 assign oCLK_9 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 75 assign oCLK_11 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 76 assign oCLK_13 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 77 assign oCLK_15 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 78 assign oCLK_17 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 79 assign oCLK_19 = (TIME_CNT1 < ((N - 1)/2)) | (TIME_CNT2 < ((N - 1)/2)); 80 //------------------------------------------------------------------------------- 81 endmodule
1 /********************************************************************************* 2 * Company : 3 * Engineer : 空氣微涼 4 * 5 * Create Date : 00:00:00 22/03/2013 6 * Design Name : 7 * Module Name : 8 * Project Name : 9 * Target Devices : 10 * Tool versions : 11 * Description : 12 * http://www.cnblogs.com/kongqiweiliang/ 13 * Dependencies : 14 * 15 * Revision : 16 * Revision : 0.01 - File Created 17 * Additional Comments : 18 ********************************************************************************/ 19 `timescale 1ns/100ps 20 `define UD #1 21 /*******************************************************************************/ 22 module three_tb(); 23 //------------------------------------------------------------------------------- 24 //system interface 25 reg iSYSCLK ; 26 reg iRESET ; 27 //Interface package 28 wire oCLK_3 ; 29 wire oCLK_5 ; 30 wire oCLK_7 ; 31 wire oCLK_9 ; 32 wire oCLK_11 ; 33 wire oCLK_13 ; 34 wire oCLK_15 ; 35 wire oCLK_17 ; 36 wire oCLK_19 ; 37 //hardware interface 38 //------------------------------------------------------------------------------- 39 //測試實例設計 40 //------------------------------------------------------------------------------- 41 initial begin 42 iRESET = 0; 43 iSYSCLK = 0; 44 #100 45 iRESET = 1; 46 iSYSCLK = 1; 47 end 48 49 always #10 iSYSCLK = ~iSYSCLK ; 50 51 //------------------------------------------------------------------------------- 52 //例化被測試工程 53 //------------------------------------------------------------------------------- 54 three m_three 55 ( 56 //system interface 57 .iCLK_50 (iSYSCLK ),//50MHz 58 .iRESET (iRESET ),//system interface 59 //Interface package 60 .oCLK_3 (oCLK_3 ),// 61 .oCLK_5 (oCLK_5 ),// 62 .oCLK_7 (oCLK_7 ),// 63 .oCLK_9 (oCLK_9 ),// 64 .oCLK_11 (oCLK_11 ),// 65 .oCLK_13 (oCLK_13 ),// 66 .oCLK_15 (oCLK_15 ),// 67 .oCLK_17 (oCLK_17 ),// 68 .oCLK_19 (oCLK_19 ) // 69 //hardware interface 70 ); 71 //******************************************************************************* 72 endmodule
二 、任意占空比的任意分頻
FPGA系統時鍾是50M Hz,而我們要產生的頻率是880Hz,那么,我們需要對系統時鍾進行分頻。很容易想到用計數的方式來分頻:50000000/880 = 56818。顯然這個數字不是2的整冪次方,那么我們可以設定一個參數,讓它到56818的時候重新計數就可以實現了。程序如下:
1 module div(clk, clk_div); 2 3 input clk; 4 5 output clk_div; 6 7 reg [15:0] counter; 8 9 always @(posedge clk) 10 11 if(counter==56817) counter <= 0; 12 13 else counter <= counter+1; 14 15 assign clk_div = counter[15]; 16 17 endmodule
下面我們來算一下它的占空比:我們清楚地知道,這個輸出波形在counter為0到32767的時候為低,在32768到56817的時候為高,占空比為40%多一些,如果我們需要占空比為50%,那么我們需要再設定一個參數,使它為56817的一半,使達到它的時候波形翻轉,就可以實現結果了。程序如下:
1 module div(clk, clk_div); 2 3 input clk; 4 5 output clk_div; 6 7 reg [14:0] counter; 8 9 always @(posedge clk) 10 11 if(counter==28408) counter <= 0; 12 13 else counter <= counter+1; 14 15 reg clk_div; 16 17 always @(posedge clk) 18 19 if(counter==28408) clk_div <= ~clk_div; 20 21 endmodule
繼續讓我們來看如何實現任意占空比,比如還是由50 M分頻產生880Hz,而分頻得到的信號的占空比為30%。 56818×30%=17045
1 module div(clk,reset,clk_div,counter); 2 3 input clk,reset; 4 5 output clk_div; 6 7 output [15:0] counter; 8 9 reg [15:0] counter; 10 11 reg clk_div; 12 13 always @(posedge clk) 14 15 if(!reset) counter <= 0; 16 17 else if(counter==56817) counter <= 0; 18 19 else counter <= counter+1; 20 21 always @(posedge clk) 22 23 if(!reset) clk_div <= 0; 24 25 else if(counter<17045) clk_div <= 1; 26 27 else clk_div <= 0; 28 29 endmodule