程序实现任意整数分频的功能,已在modelsim中通过验证。
1 //`define N 5 2 module div_N ( 3 input CLK, // 基准时钟 4 output CLK_div_N, // N分频后得到的时钟 5 input rst 6 ); 7 wire [31:0] N=5; // ★ N为分频系数,N≥2即可,N的值为CLK除以CLK_div_N后取整(四舍五入) 8 9 /******************** 产生备用时钟1 ***************/ 10 reg [31:0] cnt1; 11 reg CLK_div_N_1; 12 always @ (posedge CLK or negedge rst) 13 begin 14 if(!rst) 15 begin 16 cnt1<=0; 17 CLK_div_N_1<=0; 18 end 19 else if(N[0]==0) // 如果N为偶数,比N%2==0这种判断方式更节省资源 20 begin 21 if(N==2) // 如果N为2 22 CLK_div_N_1 <= ~CLK_div_N_1; 23 else 24 if(cnt1==((N-2)>>1)) //比cnt1==(N-2)/2这种判断方式更节省资源 25 begin 26 cnt1 <= 0; 27 CLK_div_N_1 <= ~CLK_div_N_1; 28 end 29 else 30 cnt1 <= cnt1+1; 31 end 32 end 33 else // 如果N为奇数 34 if(cnt1==(N-1)/2) 35 begin 36 CLK_div_N_1 <= ~CLK_div_N_1;cnt1<=cnt1+1'b1; 37 end 38 else if(cnt1==N-1) begin cnt1 <= 0;CLK_div_N_1 <= ~CLK_div_N_1;end 39 else 40 cnt1<=cnt1+1'b1; 41 42 end 43 44 /*********************** 产生备用时钟2 *********************/ 45 wire CLK0=(N%2)? (~CLK):0; // 如果N为偶数,备用时钟2(CLK_div_N_2)恒为0,即不需要用到此备用时钟 46 reg [31:0] cnt2; 47 reg CLK_div_N_2; 48 always @ (posedge CLK0 or negedge rst) 49 if(!rst) 50 begin 51 cnt2<=0; 52 CLK_div_N_2<=0; 53 end 54 else 55 if(cnt2==(N-1)/2) 56 begin 57 CLK_div_N_2 <= ~CLK_div_N_2;cnt2 <= cnt2+1; 58 end 59 else if(cnt2==N-1) begin cnt2 <= 0;CLK_div_N_2 <= ~CLK_div_N_2;end 60 else 61 cnt2 <= cnt2+1; 62 63 64 /******************** 产生最终分频时钟************************/ 65 assign CLK_div_N = CLK_div_N_1 | CLK_div_N_2; 66 67 endmodule
`timescale 1ns/1ns module div_N_tb; reg CLK,rst; wire CLK_div_N; div_N U1( .CLK(CLK), .CLK_div_N(CLK_div_N), .rst(rst) ); initial begin CLK=0; rst=0; #5 rst=1; forever #5 CLK=~CLK; end endmodule
图1: 9分频电路
图2: 8分频电路
解释:刚程序调好时发现,偶数分频时候,第一个分频后的时钟不是占用原时钟8clk,还以为程序有问题,细想之后,应该是偶数计数器是从0到(N/2)-1计数,每次到(N/2)-1时翻转,而第一次初始情况下cnt就是0,但新时钟却没有翻转,