资源描述
分频的Verilog实现
1. 分频:在实际应用中,自己设计的开发板上不会去装多个晶振来产生不同频率的时钟信号,这就要我们在已有的基础上自己来创造设计电路中所需要的时钟信号来,有时候所需要的频率并不是在已有的频率上直接进行简单的整数分频就可以得到的,有时需要进行小数的分频。
2. 在分频的过程中,偶数分频并不困难,若要进行2N次分频的话,只需要计数到N的时候,波形进行翻转就行了,或者在最后一级加一个2分频也可以实现。
下面是我写的一个偶数分频的代码:
module div2n(rst,clk,cnt,clk_2n);//偶数次分频
input rst,clk;
output clk_2n,cnt;
reg [3:0] cnt;//刚开始没有定义计数的位宽仿真的时候老是出现输出为0的现象,看似很简单的程序搞的有些纠结啊
reg clk_2n;
always @(posedge clk )
begin
if(rst) //若复位信号为高电平则计数清零和输出清零
begin
cnt<=0;
clk_2n<=0;
end
else
if(cnt==3)//进行8分频,这里的cnt取不同的值进行其他的分频,若计数到达4时从0开始的输出电平翻转
begin
clk_2n<=~clk_2n;
cnt<=0;
end
else cnt<=cnt+1;
end
endmodule
功能仿真波形以及后仿真波形如下:
从后仿真中可以明显的看出输出时钟信号和输入的标准信号有延迟时间,在计数寄存器中出现了相邻两个数之间的竞争,但是没有出现在时钟的上升沿,不会引起最后实现的错误!
奇数分频:若奇数分频中不考虑占空比的话,分频代码可以按照偶数分频的思路来写,但是大多数情况下需要考虑的是使占空比设计为50%。若要进行奇数次的分频而且要求占空比为50%可以采用:用两个计数器,一个由输入时钟下降沿触发,一个由输入时钟的上升沿触发,最后将两个计数器的输出进行相或,就可得到。
程序代码:
module div7(rst,clk,cout1,cout2,cout);
input clk,rst;
output cout1,cout2,cout;
reg [2:0] m,n;//定义两个中间的计数变量
wire cout;
reg cout1,cout2;
assign cout=cout1|cout2;//将上升沿和下降沿的输出相或得到占空比为50%的波形
always @(posedge clk)//上升沿触发
begin
if(rst) begin cout1<=0;m<=0;end//当rst为1时复位
else if(!rst)
begin if(m==6) begin m<=0;end//计数到达7时计数复位
else m<=m+1;//其他情况计数器正常计数
if(m==2) cout1=~cout1;//计数到达3时翻转
else if(m==5) cout1=~cout1;//计数器达到6时再翻转
end
end
always @(negedge clk)//下降沿触发,情况同上
begin
if(rst) begin cout2<=0;n<=0;end
else if(!rst)
begin if(n==6) begin n<=0;end
else n<=n+1;
if(n==2) cout2=~cout2;
else if(n==5) cout2=~cout2;
end
end
endmodule
最后仿真波形:
时序仿真波形为:
半整数分频:半整数分频N.5的分频。设计的思想是:比如说要实现2.5分频可以先设计一个模3计数器,再设计一个脉冲扣除电路,加在模3计数器之后,每来3个脉冲就扣除半个脉冲,即可实现分频系数为2.5的半整数分频,采用类似的方法,可以实现任意半整数分配器。脉冲扣除是输入频率与2分频输出异或的结果。
大致的思路可用下图来分析:
clk1
=1
模N计数器
2分频
clk2 clkout
clkin
5.5分频代码为
module xfp(clkin,clr,clkout);
input clkin,clr;
output clkout;
reg clkout,clk1;
wire clk2;
integer count;
xor xor1(clk2,clkin,clk1);//将输出2分频时钟与clk2/6分频时钟相异或得到5.5分频
always @(posedge clkout or negedge clr)//输出时钟2分频
begin if(~clr)
begin clk1<=1'b0; end
else clk1<=~clk1;
end
always @(posedge clk2 or negedge clr)//将时钟clk2 6分频
begin if(~clr)
begin count<=0;clkout<=1'b0; end
else if(count==5)//改变count的值可实现不同模的分频
begin count<=0;clkout<=1'b1; end
else begin count<=count+1;clkout<=1'b0;end
end
endmodule
当然仿真波形比较的简单,只给出功能仿真波形,从波形图中很容易的可以看出是5.5分频,若要改成其他的N.5分频只需将代码中count的赋值就可以了。
小数分频:在实际应用中,还会遇到小数分频。总结实现小数分频可以采用两种方法,方法一是:用数字锁相环实现,先利用锁相环电路将输入时钟倍频,然后再利用分频器对新产生的高频信号进行分频得到需要的时钟频率。比如要实现5.7分频,可以先将输入的时钟10倍频,然后再将倍频后的时钟57分频,这样就可以得到精确的5.7的小数分频。方法二是先设计两个不同分频比的整数分频器,然后通过控制两种分频比出现不同次数来获得所需要的小数分频值来实现小数分频。分频比可以表示为N=M/P,其中N表示分频比,M表示分频器输入脉冲数,P表示分频器输出脉冲数。当N为小数分频比时,又可以表示为N=K+10-nX,式中K,n和X都为正整数,n表示为小数的位数。由以上两式可得M=( K+10-nX)P,令P=10n,有M=10nk+X,即在进行10nK分频时多输入X个脉冲。下面给出8.1分频电路的代码
module rxs(clk_in,rst,clk_out);//8.1小数分频(8×9+9×1)/(9+1)
input clk_in,rst;
output clk_out;
reg clk_out;
reg [3:0] cnt1,cnt2;
always @(posedge clk_in or posedge rst)
begin if(rst) begin cnt1<=0;cnt2<=0;clk_out<=0;end//复位清零
else if(cnt1<9) //9次8分频
begin if(cnt2<7) begin cnt2<=cnt2+1;clk_out<=0;end
else begin cnt2<=0;cnt1<=cnt1+1;clk_out<=1;end
end
else begin //1次9分频
if(cnt2<8) begin cnt2<=cnt2+1;clk_out<=0;end
else begin cnt2<=0;cnt1<=0;clk_out<=1;end
end
end
仿真波形和上面的分频波形差不多,到此为止所有的分频电路都可以实现了,上面的代码只给出了简单的几个分频,如果要进行其他的分频的话改变代码中的计数变量的值即可。
展开阅读全文