在FPGA设计过程中,分频技术常应用域产生时钟,较与锁相环技术而言,更省逻辑,但不适合高频率的分频,因为时序逻辑需满足setup/hold要求。FPGA分频技术通常划分为偶数分频、奇数分频、半整数分频以及任意小数分频。
1、偶数分频
(1)偶数分频是属于对称分频,即把src_clk降为它的1/2, 1/4, 1/6, ... ... 1/2n,实现timing图如下:
(2)设计原理:
偶数分频:N = 2, 4, 6, 8 ...,对应的cnt_step = N/2,计数器范围:0 ~ N-1
当cnt==0时,时钟为高,即out_clk1 <= 1'b1;
当cnt==cnt_step,时钟翻转,即out_clk <= ~out_clk
2、奇数分频
(1)奇数分频属于非对称分频,其实就是按半个时钟周期的偶数分频,分别对其上升沿和下降沿进行N+1分频操作,然后再取与。
例如将src_clk降为它的1/3, 1/5 1/7, ... ... 1/2n-1,实现timing图如下:
(2)设计原理:
偶数分频:N = 3, 5, 7 ...,对应的cnt_step = (N+1)/2,计数器范围:0 ~ N-1
当cnt==0时,时钟为高,即out_clk1 <= 1'b1;
当cnt==cnt_step,时钟翻转,即out_clk <= ~out_clk
3、半整数分频
(1)半整数分频就是按1.5, 2.5, 3.5 ....的数值进行分频,对应的N = 1, 2, 3 ....,故可以理解为对2*N的奇数分频,实现timing图如下:
(2)设计原理:
半整数分频:1.5, 2.5, 3.5 ....,N = 1, 2, 3 ...,对应的cnt_step = N+1,计数器范围:0 ~ 2*N
当cnt==0时,时钟为高,即out_clk1 <= 1'b1;
当cnt==cnt_step,时钟翻转,即out_clk <= ~out_clk
4、任意小数
(1)任意小数分频,实现对rate = 输入频率/输出频率 的有效循环数的分频,这种使用较少,请参考:FPGA奇数和偶数分频器和半整数及任意小数分频器设计(Verilog程序) (renrendoc.com)
5、verilog 代码:
//even divider frequency
always @(posedge src_clk or negedge rst_n) begin //0 ~ CNT_MAX counter
if(~rst_n)
cnt <= {DIV_W{1'b0}};
else if(cnt >= CNT_MAX)
cnt <= {DIV_W{1'b0}};
else
cnt <= cnt + 1'b1;
end
always @(posedge src_clk or negedge rst_n) begin //posedge simple
if(~rst_n)
reg_clk <= 1'b0;
else if(cnt == 0)
reg_clk <= 1'b1;
else if(cnt == CNT_STEP)
pos_clk <= ~pos_clk;
end
assign out_clk = reg_clk; //output clock
//odd or half integer divider frequency
always @(posedge src_clk or negedge rst_n) begin //0 ~ CNT_MAX counter
if(~rst_n)
cnt <= {DIV_W{1'b0}};
else if(cnt >= CNT_MAX)
cnt <= {DIV_W{1'b0}};
else
cnt <= cnt + 1'b1;
end
always @(posedge src_clk or negedge rst_n) begin //posedge simple
if(~rst_n)
pos_clk <= 1'b0;
else if(cnt == 0)
pos_clk <= 1'b1;
else if(cnt == CNT_STEP)
pos_clk <= ~pos_clk;
end
always @(negedge src_clk or negedge rst_n) begin //negedge simple
if(~rst_n)
neg_clk <= 1'b0;
else if(cnt == 0)
neg_clk <= 1'b0;
else if(cnt == CNT_STEP)
neg_clk <= ~neg_clk;
end
assign out_clk = pos_clk | neg_clk; //output clock