我是靠谱客的博主 调皮信封,这篇文章主要介绍NO.1 基于verilogHDL的时钟分频与任意占空比调节基于verilogHDL的时钟分频与任意占空比调节,现在分享给大家,希望可以做个参考。

基于verilogHDL的时钟分频与任意占空比调节

学生,小白,刚开始了解FPGA,想要深入学习verilog这一硬件描述语言。
就从我学到的东西开始谈起吧。
我们在做fpga项目绝大部分要用到分频计数器及其占空比的调节,可以说是必备的技能。

时钟分频(偶数)

我们所写的程序将下载烧录到basys2FPGA开发板上,而开发板spartan-3E的时钟频率为50MHZ(周期为20ns),而我们在做譬如流水灯等实验时,需要观察LED灯的亮灭需要将其频率调至1HZ左右,即每一秒输出时钟沿跳变一次。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

测试激励:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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后,输出时钟翻转

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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分频不好观察,所以采用50M/50,即50个时钟周期翻转一次

与1HZ分频相比,1MHZ分频的区别就是计数器计数的不同,记满50个clk_in的上升沿,clk_out翻转。我感觉,这就是实现任意偶数分频的关键。(奇数分频还没了解,以后补充)。

占空比调节

下面大概了解一下占空比。占空比就是高电平所占周期的比率,如占空比为0.5即高电平持续时间占整个周期的二分之一。
显而易见,我们上面的分频输出时钟都是占空比为0.5,怎样才能调节才能使占空比改变。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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

测试激励:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(101)

评论列表共有 0 条评论

立即
投稿
返回
顶部