概述
基于verilogHDL的时钟分频与任意占空比调节
学生,小白,刚开始了解FPGA,想要深入学习verilog这一硬件描述语言。
就从我学到的东西开始谈起吧。
我们在做fpga项目绝大部分要用到分频计数器及其占空比的调节,可以说是必备的技能。
时钟分频(偶数)
我们所写的程序将下载烧录到basys2FPGA开发板上,而开发板spartan-3E的时钟频率为50MHZ(周期为20ns),而我们在做譬如流水灯等实验时,需要观察LED灯的亮灭需要将其频率调至1HZ左右,即每一秒输出时钟沿跳变一次。
module div(clk_in,clk_out,rst);
input clk_in; //输入时钟,频率为50Mhz
input rst; //复位信号,低电平有效
output reg clk_out; //输出时钟信号
reg [25:0]cn; //模25计数器
always@(posedge clk_in or negedge rst)begin
if(~rst)
begin
cn <= 0;
clk_out <= 0;
end
else if(cn == 24999999) //计数器记到24_999_999,即2500个clk_in上升沿后,输出波形翻转
begin
cn <= 0;
clk_out <= ~clk_out;
end
else
cn <= cn + 1;
end
测试激励:
module tb_div;
// Inputs
reg clk_in;
reg rst;
// Outputs
wire clk_out;
// Instantiate the Unit Under Test (UUT)
div uut (
.clk_in(clk_in),
.clk_out(clk_out),
.rst(rst)
);
always #10 clk_in = ~clk_in; //每10ns输入时钟翻转一次,且正好符合时钟频率的要求
initial begin
// Initialize Inputs
clk_in = 0;
rst = 0;
// Wait 100 ns for global reset to finish
#100;
rst = 1;
// Add stimulus here
end
endmodule
但是我第一次看仿真波形时,输入时钟clk_in走到100ns就不往后走了,所以就把上面一个小框框里的1.00us改成了1s,就看到了一秒时候输出时钟波形的跳转。
将其改为1s,得到下面能看到跳转的波形:
另一种分频,采用50M/50,即50个时钟周期翻转一次。一个时钟周期20ns,1000ns后,输出时钟翻转
module div(clk_in,clk_out,rst);
input clk_in;
input rst;
output reg clk_out;
reg [25:0]cn;
always@(posedge clk_in or negedge rst)begin
if(~rst)
begin
cn <= 0;
clk_out <= 0;
end
else if(cn == 49)
begin
cn <= 0;
clk_out <= ~clk_out;
end
else
cn <= cn + 1;
end
endmodule
其波形:
与1HZ分频相比,1MHZ分频的区别就是计数器计数的不同,记满50个clk_in的上升沿,clk_out翻转。我感觉,这就是实现任意偶数分频的关键。(奇数分频还没了解,以后补充)。
占空比调节
下面大概了解一下占空比。占空比就是高电平所占周期的比率,如占空比为0.5即高电平持续时间占整个周期的二分之一。
显而易见,我们上面的分频输出时钟都是占空比为0.5,怎样才能调节才能使占空比改变。
module fpzkb(clk,m,n,out);
input clk;
input [13:0] m; //占空比调节,设占空比为0.8,占空比为m/n,m=4000
input [13:0] n; //n分频,输出频率为50M/n,设n=5000,输出频率为10KHZ
output reg out;
parameter bitsize = 14;
reg [bitsize:0] cn ; //以5000分频为例
always@(posedge clk)
begin
if(m==0) //占空比为0,输出时钟总为0
out <= 0;
else
begin
if(m>=n) //占空比大于1
out <= 1; //输出时钟总为1
else
begin
if(cn<(m-1))
out <= 1;
else
out <= 0; //cn小于m-1时,输出高电平,否则输出低电平
begin //这里的begin很奇怪,不知道是谁的begin啊
if(cn<(n-1))
cn <= cn + 1;
else
begin
out <= ~out; //计数器记到n-1时,输出时钟翻转
cn <= 0;
end
end
end
end
end
endmodule
测试激励:
module tb_fpzkb;
// Inputs
reg clk;
reg [13:0] m;
reg [13:0] n;
// Outputs
wire out;
// Instantiate the Unit Under Test (UUT)
fpzkb uut (
.clk(clk),
.m(m),
.n(n),
.out(out)
);
always #10 clk = ~clk;
initial begin
// Initialize Inputs
clk = 0;
m = 4000;
n = 5000;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
详细解释见注释
波形图如下,可以看出,一个输出时钟周期为100us即1/10kHZ秒,占空比为80%。
占空比调节的代码里有一个begin,不知道是谁的,但是仿真没问题,可能是没见过这种写法,以后会看书的时候会留神。
注:仿真工具我用的是ISE自带的;
仿真的最后要写仿真多少秒停止,不然仿真会一直进行,可以设置一个比较大的时间,如#1000 $stop;(学长教的)
如果else下面的话过两句,就要用begin和end;
奇数分频等学懂了写;
代码风格非常一般,可以说乱,加油改进。
最后
以上就是调皮信封为你收集整理的NO.1 基于verilogHDL的时钟分频与任意占空比调节基于verilogHDL的时钟分频与任意占空比调节的全部内容,希望文章能够帮你解决NO.1 基于verilogHDL的时钟分频与任意占空比调节基于verilogHDL的时钟分频与任意占空比调节所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复