分频器是指将输出信号频率设为输入信号频率的整数分之一的电子电路。 电子表和频率合成器等许多电子设备都需要各种不同频率的信号协同工作,常用的方法是以高稳定性的晶体振荡器为主振荡源,通过转换获得所需的各种频率分量,分频器是主要的转换手段。 早期分频器多为正弦分频器,但随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代正弦分频器。 以Verilog HDL语言为基础介绍占空比为50%的分频器。
1偶分频
偶数分频比较简单,假设为n分频,则只需计数到N/2-1,然后反转时钟,将计数清零,即可在该周期中得到n (偶数分频)。 代码如下所示。
moduleFP_Even(clk_out,clk_in,rst );
output clk_out;
input clk_in;
输入rst;
reg [1:0] cnt;
reg clk_out;
parameter N=6;
always @ (posedge clk _ inornegedgerst )
比根
if (! rst )
比根
cnt=0;
clk_out=0;
结束
else begin
if(CNT==n/2-1 ) ) )。
begin clk_out=! clk_out; cnt=0; 结束
else
cnt=cnt 1;
结束
结束
结束模块
通过改变参数n的值和计数变量cnt的位宽可以实现任意的偶数分频。
偶数分频(N=6)的RTL原理图:
偶数分频(N=6)的行为模拟结果:
2奇分频
实现奇数(n )分频,分别在上升沿计数到(N-1 )/2,计数到N-1; 在下降沿计数到(N-1 )/2,计数到N-1,得到2个波形,对它们进行相或分频,即可得到n分频。 代码如下所示。
moduleFP_odd(clk_out,clk_p,clk_n,clk_in,rst );
output clk_out;
output clk_p,clk_n;
input clk_in,rst;
reg [2:0] cnt_p,cnt_n;
reg clk_p,clk_n;
参数n=5;
always @ (posedge clk _ inornegedgerst )
比根
if (! rst ) cnt_p=0;
ELSEif(CNT_p==n-1 ) cnt_p=0;
else cnt_p=cnt_p 1;
结束
always @ (posedge clk _ inornegedgerst )
比根
if (! rst ) clk_p=0;
ELSEif(CNT_p==(n-1 )/2 ) ) ) ) ) ) ) )。
clk_p=! clk_p;
elseif(CNT_p==n-1 ) ) ) ) ) ) ) )。
clk_p=! clk_p;
结束
always @ (negedge clk _ inornegedgerst )
比根
if (! rst ) cnt_n=0;
ELSEif(CNT_n==n-1 ) cnt_n=0;
else cnt_n=cnt_n 1;
结束
always @ (negedge clk _ inornegedgerst )
比根
if (! rst ) clk_n=0;
ELSEif(CNT_n==(n-1 )/2 ) ) ) ) ) ) ) ) ) ) )。
clk_n=! clk_n;
elseif(CNT_n==n-1 ) () ) ) ) ) ) ) ) ) )。
clk_n <= !clk_n;end
assign clk_out = clk_p | clk_n;
endmodule
RTL Schematic:
Simulate Behavioral Model:
同理,可以通过改变参量N的值和计数变量cnt_p和cnt_n的位宽实现任意奇分频。
3 任意占空比的任意分频
在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求这样的话,对于程序有一定的要求,现在在前面两个实验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。
比如: FPGA系统时钟是50M Hz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。很容易想到用计数的方式来分频:50000000/880 = 56818。显然这个数字不是2的整幂次方,那么我们可以设定一个参数,让它到56818的时候重新计数就可以实现了。程序如下:
module div(clk, clk_div);
input clk;
output clk_div;
reg [15:0] counter;
always @(posedge clk)
if(counter==56817) counter <= 0;
else counter <= counter+1;
assign clk_div = counter[15];
endmodule
分频的应用很广泛,一般的做法是先用高频时钟计数,然后使用计数器的某一位输出作为工作时钟进行其他的逻辑设计,上面的程序就是一个体现。
下面我们来算一下它的占空比:我们清楚地知道,这个输出波形在counter为0到32767的时候为低,在32768到56817的时候为高,占空比为40%多一些,如果我们需要占空比为50%,那么我们需要再设定一个参数,使它为56817的一半,使达到它的时候波形翻转,就可以实现结果了。程序如下:
module div(clk, clk_div);
input clk;
output clk_div;
reg [14:0] counter;
always @(posedge clk)
if(counter==28408) counter <= 0;
else counter <= counter+1;
reg clk_div;
always @(posedge clk)
if(counter==28408) clk_div <= ~clk_div;
endmodule
继续让我们来看如何实现任意占空比,比如还是由50 M分频产生880Hz,而分频得到的信号的占空比为30%。
56818×30%=17045
module div(clk,reset,clk_div,counter);
input clk,reset;
output clk_div;
output [15:0] counter;
reg [15:0] counter;
reg clk_div;
always @(posedge clk)
if(!reset) counter <= 0;
else if(counter==56817) counter <= 0;
else counter <= counter+1;
always @(posedge clk)
if(!reset) clk_div <= 0;
else if(counter<17045) clk_div <= 1;
else clk_div <= 0;
endmodule
RTL级描述:
仿真结果:
4 小结
通过以上几个例子对比不难发现,借助计数器来实现任意点空比的任意分频的方法简单,且用verilog语言进行行为描述时,代码简洁、易懂、通用。通过以上的学习,对分频器有了比较深刻的认识,将在以后的学习中会有广泛的应用。