赞
踩
分频器,是将输入信号的频率进行缩小。实际上,在数学IC笔面中常考的分频器设计,就是采用计数器,对输入时钟合理生成中间信号,最后通过逻辑操作输出。本质上,这里考的还是计数器相关的知识点,同时会涉及到时钟相关的基本概念。
(1)在实际的项目中,除非是对时钟没有特殊要求,这时候才能使用分频的方法;
(2)一般会优先使用PLL、MMCM等成熟IP,得到精确、质量高的时钟信号。
关于分频器的种类,大致有以下几点:
(1)偶数分频,始终产生占空比50%。
(2)奇数分频,分为占空比50%和非50%。(相较于偶数分频,奇数分频是常考的知识点)
(3)小数分频,结合正常分频和平均分布实现的。(之前都没怎么考过,相较于前两种,更加综合,看看现在这越来越卷的数字IC,建议还是要掌握)
注意点:
除了分频器本身相关的知识点,这里在面试时也会有时钟和时序分析相关的拓展点,建议同学们也要了解时钟和时序分析相关的知识点。有条件的同学,可以亲手做做时序分析相关的实验,了解时序路径和时序报告。
采用触发器加反相器,可以构成简单的2分频电路,以这个基本单元进行级联可以实现4分频、8分频、16分频,分频系数是2^n.
2分频电路:
4分频电路:
2^n分频电路:
Verilog实现:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : even_fre_div1.v
// Create : 2022-11-07 10:06:32
// Revise : 2022-11-07 10:06:32
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 2^n 偶数分频 利用DFF 取反 //div2 div4 div8
// -----------------------------------------------------------------------------
module even_fre_div1 (
input clk , // Source Clock
input rst_n , // Asynchronous reset active low
output wire clk_div2 , // clock div2
output wire clk_div4 , // clock div4
output wire clk_div8 // clock div8
);
//reg define
reg clk_div2_t ;
reg clk_div4_t ;
reg clk_div8_t ;
//div_2
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
clk_div2_t <= 1'b0 ;
end
else begin
clk_div2_t <= ~clk_div2_t ;
end
end
//div4
always @(posedge clk_div2 or negedge rst_n) begin
if(~rst_n) begin
clk_div4_t <= 1'b0;
end
else begin
clk_div4_t <= ~clk_div4_t ;
end
end
//div8
always @(posedge clk_div4 or negedge rst_n) begin
if(~rst_n) begin
clk_div8_t <= 1'b0;
end
else begin
clk_div8_t <= ~clk_div8_t ;
end
end
//assign
assign clk_div2 = clk_div2_t ;
assign clk_div4 = clk_div4_t ;
assign clk_div8 = clk_div8_t ;
endmodule
利用计数器,计数范围(0~2N-1),在N-1处取反。直接看波形:
计数器2n偶数分频:
Verilog实现:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : even_fre_div2.v
// Create : 2022-11-07 10:30:09
// Revise : 2022-11-07 10:30:09
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 2n偶数分频,计数器实现
// -----------------------------------------------------------------------------
module even_fre_div2 #(
parameter div_2n = 12
)(
input clk , // Source Clock
input rst_n , // Asynchronous reset active low
output wire clk_div2n // div 2n
);
reg [3:0] cnt ;
reg clk_div2n_t ;
//cnt
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
cnt <= 4'd0;
end
else if(cnt == (div_2n/2) -1)begin
cnt <= 4'd0 ;
end
else begin
cnt <= cnt +4'd1 ;
end
end
//out clk
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
clk_div2n_t <= 1'b0;
end
else if(cnt == (div_2n/2)-1) begin
clk_div2n_t <= ~clk_div2n_t;
end
else begin
clk_div2n_t <= clk_div2n_t ;
end
end
//assign
assign clk_div2n = clk_div2n_t ;
endmodule
相较于偶数分频,奇数分频的知识点要稍微多些,有占空比50%和非50%;而占空比50%又是最常考的知识点,有相与、相或、相异或三种。
实际手撕代码时,要求熟练掌握一种奇数分频的电路就行,这里推荐相与和相或,两种任一选择一种练习就行。
**PS:**奇数分频还涉及到双边沿计数器,感兴趣的同学可以了解双边沿采样相关的知识点。
先看方法:
再看波形:
最后看代码:
示例1,单计数器实现:
只在上升沿计数,在上升沿和下降沿采用输出高低电平;
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : odd_fre_or_div1.v
// Create : 2022-11-07 15:49:36
// Revise : 2022-11-07 15:49:36
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 奇数分频 占空比50% OR操作 单计数器实现
// -----------------------------------------------------------------------------
module odd_fre_or_div1 #(
parameter DIV_CLK = 9 //div 2n+1
)(
input clk , //Source Clock
input rst_n , //Asynchronous reset active low
output wire clk_div_odd //div odd
);
//reg define
reg [3:0] cnt ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//cnt
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt <= 'b0 ;
end
else if (cnt == DIV_CLK-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
//posedge clk_div
always @(posedge clk or negedge rst_n) begin // N >>> high N+1 >>> low
if (~rst_n) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt == (DIV_CLK>>1)-1 ) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt == DIV_CLK-1) begin
clkp_odd_r <= 1'b1 ;
end
else begin
clkp_odd_r <= clkp_odd_r ;
end
end
//negedge clk_div
always @(negedge clk or negedge rst_n) begin // N >>> high N+1 >>> low
if (~rst_n) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt == (DIV_CLK>>1)-1 ) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt == DIV_CLK-1) begin
clkn_odd_r <= 1'b1 ;
end
else begin
clkn_odd_r <= clkn_odd_r ;
end
end
//OR
assign clk_div_odd = clkp_odd_r | clkn_odd_r ;
endmodule
示例2,双计数器实现:
在上升沿和下降沿计数,在上升沿和下降沿采用输出高低电平;
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : odd_fre_or_div2.v
// Create : 2022-11-07 16:10:14
// Revise : 2022-11-07 16:10:14
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 奇数分频 占空比50% OR操作 双计数器实现
// -----------------------------------------------------------------------------
module odd_fre_or_div2 #(
parameter DIV_CLK = 9
)(
input clk , // Source Clock
input rst_n , // Asynchronous reset active low
output wire clk_div_odd // div odd
);
reg [3:0] cnt_p ;
reg [3:0] cnt_n ;
reg clkp_odd_r ;
reg clkn_odd_r ;
// pos cnt
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt_p <= 'b0 ;
end
else if (cnt_p == DIV_CLK-1) begin
cnt_p <= 'b0 ;
end
else begin
cnt_p <= cnt + 1'b1 ;
end
end
//neg cnt
always @(negedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt_n <= 'b0 ;
end
else if (cnt_n == DIV_CLK-1) begin
cnt_n <= 'b0 ;
end
else begin
cnt_n <= cnt + 1'b1 ;
end
end
//posedge clk_div
always @(posedge clk or negedge rst_n) begin // N >>> high N+1 >>> low
if (~rst_n) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt_p == (DIV_CLK>>1)-1 ) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt_p == DIV_CLK-1) begin
clkp_odd_r <= 1'b1 ;
end
else begin
clkp_odd_r <= clkp_odd_r ;
end
end
//negedge clk_div
always @(negedge clk or negedge rst_n) begin // N >>> high N+1 >>> low
if (~rst_n) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt_n == (DIV_CLK>>1)-1 ) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt_n == DIV_CLK-1) begin
clkn_odd_r <= 1'b1 ;
end
else begin
clkn_odd_r <= clkn_odd_r ;
end
end
//OR
assign clk_div_odd = clkp_odd_r | clkn_odd_r ;
endmodule
先看方法:
再看波形:
最后看代码:
示例1,单计数器实现:
只在上升沿计数,在上升沿和下降沿采用输出高低电平;
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : odd_fre_and_div1.v
// Create : 2022-11-07 16:30:31
// Revise : 2022-11-07 16:30:31
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description:奇数分频 占空比50% AND操作 单计数器实现
// -----------------------------------------------------------------------------
module odd_fre_and_div1 #(
parameter DIV_CLK = 9
)(
input clk ,
input rst_n ,
output wire clk_div_odd
);
//capture at negedge
reg [3:0] cnt ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//cnt
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt <= 'b0 ;
end
else if (cnt == DIV_CLK-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
//posedge clk_div
always @(posedge clk or negedge rst_n) begin // N+1 >>> high N >>> low
if (~rst_n) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt == (DIV_CLK>>1) ) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt == DIV_CLK-1) begin
clkp_odd_r <= 1'b1 ;
end
else begin
clkp_odd_r <= clkp_odd_r ;
end
end
//negedge clk_div
always @(negedge clk or negedge rst_n) begin // N+1 >>> high N >>> low
if (~rst_n) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt == (DIV_CLK>>1) ) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt == DIV_CLK-1) begin
clkn_odd_r <= 1'b1 ;
end
else begin
clkn_odd_r <= clkn_odd_r ;
end
end
//AND
assign clk_div_odd = clkp_odd_r & clkn_odd_r ;
endmodule
示例2,双计数器实现:
在上升沿和下降沿计数,在上升沿和下降沿采用输出高低电平;
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : CHAO LI 1320343336@qq.com
// File : odd_fre_and_div2.v
// Create : 2022-11-07 16:38:20
// Revise : 2022-11-07 16:38:20
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 奇数分频 占空比50% AND操作 双计数器实现
// -----------------------------------------------------------------------------
module odd_fre_and_div2 #(
parameter DIV_CLK = 9
)(
input clk , // Source Clock
input rst_n , // Asynchronous reset active low
output wire clk_div_odd // div odd
);
reg [3:0] cnt_p ;
reg [3:0] cnt_n ;
reg clkp_odd_r ;
reg clkn_odd_r ;
// pos cnt
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt_p <= 'b0 ;
end
else if (cnt_p == DIV_CLK-1) begin
cnt_p <= 'b0 ;
end
else begin
cnt_p <= cnt + 1'b1 ;
end
end
//neg cnt
always @(negedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt_n <= 'b0 ;
end
else if (cnt_n == DIV_CLK-1) begin
cnt_n <= 'b0 ;
end
else begin
cnt_n <= cnt + 1'b1 ;
end
end
//posedge clk_div
always @(posedge clk or negedge rst_n) begin // N+1 >>> high N >>> low
if (~rst_n) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt_p == (DIV_CLK>>1) ) begin
clkp_odd_r <= 1'b0 ;
end
else if (cnt_p == DIV_CLK-1) begin
clkp_odd_r <= 1'b1 ;
end
else begin
clkp_odd_r <= clkp_odd_r ;
end
end
//negedge clk_div
always @(negedge clk or negedge rst_n) begin // N+1 >>> high N >>> low
if (~rst_n) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt_n == (DIV_CLK>>1) ) begin
clkn_odd_r <= 1'b0 ;
end
else if (cnt_n == DIV_CLK-1) begin
clkn_odd_r <= 1'b1 ;
end
else begin
clkn_odd_r <= clkn_odd_r ;
end
end
//AND
assign clk_div_odd = clkp_odd_r & clkn_odd_r ;
endmodule
XOR操作相较于上述两种方法使用较少,这里大家理解一下实现的思路就好,仅供感兴趣的同学提供新思路。
重要的是自己要熟练掌握一种奇数分频方法。
先看方法:
再看波形:
最后看代码:
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : odd_fre_xor_div.v
// Create : 2022-11-07 17:02:24
// Revise : 2022-11-07 17:02:24
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 奇数分频 占空比50% XOR操作
// -----------------------------------------------------------------------------
module odd_fre_xor_div #(
parameter DIV_CLK = 9
)(
input clk , // Source Clock
input rst_n , // Asynchronous reset active low
output wire clk_div_odd // div odd
);
reg [3:0] cnt;//上升沿计数
reg clkp_odd ;
reg clkn_odd ;
//cnt
always@(posedge clk or negedge rst_n)begin
if(~rst_n)begin
cnt <= 4'd0;
end
else if(cnt == DIV_CLK-1) begin
cnt <= 4'd0;
end
else begin
cnt <= cnt + 1;
end
end
//pos clk_div
always@(posedge clk or negedge rst_n)begin
if(~rst_n)begin
clkp_odd <= 1'b0;
end
else if (cnt == DIV_CLK-1 )begin
clkp_odd <= ~clkp_odd;
end
else begin
clkp_odd <= clkp_odd;
end
end
//neg clk_div
always@(negedge clk or negedge rst_n) begin
if(~rst_n) begin
clkn_odd <= 1'b0;
end
else if (cnt == DIV_CLK >> 1) begin
clkn_odd <= ~clkn_odd;
end
else begin
clkn_odd <= clkn_odd ;
end
end
//XOR
assign clk_div_odd = clkp_odd ^ clkn_odd;
endmodule
占空比非50%的情况,只要分频后的波形周期是原波形周期的2N+1就行。
3分频有两种占空比,1/3 和2/3。分别对应OR 操作和AND操作,具体代码可以参考上述。
小数分频不能做到精确控制占空比,也没法做到精确的小数分频,而是平均频率是小数倍。这里小数分频涉及到奇数分频、偶数分频以及平均分布的方法。
小数分频的关键点有两个:
(1)完成奇偶分频,确定好分频次数;
(2)确定分频次数后,要合理安排分频的顺序,确保平均。
例如8.4分频,得到6次8分频和4次9分频,对应有四种分布方式。
分布方式 | 具体操作 | 备注 |
---|---|---|
1 | 先6次8分频,再4次9分频 | 频率不均,边缘处时钟抖动大 |
2 | 先4次9分频,再6次8分频 | 频率不均,边缘处时钟抖动大 |
3 | 6次8分频和4次9分频,平均分布 | 频率均匀,抖动小 |
以8.4倍小数分频举例
源代码参数传递出现问题,感谢@m0_71109578 纠正。
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : fre_fractional_n.v
// Create : 2022-11-08 14:45:45
// Revise : 2024-4-13 11:53:20
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 小数分频 8.4倍小数
// -----------------------------------------------------------------------------
module fre_fractional_n (
input rstn , //Asynchronous reset active low
input clk , //Source Clock
output clk_frac //fractional frequency division
);
parameter SOURCE_NUM = 84 ; //Sorce clocks
parameter DEST_NUM = 10 ; //div nums 8.4
localparam SOURCE_DIV = SOURCE_NUM/DEST_NUM ; //8-divisor
localparam DEST_DIV = SOURCE_DIV + 1; //9-divisor
localparam DIFF_ACC = SOURCE_NUM - SOURCE_DIV*DEST_NUM ;
//reg
reg [3:0] cnt_end_r ;
reg [3:0] main_cnt ;
reg clk_frac_r ;
wire diff_cnt_en ;
//difference counter
reg [4:0] diff_cnt_r ;
wire [4:0] diff_cnt ;
//main_cnt
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
main_cnt <= 'b0 ;
clk_frac_r <= 1'b0 ;
end
else if (main_cnt == cnt_end_r) begin
main_cnt <= 'b0 ;
clk_frac_r <= 1'b1 ;
end
else begin
main_cnt <= main_cnt + 1'b1 ;
clk_frac_r <= 1'b0 ;
end
end
//diff_cnt
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
diff_cnt_r <= 0 ;
end
else if (diff_cnt_en) begin
diff_cnt_r <= diff_cnt ;
end
end
// cnt_end
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
cnt_end_r <= SOURCE_DIV-1 ;
end
else if (diff_cnt >= 10) begin
cnt_end_r <= DEST_DIV-1 ;
end
else begin
cnt_end_r <= SOURCE_DIV-1 ;
end
end
//assign
assign clk_frac = clk_frac_r ;
assign diff_cnt_en = (main_cnt == cnt_end_r)?1'b1:1'b0 ;
assign diff_cnt = diff_cnt_r >= DEST_NUM ?
(diff_cnt_r -10 + DIFF_ACC)
: (diff_cnt_r + DIFF_ACC) ;
endmodule
分频器作为数字IC笔面最常考的知识点,经常会出现在编程题和手撕代码环节,其中,奇数分频又是最常考的部分,要求必须熟练掌握一种奇数分频方法。
(1)偶数分频不需要考虑占空比,是理想的50%。
(2)奇数分频需要考虑占空比是否50%,要求使用双边沿逻辑,涉及到双边沿操作,这里会有一定的拓展,例如双边沿采样怎么实现?另外,时钟相关的概念也有涉及,例如频率、相位、抖动和偏移等。
(3)小数分频涉及奇数分频和偶数分频,之前很少出现手撕代码的环节,大多在笔试环节或者面试询问相关的实现方式,要求理解实现方法就好,但看现在数字IC越来越卷的现状,建议有时间精力的同学还是了解相关知识点。
(4)分频器相关的知识点拓展可以是时钟相关的IP以及时序分析相关的知识点,同学们也要了解相关的知识点,打好基础。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。