一、实验目的与要求
使用Verilog编程实现小数分频,输入时钟信号频率为50MHz,先从50MHz经小数分频得到42.3MHz的时钟信号,进而从42.3MHz时钟分频得到1Hz、2Hz、3Hz、4Hz、5Hz、6Hz、7Hz、8Hz、9Hz、10Hz等10个时钟频率,并将分频后的信号用数码管或显示屏实时显示出来。
二、实验内容
<1>实验原理阐述
注意:利用本例删除信号的方法得到的输出信号波形不满足占空比为50%
小数分频是通过可变分频和多次平均的方法来实现。输入时钟信号频率为f0,期望得到的频率为f1,则其分频比X=(f0/f1),其中X>1,假设M<X<M+1,M为整数,则有X=M+(N2 / (N1+N2) ),其中N1和N2为整数。当N1和N2取不同的正整数时就可以实现小数分频。
利用脉冲删除电路,有规律的删除时钟源中的一些脉冲,从而实现平均意义上的小数分频。在硬件电路的设计过程中,利用脉冲删除电路,不会出现竞争冒险和毛刺的问题,而且可以很容易地用硬件实现任意小数分频。令Q=N1+N2,P=M*(N1+N2)+N2,则X=P/Q,其中P、Q均为整数。当输入时钟源每输入P个脉冲,利用脉冲删除电路从这P个脉冲中按照一定的规律删除P-Q个脉冲,输出Q个脉冲,便实现了平均意义上的X分频。
具体设计思路如下:设置一个计数器,令其初始值为0,在每一个inclk的上升沿,计数器加上Q,若计数器中的值小于P,则发出删除一个脉冲的信号delete,置delete为高电平;若其值大于P,则将计数器的值减去P,并将delete置为低电平,不发出删除信号的脉冲。比如,从50MHz的时钟源得到42.3MHz的时钟信号,则可以令P=26,Q=22,它的工作过程见表1。
表1
三:实验代码
<1>端口定义
input rst,clk50m;
input [3:0] sel;
output reg clk423m;
output reg clk_16m;
output reg clk_ry;
reg delete;
reg [19:0]temp;
integer count,cnt,delete1,count3,count1;
reg [3:0] cnt1,cnt2,cnt3;
reg clk39m;
<2>42.3MHZ分频
1:频率计算:
f=N/(t*10^-12)=5/(120000*10^-12)=41.7MHZ
如果有表一,且觉得计算P、Q值比较麻烦的读者也可以采取直接删除特定的序号的信号脉冲的方法
//42.3MHZ分频
always@(posedge clk50m or posedge rst)
begin
if(rst==1)
begin
count=0;
delete=1'b0;//初始化计数器的值
end
else
begin
count=count+22;
if(count>=26)
begin
count=count-26;
delete=1'b0;//不删除脉冲
end
else
delete=1'b1;//删除脉冲
end
end
always@(delete)//根据delete的值判断是否删除脉冲
begin
if(delete==1'b1)
clk423m=1'b1;
else
clk423m=clk50m;
end
2:仿真波形
<3>将42.3MHZ信号分频得到1.6MHZ信号
1:代码展示
/1.6MHZ分频
always@(posedge clk423m or posedge rst) //实现1.6MHZ分频
begin
if(rst)
begin
count1=0;delete1=1'b0;
end
else
begin
count1=count1+390;
if(count1>=423)
begin
count1=count1-423;
delete1=1'b0; //不删除脉冲
end
else
delete1=1'b1; //删除1个脉冲
end
end
always@(delete1)
begin
if(delete1==1'b1)
clk39m=1'b1;
else
clk39m=clk423m;
end
always@(posedge clk39m or posedge rst)
begin
if(rst==1)
begin
clk_16m <= 0;count3=0;
end
else if(count3==9)
begin
clk_16m <= ~clk_16m;
count3 <= 0;
end
else
begin
count3 <= count3 + 1;
end
end
2:实物波形效果展示
注:输出为1.66MHZ方波,波形失真可能是因为高低电平翻转时计数值过大,持续时间过长导致;
<4>将1.6MHZ分频得到1~10HZ信号
//1-10HZ任意分频 可调
always@(posedge clk_16m or posedge rst)
begin
if(rst==1)
begin
clk_ry <= 0;
end
else if(cnt==1048576)
begin
clk_ry <= ~clk_ry;
cnt <= temp;
end
else
begin
cnt <= cnt + 1;
end
end
<5>按键调控分频结果(1~10HZ)
1:代码展示
always @ (sel)
begin
case(sel)
4'b0001:temp <= 298576;
4'b0010:temp <= 673576;
4'b0011:temp <= 798576;
4'b0100:temp <= 816076;
4'b0101:temp <= 898576;
4'b0110:temp <= 923576;
4'b0111:temp <= 941433;
4'b1000:temp <= 954826;
4'b1001:temp <= 965243;
4'b1010:temp <= 973576;
default:temp <= 1048574;
endcase
end
2:实物效果展示(以6HZ为例)
四:完整代码展示
module fengping_432(rst,clk50m,clk423m,clk_15m,clk_ry,sel);
input rst,clk50m;
input [3:0] sel;
output reg clk423m;
output reg clk_15m;
output reg clk_ry;
reg delete;
reg [19:0]temp;
integer count,cnt,delete1,count3,count1;
reg [3:0] cnt1,cnt2,cnt3;
reg clk39m;
//42.3MHZ分频
always@(posedge clk50m or posedge rst)
begin
if(rst==1)
begin
count=0;
delete=1'b0;//初始化计数器的值
end
else
begin
count=count+22;
if(count>=26)
begin
count=count-26;
delete=1'b0;//不删除脉冲
end
else
delete=1'b1;//删除脉冲
end
end
always@(delete)//根据delete的值判断是否删除脉冲
begin
if(delete==1'b1)
clk423m=1'b1;
else
clk423m=clk50m;
end
//1.5MHZ分频
always@(posedge clk423m or posedge rst) //实现1.5MHZ分频
begin
if(rst)
begin
count1=0;delete1=1'b0;
end
else
begin
count1=count1+390;
if(count1>=423)
begin
count1=count1-423;
delete1=1'b0; //不删除脉冲
end
else
delete1=1'b1; //删除1个脉冲
end
end
always@(delete1)
begin
if(delete1==1'b1)
clk39m=1'b1;
else
clk39m=clk423m;
end
always@(posedge clk39m or posedge rst)
begin
if(rst==1)
begin
clk_15m <= 0;count3=0;
end
else if(count3==9)
begin
clk_15m <= ~clk_15m;
count3 <= 0;
end
else
begin
count3 <= count3 + 1;
end
end
//1-10HZ任意分频 可调
always@(posedge clk_15m or posedge rst)
begin
if(rst==1)
begin
clk_ry <= 0;
end
else if(cnt==1048576)
begin
clk_ry <= ~clk_ry;
cnt <= temp;
end
else
begin
cnt <= cnt + 1;
end
end
//用来控制显示1-10HZ分频
always @ (sel)
begin
case(sel)
4'b0001:temp <= 298576;
4'b0010:temp <= 673576;
4'b0011:temp <= 798576;
4'b0100:temp <= 816076;
4'b0101:temp <= 898576;
4'b0110:temp <= 923576;
4'b0111:temp <= 941433;
4'b1000:temp <= 954826;
4'b1001:temp <= 965243;
4'b1010:temp <= 973576;
default:temp <= 1048574;
endcase
end
endmodule