任意分频模板和技巧ide
(一) 偶数的分频技巧性能
(1) 任意偶数分频(占空比为50%)的模板优化
/******************** N dividen clk (1:1) duty Template ***************/spa
module clk_div(设计
inputclk_100,3d
output clk_outcode
);blog
/********* 10 dividen clk 1:1 duty success *********/ip
// 1--2--3--4--5-- ...--9--0--1 10分频就只须要10个状态ci
parameter N =4'd8; // here replace: 14, 12, 10, 8, 6, 4, 2
reg [3:0] cnt =4'd0;
always@(posedge clk_100)
begin
if(cnt == (N-1) )
cnt <= 4'd0;
else
cnt <= cnt + 1'b1;
end
reg clkout =1'b0;
always@(posedge clk_100)
begin
if(cnt == 4'd0)
clkout <= 1'b1;
else if(cnt == (N/2))
clkout <= 1'b0;
else
clkout <= clkout;
end
assign clk_out =clkout;
/***********************************************************/
上面的仿真图:
(2) 任意偶数分频(占空比为任意)的模板
/********************偶数任意分频 占空比为 (N/2+X):(N/2-X)的 模板 success ***************/
module clk_div(
inputclk_100,
output clk_out
);
// 1--2--3--4--5-- ...--9--0--1 10分频就只须要10个状态
parameter N =4'd8; // 14, 12, 10, 8 ,6 ,4 ,2
parameter X =4'd2;
reg [3:0] cnt =4'd0;
always@(posedge clk_100)
begin
if(cnt == (N-1) )
cnt <= 4'd0;
else
cnt <= cnt + 1'b1;
end
reg clkout =1'b0;
always@(posedge clk_100)
begin
if(cnt == 4'd0)
clkout <= 1'b1;
else if(cnt == (N/2 + X))
clkout <= 1'b0;
else
clkout <= clkout;
end
assign clk_out =clkout;
/***********************************************************************************/
上面的仿真图:
(二) 奇数的分频技巧
(1) 任意奇数分频(占空比为50%)的模板
/******************************* 任意奇数分频 (占空比为50%)************************************/
module clk_div(
inputclk_100,
output clk_out
);
parameter N =9; // Dividend
reg [3:0] cnt_p= 0;
always@(posedge clk_100)
begin
if(cnt_p == N-1)
cnt_p <= 4'd0;
else
cnt_p<= cnt_p + 1'b1;
end
reg clk_p = 0;
always@(posedge clk_100)
begin
if(cnt_p == (N-1)/2)
clk_p <= ~clk_p;
elseif(cnt_p == (N-1))
clk_p <= ~clk_p;
else
clk_p <= clk_p;
end
reg [3:0] cnt_n= 0;
always@(negedge clk_100)
begin
if(cnt_n == N-1)
cnt_n <= 4'd0;
else
cnt_n <= cnt_n + 1'b1;
end
reg clk_n = 0;
always@(negedge clk_100)
begin
if(cnt_n == (N-1)/2)
clk_n <= ~clk_n;
elseif(cnt_n == (N-1))
clk_n <= ~clk_n;
else
clk_n <= clk_n;
end
assign clk_out =clk_n | clk_p;
/*****************************************************************************/
仿真图以下:
(2) 任意奇数分频(占空比为任意)的模板
/********************************************任意分频要点和注意事项*******************************************************
1. 公式: fi*K = fo*2^32 fi -- 输入频率 fo -- 输出频率 k -- 计数步长
2. 占空比问题: 用这种方式求占空比问题时候,若是是是奇数分频,那么不能求到准确的1:1占空比。 (好比咱们求5分频,那么咱们只能求1/5的整数倍的占空 比) 在求准确的占空比时候,好比咱们在5分频时候,那么能够跟2^32/5 的整数倍(1~4)进行比较,而后输出高低电平,进而输出必定的占空比
3. 弊端: 任意分频只能求必定的占空比,不能求1:1占空比. 这是它的弊端。
/***************************************************************************************************************************/
/******************************* 任意分频 ************************************/
// fout*2^32 = fin*K k = fout*2^32/fin = 20*2^32/100 = 2^32/5
// 2^32 = 4294967296;
// 2^32/2 = 32'd2147483648;
// 2^32/5 = 32'd858993459
parameter K =32'd858993459; // 2^32/5 = 858993459 步长为 2^32/5 因此可使用步长的整数倍来进行分频时候使用
parameter X =4'd2; // 1, 2 ,3 ,4
reg [31:0] cnt =32'd0;
always@(posedge clk_100)
begin
cnt <= cnt + K;
end
reg clkout;
always@(posedge clk_100)
begin
if(cnt <= X*K) // cnt< 2*2^32/5 --- 占空比为 3:2
clkout<= 1'b0;
else
clkout<= 1'b1;
end
assign clk_out =clkout;
/*****************************************************************************/
下面是仿真图:
注意:
门控时钟指的是不用FPGA内部的全局时钟资源BUFG来控制触发器的时钟沿输入端而是采用组合逻辑和其它时序逻辑(如分频器)产生的信号做为触发器的时钟沿输入端。门控时钟容易带来时钟漂移、毛刺等,使得触发器误动做,一般,对于驱动的触发器数量较少的门控时钟,编译器能够自动将分布时钟缓冲器将其布线优化,可是对于驱动触发器较多的门控时钟,将会使布线不稳定,重者形成设计混乱。门控时中较多,也会使得整个设计的最大工做速度降低,下降产品的性能。
咱们不能直接使用门控时钟,最好使用使能时钟。 下面就是使能时钟的生成: 设 clkout 是由组合逻辑或者分频计数实现的时钟,clk_out 是咱们最终生成的时钟。
reg[1:0] clkout1;
always@(posedge clk_100)
begin
clkout1 <= {clkout1[0], clkout};
end
assign clk_out = ~clkout1[0]&&clkout1[1] ? 1'b1 : 1'b0;
/*************************************************************** for example *******************************************************************
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 10:59:16 08/09/2015 // Design Name: // Module Name: clk_div // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module clk_div( input clk_100, // output [1:0]cnta, // output [1:0]cntb, output cnta, output cntb, output clk_out ); /******************** 偶数任意分频 占空比为50%模板 1:1 duty success *************** // 1--2--3--4--5-- ...--9--0--1 10分频就只须要10个状态 parameter N = 4'd8; // 14, 12, 10, 8 ,6 ,4 ,2 reg [3:0] cnt = 4'd0; always@(posedge clk_100) begin if(cnt == (N-1) ) cnt <= 4'd0; else cnt <= cnt + 1'b1; end reg clkout = 1'b0; always@(posedge clk_100) begin if(cnt == 4'd0) clkout <= 1'b1; else if(cnt == (N/2)) clkout <= 1'b0; else clkout <= clkout; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /***********************************************************************************/ /******************** 偶数任意分频 占空比为 (N/2+X):(N/2-X)的 模板 success *************** // 1--2--3--4--5-- ...--9--0--1 10分频就只须要10个状态 parameter N = 4'd8; // 14, 12, 10, 8 ,6 ,4 ,2 parameter X = 4'd2; reg [3:0] cnt = 4'd0; always@(posedge clk_100) begin if(cnt == (N-1) ) cnt <= 4'd0; else cnt <= cnt + 1'b1; end reg clkout = 1'b0; always@(posedge clk_100) begin if(cnt == 4'd0) clkout <= 1'b1; else if(cnt == (N/2 + X)) clkout <= 1'b0; else clkout <= clkout; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /***********************************************************************************/ /************* 2 dividen clk right ******************* reg clk_R = 1'b0; always@(posedge clk_100) begin clk_R = ~ clk_R; end assign clk_out = clk_R; /*******************************************************/ /******************** 4 dividen clk 3:1 duty success *************** // 1--2--3--0--1 4分频就只须要4个状态 reg [1:0] cnt = 2'd0; always@(posedge clk_100) begin if(cnt == 2'd3) cnt <= 2'd0; else cnt <= cnt + 1'b1; end reg clkout = 1'b0; always@(posedge clk_100) begin if(cnt == 2'd1) clkout <= 1'b1; else if(cnt == 2'd0) clkout <= 1'b0; else clkout <= clkout; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /***********************************************************/ /******************** 6 dividen clk 4:2 duty success *************** // 1--2--3--4--5--0--1 6分频就只须要6个状态 reg [2:0] cnt = 3'd0; always@(posedge clk_100) begin if(cnt == 3'd5) cnt <= 3'd0; else cnt <= cnt + 1'b1; end reg clkout = 1'b0; always@(posedge clk_100) begin if(cnt == 3'd1) clkout <= 1'b1; else if(cnt == 3'd5) clkout <= 1'b0; else clkout <= clkout; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /***********************************************************/ /******************** 偶数任意分频 占空比为50%模板 1:1 duty success *************** // 1--2--3--4--5-- ...--9--0--1 10分频就只须要10个状态 parameter N = 4'd8; // 14, 12, 10, 8 ,6 ,4 ,2 reg [3:0] cnt = 4'd0; always@(posedge clk_100) begin if(cnt == (N-1) ) cnt <= 4'd0; else cnt <= cnt + 1'b1; end reg clkout = 1'b0; always@(posedge clk_100) begin if(cnt == 4'd0) clkout <= 1'b1; else if(cnt == (N/2)) clkout <= 1'b0; else clkout <= clkout; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /***********************************************************************************/ /***************** 3 dividen clk error ***************** //This code looks like right,and simulation shows right // But it is wrong. reg [2:0] cnt = 3'd0; reg clk_R = 1'b0; always@(clk_100) begin if(cnt < 3'd3) cnt = cnt + 1'b1; if(cnt == 3'd3) begin clk_R = ~ clk_R; cnt = 3'd0; end end assign clk_out = clk_R; /*********************************************************/ /***************** 3 dividen clk success ***************** reg [1:0] cnt_a = 0; always@(posedge clk_100) begin if(cnt_a == 2'b10) cnt_a <= 2'd0; else cnt_a <= cnt_a + 1'b1; end reg [1:0] cnt_b = 0; always@(negedge clk_100) begin if(cnt_b == 2'b10) cnt_b <= 2'd0; else cnt_b <= cnt_b + 1'b1; end reg clk_R = 1'b0; always@(cnt_a or cnt_b) begin if((cnt_a + cnt_b == 3'd4) || (cnt_a + cnt_b == 3'd1)) clk_R <= ~ clk_R; else clk_R <= clk_R; end assign clk_out = clk_R; assign cnta = cnt_a; assign cntb = cnt_b; /*********************************************************/ /****************** 3 dividen clk success ********************** reg q1,q2,d,throut; initial begin d = 0; q1 = 0; q2 = 0; throut = 0; end always @(posedge clk_100) if(!d) q1=1'b1; else q1=~q1; always @(negedge clk_100) if(!d) q2=1'b1; else q2=~q2; always @(q1 or q2) d=q1&q2; always @(posedge d) throut=~throut; assign clk_out = throut; /*******************************************************************/ /********************* 3 dividen clk success duty50% ********************** reg [1:0] step1, step; always @(posedge clk_100) begin case (step) //这个状态机就是一个计数器 2'b00: step<=2'b01; 2'b01: step<=2'b10; 2'b10: step<=2'b00; default :step<=2'b00; endcase end always @(negedge clk_100) //step1与step相差半个clk begin case (step1) 2'b00: step1<=2'b01; 2'b01: step1<=2'b10; 2'b10: step1<=2'b00; default :step1<=2'b00; endcase end assign clk_out = step[1] | step1[1]; //利用step和step1高位的或运算,实如今1.5个clk时翻转。 /***********************************************************************************/ /********************* 5 dividen clk success duty50% ********************** reg [2:0] step1, step2; always@(posedge clk_100) begin case (step1) 3'b000: step1<=3'b001; 3'b001: step1<=3'b011; 3'b011: step1<=3'b100; 3'b100: step1<=3'b010; 3'b010: step1<=3'b000; default:step1<=3'b000; endcase end always@(negedge clk_100) begin case (step2) 3'b000: step2<=3'b001; 3'b001: step2<=3'b011; //注意调换了顺序,目的为了使最低位为1的状况互邻 3'b011: step2<=3'b100; 3'b100: step2<=3'b010; 3'b010: step2<=3'b000; default:step2<=3'b000; endcase end assign clk_out = (step1[0]|step2[0]); //step1与step2 最低位相或 assign cnta = 2'b11; assign cntb = 2'b11; /********************* 5 dividen clk success 50%duty ********************** reg [2:0] cnt_p = 0; reg [2:0] cnt_n = 0; reg clk_p = 0; reg clk_n = 0; parameter N = 5; // posedge clk 0-1-2-3-4-0 always@(posedge clk_100) begin if(cnt_p==N-1) cnt_p <=0; else cnt_p <= cnt_p + 1; end always@(posedge clk_100) begin if(cnt_p==(N-1)/2) //2 clk_p <= !clk_p; else if(cnt_p==N-1) clk_p <= !clk_p; //4 end // negedge clk 0-1-2-3-4-0 always@(negedge clk_100 ) begin if(cnt_n==N-1) cnt_n <=0; else cnt_n <= cnt_n + 1; end always@(negedge clk_100) begin if(cnt_n==(N-1)/2) clk_n <= !clk_n; else if(cnt_n==N-1) clk_n <= !clk_n; end assign clk_out = clk_p | clk_n; //*********** for simulation ************** //assign cnta = clk_p; //assign cntb = clk_n; //******************************************* assign cnta = 2'b11; assign cntb = 2'b11; /*********************************************************/ /******************************* 5 分频 ************************************ // fout*2^32 = fin*K k = fout*2^32/fin = 20*2^32/100 = 2^32/5 // 2^32 = 4294967296; // 2^32/2 = 32'd2147483648; // 2^32/5 = 32'd858993459 parameter K = 32'd858993459; // 2^32/5 = 858993459 reg [31:0] cnt = 32'd0; always@(posedge clk_100) begin cnt <= cnt + K; end reg clkout; always@(posedge clk_100) begin if(cnt < 32'd2147483648) // cnt < 2^32/5---占空比为 4:1 cnt < 2^32/2---占空比为 1:1 clkout <= 1'b0; else clkout <= 1'b1; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /*****************************************************************************/ /********************* 7 dividen clk duty = 50% success ********************** reg [2:0] cnt_p = 0; reg [2:0] cnt_n = 0; reg clk_p = 0; reg clk_n = 0; parameter N = 7; always@(posedge clk_100) begin if(cnt_p == N-1) cnt_p <= 3'd0; else cnt_p <= cnt_p + 1'b1; end always@(posedge clk_100) begin if(cnt_p == (N-1)/2) clk_p <= ~ clk_p; else if(cnt_p == (N-1)) clk_p <= ~ clk_p; else clk_p <= clk_p; end always@(negedge clk_100) begin if(cnt_n == N-1) cnt_n <= 3'd0; else cnt_n <= cnt_n+ 1'b1; end always@(negedge clk_100) begin if(cnt_n == (N-1)/2) clk_n <= ~ clk_n; else if(cnt_n == (N-1)) clk_n <= ~ clk_n; else clk_n <= clk_n; end assign cnta = clk_p; assign cntb = clk_n; assign clk_out = clk_p | clk_n; /********************************************************/ /******************************************** 任意分频要点和注意事项 ******************************************************* 1. 公式: fi*K = fo*2^32 fi -- 输入频率 fo -- 输出频率 k -- 计数步长 2. 占空比问题: 用这种方式求占空比问题时候,若是是是奇数分频,那么不能求到准确的1:1占空比。 (好比咱们求5分频,那么咱们只能求1/5的整数倍的占空比) 在求准确的占空比时候,好比咱们在5分频时候,那么能够跟 2^32/5 的整数倍(1~4)进行比较,而后输出高低电平,进而输出必定的占空比 3. 弊端: 任意分频只能求必定的占空比,这是它的弊端。 /**********************************************************************************************************************/ /******************************* 任意分频 ************************************ // fout*2^32 = fin*K k = fout*2^32/fin = 20*2^32/100 = 2^32/5 // 2^32 = 4294967296; // 2^32/2 = 32'd2147483648; // 2^32/5 = 32'd858993459 parameter K = 32'd858993459; // 2^32/5 = 858993459 步长为 2^32/5 因此可使用步长的整数倍来进行分频时候使用 parameter X = 4'd2; // 1, 2 ,3 ,4 reg [31:0] cnt = 32'd0; always@(posedge clk_100) begin cnt <= cnt + K; end reg clkout; always@(posedge clk_100) begin if(cnt < X*K) // cnt < 2*2^32/5---占空比为 3:2 if(cnt <= X*K) clkout <= 1'b0; else clkout <= 1'b1; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /*****************************************************************************/ /******************************* 任意奇数分频 (占空比为50%) ************************************/ parameter N = 9; // Dividend reg [3:0] cnt_p = 0; always@(posedge clk_100) begin if(cnt_p == N-1) cnt_p <= 4'd0; else cnt_p <= cnt_p + 1'b1; end reg clk_p = 0; always@(posedge clk_100) begin if(cnt_p == (N-1)/2) clk_p <= ~clk_p; else if(cnt_p == (N-1)) clk_p <= ~clk_p; else clk_p <= clk_p; end reg [3:0] cnt_n = 0; always@(negedge clk_100) begin if(cnt_n == N-1) cnt_n <= 4'd0; else cnt_n <= cnt_n + 1'b1; end reg clk_n = 0; always@(negedge clk_100) begin if(cnt_n == (N-1)/2) clk_n <= ~clk_n; else if(cnt_n == (N-1)) clk_n <= ~clk_n; else clk_n <= clk_n; end assign clk_out = clk_n | clk_p; assign cnta = 1'b1; assign cntb = 1'b1; /*****************************************************************************/ /*********************************** 7分频 占空比为 4:3 success ********************************* // 2^32*fout = K*fin; fin=100 fout=100/7= 14.285714285714285714285714285714 parameter K = 32'd613566756; // 2^32*fout/fin = k = 2^32/7 = 613566756 4*k = 2454267026 reg [31:0] cnt = 32'd0; always@(posedge clk_100) begin cnt <= cnt + K; end reg clkout = 1'b0; always@(posedge clk_100) begin if(cnt <= 32'd2454267026) // 4*k clkout <= 1'b1; else clkout <= 1'b0; end assign clk_out = clkout; assign cnta = 1'b1; assign cntb = 1'b1; /****************************************************************************************/ endmodule